Skip to content

Commit

Permalink
Do not use chunked transfer encoding on ASP.NET Core 2.1
Browse files Browse the repository at this point in the history
Setting the Content-Length header explicitly will disable chunked
transfer-encoding. However this was only done for one of the two
WriteMessageAsync methods in SoapMessageEncoder. I have changed the
other method to also set the Content-Length header.

To do this I have used a MemoryStream. The other implementation used
a StringWriter, which is not ideal, because it will convert to and from
different encodings. We only want to find out the length of the stream,
so a MemoryStream is faster and sufficient. Also changed the other
WriteMessageAsync implementation to use a MemoryStream and removed the
CustomStringWriter class.

Fixes DigDes#1015
  • Loading branch information
vidrenning committed Feb 9, 2024
1 parent 3ab2c90 commit ff90b2b
Show file tree
Hide file tree
Showing 4 changed files with 44 additions and 62 deletions.
2 changes: 1 addition & 1 deletion src/SoapCore.Tests/Wsdl/WsdlTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1169,7 +1169,7 @@ private async Task<string> GetWsdlFromMetaBodyWriter<T>(SoapSerializer serialize

using (var memoryStream = new MemoryStream())
{
await encoder.WriteMessageAsync(responseMessage, memoryStream, true);
await encoder.WriteMessageAsync(responseMessage, null, memoryStream, true);
memoryStream.Position = 0;

using (var streamReader = new StreamReader(memoryStream))
Expand Down
23 changes: 0 additions & 23 deletions src/SoapCore/CustomStringWriter.cs

This file was deleted.

77 changes: 41 additions & 36 deletions src/SoapCore/MessageEncoder/SoapMessageEncoder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -181,41 +181,36 @@ public virtual async Task WriteMessageAsync(Message message, HttpContext httpCon

ThrowIfMismatchedMessageVersion(message);

//Custom string writer with custom encoding support
using (var stringWriter = new CustomStringWriter(_writeEncoding))
using var memoryStream = new MemoryStream();
using (var xmlTextWriter = XmlWriter.Create(memoryStream, new XmlWriterSettings
{
using (var xmlTextWriter = XmlWriter.Create(stringWriter, new XmlWriterSettings
{
OmitXmlDeclaration = _optimizeWriteForUtf8 && _omitXmlDeclaration, //can only omit if utf-8
Indent = indentXml,
Encoding = _writeEncoding,
CloseOutput = true,
CheckCharacters = _checkXmlCharacters
}))
{
using var xmlWriter = XmlDictionaryWriter.CreateDictionaryWriter(xmlTextWriter);
message.WriteMessage(xmlWriter);
xmlWriter.WriteEndDocument();
xmlWriter.Flush();
}

var data = stringWriter.ToString();
var soapMessage = _writeEncoding.GetBytes(data);

//Set Content-length in Response
httpContext.Response.ContentLength = soapMessage.Length;
OmitXmlDeclaration = _optimizeWriteForUtf8 && _omitXmlDeclaration, //can only omit if utf-8
Indent = indentXml,
Encoding = _writeEncoding,
CloseOutput = false,
CheckCharacters = _checkXmlCharacters
}))
{
using var xmlWriter = XmlDictionaryWriter.CreateDictionaryWriter(xmlTextWriter);
message.WriteMessage(xmlWriter);
xmlWriter.WriteEndDocument();
xmlWriter.Flush();
}

if (_overwriteResponseContentType)
{
httpContext.Response.ContentType = ContentType;
}
//Set Content-length in Response
httpContext.Response.ContentLength = memoryStream.Length;

await pipeWriter.WriteAsync(soapMessage);
await pipeWriter.FlushAsync();
if (_overwriteResponseContentType)
{
httpContext.Response.ContentType = ContentType;
}

memoryStream.Seek(0, SeekOrigin.Begin);
await memoryStream.CopyToAsync(pipeWriter);
await pipeWriter.FlushAsync();
}

public virtual Task WriteMessageAsync(Message message, Stream stream, bool indentXml)
public virtual async Task WriteMessageAsync(Message message, HttpContext httpContext, Stream stream, bool indentXml)
{
if (message == null)
{
Expand All @@ -229,21 +224,31 @@ public virtual Task WriteMessageAsync(Message message, Stream stream, bool inden

ThrowIfMismatchedMessageVersion(message);

using var xmlTextWriter = XmlWriter.Create(stream, new XmlWriterSettings
using var memoryStream = new MemoryStream();
using (var xmlTextWriter = XmlWriter.Create(memoryStream, new XmlWriterSettings
{
OmitXmlDeclaration = _optimizeWriteForUtf8 && _omitXmlDeclaration, //can only omit if utf-8,
Indent = indentXml,
Encoding = _writeEncoding,
CloseOutput = false,
CheckCharacters = _checkXmlCharacters
});
}))
{
using var xmlWriter = XmlDictionaryWriter.CreateDictionaryWriter(xmlTextWriter);
message.WriteMessage(xmlWriter);
xmlWriter.WriteEndDocument();
xmlWriter.Flush();
}

using var xmlWriter = XmlDictionaryWriter.CreateDictionaryWriter(xmlTextWriter);
message.WriteMessage(xmlWriter);
xmlWriter.WriteEndDocument();
xmlWriter.Flush();
if (httpContext != null) // HttpContext is null in unit tests
{
// Set Content-Length in response. This will disable chunked transfer-encoding.
httpContext.Response.ContentLength = memoryStream.Length;
}

return Task.CompletedTask;
memoryStream.Seek(0, SeekOrigin.Begin);
await memoryStream.CopyToAsync(stream);
await stream.FlushAsync();
}

internal static string GetMediaType(MessageVersion version)
Expand Down
4 changes: 2 additions & 2 deletions src/SoapCore/SoapEndpointMiddleware.cs
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,7 @@ public async Task Invoke(HttpContext httpContext, IServiceProvider serviceProvid
#if !NETCOREAPP3_0_OR_GREATER
private static Task WriteMessageAsync(SoapMessageEncoder messageEncoder, Message responseMessage, HttpContext httpContext, bool indentXml)
{
return messageEncoder.WriteMessageAsync(responseMessage, httpContext.Response.Body, indentXml);
return messageEncoder.WriteMessageAsync(responseMessage, httpContext, httpContext.Response.Body, indentXml);
}
#else
private static Task WriteMessageAsync(SoapMessageEncoder messageEncoder, Message responseMessage, HttpContext httpContext, bool indentXml)
Expand Down Expand Up @@ -257,7 +257,7 @@ private async Task ProcessMeta(HttpContext httpContext, bool showDocumentation)
httpContext.Response.ContentType = "text/html;charset=UTF-8";

using var ms = new MemoryStream();
await messageEncoder.WriteMessageAsync(responseMessage, ms, _options.IndentWsdl);
await messageEncoder.WriteMessageAsync(responseMessage, httpContext, ms, _options.IndentWsdl);
ms.Position = 0;
using var sr = new StreamReader(ms);
var wsdl = await sr.ReadToEndAsync();
Expand Down

0 comments on commit ff90b2b

Please sign in to comment.