Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Set "default" 'Content-Type' header if none is provided #1032

Closed
jamespfluger-ava opened this issue Mar 1, 2024 · 3 comments
Closed

Set "default" 'Content-Type' header if none is provided #1032

jamespfluger-ava opened this issue Mar 1, 2024 · 3 comments

Comments

@jamespfluger-ava
Copy link

Problem

SoapCore currently throws an exception if no Content-Type header is provided. This can happen because v1.1.0.45 of this line in
v1.1.0.45/src/SoapCore/MessageEncoder/SoapMessageEncoderDefaults.cs within the ContentTypeToEncoding method:

var charSet = MediaTypeHeaderValue.Parse(contentType).CharSet;

Previous Behavior

In v1.0.0 this did not happen because the encodings were acquired using a different method that did not use the System.Net.Http.Headers namespace and the MediaTypeHeaderValue parser

v1.0.0/src/SoapCore/MessageEncoder/SoapMessageEncoderDefaults.cs

Easy Way Out

It's easy to say "make sure incoming requests have a content type, but for legacy systems this isn't always possible. If you run an external SOAP service, you may get requests that don't send this header. In order to preserve the existing behavior that 1.0.0 had (yes, some systems haven't upgraded!)

Proposed Solution

Thus, I propose

  1. Adding a default Content-Type header to ensure a value can be parsed
  2. Using MediaTypeHeaderValue.TryParse(...) instead of the regular Parse and add logic accordingly
  3. Otherwise, have a try/catch block? I dunno, but throwing an error when null is provided isn't ideal behavior
@andersjonsson
Copy link
Collaborator

Yes, that should be a TryParse.
The configured WriteEncoding will be used as a fallback if this method returns null, so there is already logic for that.

With that said it can be necessary to add a custom middleware to set Content-Type anyways.
In my legacy service a few clients sent SOAP1.2 envelopes without Content-Type set and that fails.

I solved that with a regular asp.net middleware (affects performance, but in my case it's much more important to stay backwards compatible than to maximize performance.

const string Soap12NS = "http://www.w3.org/2003/05/soap-envelope";

app.Use(async (context, next) =>
{
	if (context.Request.Method == "POST")
	{
		//This line allows us to set the reader for the request back at the beginning of its stream.
		context.Request.EnableBuffering();

		//We convert the byte[] into a string using UTF8 encoding...
		var bodyAsText = Encoding.UTF8.GetString(await context.Request.Body.ReadFullyAsync());

		try
		{
			var xdoc = XDocument.Parse(bodyAsText);

			bodyAsText = xdoc.ToString();
			context.Request.Body = new MemoryStream(Encoding.UTF8.GetBytes(bodyAsText));

			//Logging!
			await SoapMessageLog.WriteLog(context, bodyAsText);

			//Upgrade Content-Type if Envelope is Soap1.2
			if (context.Request.Headers["Content-Type"] != "application/soap+xml")
			{
				var envelope = xdoc.Descendants().FirstOrDefault(x => x.Name.LocalName == "Envelope");
				if (envelope != null && envelope.Name.ToString().Contains(Soap12NS))
				{
					context.Request.Headers["Content-Type"] = "application/soap+xml";
				}
			}

		}
		catch
		{ }

		//..and finally, assign the read body back to the request body, which is allowed because of EnableRewind()
		context.Request.Body.Position = 0;
	}

	await next();
}

);

@andersjonsson
Copy link
Collaborator

Should be fixed in #1033

@jamespfluger-ava
Copy link
Author

Ha, the use case I have is not a standard SoapCore use case, so I did the "dumb" workaround by simply using request.ContentType ?? "application/xm; charset=utf-8" using ReadMessageAsync within SoapMessageEncoder

Appreciate the rapid change!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants