Specify Content-Length for buffered responses (#9699)

This commit is contained in:
Pranav K 2019-04-24 09:57:53 -07:00 committed by GitHub
parent 0c11bb3194
commit 9ac2f52b22
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 31 additions and 8 deletions

View File

@ -69,7 +69,7 @@ namespace Microsoft.AspNetCore.WebUtilities
public override bool CanWrite => true;
/// <inheritdoc />
public override long Length => throw new NotSupportedException();
public override long Length => PagedByteBuffer.Length + (FileStream?.Length ?? 0);
/// <inheritdoc />
public override long Position
@ -78,8 +78,6 @@ namespace Microsoft.AspNetCore.WebUtilities
set => throw new NotSupportedException();
}
internal long BufferedLength => PagedByteBuffer.Length + (FileStream?.Length ?? 0);
internal PagedByteBuffer PagedByteBuffer { get; }
internal FileStream FileStream { get; private set; }
@ -103,7 +101,7 @@ namespace Microsoft.AspNetCore.WebUtilities
ThrowArgumentException(buffer, offset, count);
ThrowIfDisposed();
if (_bufferLimit.HasValue && _bufferLimit - BufferedLength < count)
if (_bufferLimit.HasValue && _bufferLimit - Length < count)
{
Dispose();
throw new IOException("Buffer limit exceeded.");
@ -136,7 +134,7 @@ namespace Microsoft.AspNetCore.WebUtilities
ThrowArgumentException(buffer, offset, count);
ThrowIfDisposed();
if (_bufferLimit.HasValue && _bufferLimit - BufferedLength < count)
if (_bufferLimit.HasValue && _bufferLimit - Length < count)
{
Dispose();
throw new IOException("Buffer limit exceeded.");

View File

@ -31,6 +31,8 @@ namespace Microsoft.AspNetCore.WebUtilities
bufferingStream.Write(input, 0, input.Length);
// Assert
Assert.Equal(input.Length, bufferingStream.Length);
// We should have written content to memory
var pagedByteBuffer = bufferingStream.PagedByteBuffer;
Assert.Equal(input, ReadBufferedContent(pagedByteBuffer));
@ -53,6 +55,8 @@ namespace Microsoft.AspNetCore.WebUtilities
var pageBuffer = bufferingStream.PagedByteBuffer;
var fileStream = bufferingStream.FileStream;
Assert.Equal(input.Length, bufferingStream.Length);
// File should have been created.
Assert.Null(fileStream);
@ -238,6 +242,8 @@ namespace Microsoft.AspNetCore.WebUtilities
Assert.NotNull(fileStream);
var fileBytes = ReadFileContent(fileStream);
Assert.Equal(input.Length, bufferingStream.Length);
Assert.Equal(new byte[] { 1, 2, 3, 4, 5, }, fileBytes);
Assert.Equal(new byte[] { 6, 7 }, ReadBufferedContent(pageBuffer));
}
@ -344,6 +350,7 @@ namespace Microsoft.AspNetCore.WebUtilities
// Assert
Assert.Equal(input, memoryStream.ToArray());
Assert.Equal(0, bufferingStream.Length);
}
[Fact]
@ -360,6 +367,7 @@ namespace Microsoft.AspNetCore.WebUtilities
// Assert
Assert.Equal(input, memoryStream.ToArray());
Assert.Equal(0, bufferingStream.Length);
}
public void Dispose()

View File

@ -101,7 +101,7 @@ namespace Microsoft.AspNetCore.Mvc.Formatters
public XmlWriterSettings WriterSettings { get; }
/// <summary>
/// Gets or sets the <see cref="DataContractSerializerSettings"/> used to configure the
/// Gets or sets the <see cref="DataContractSerializerSettings"/> used to configure the
/// <see cref="DataContractSerializer"/>.
/// </summary>
public DataContractSerializerSettings SerializerSettings
@ -284,6 +284,7 @@ namespace Microsoft.AspNetCore.Mvc.Formatters
if (fileBufferingWriteStream != null)
{
response.ContentLength = fileBufferingWriteStream.Length;
await fileBufferingWriteStream.DrainBufferAsync(response.Body);
}
}

View File

@ -260,6 +260,7 @@ namespace Microsoft.AspNetCore.Mvc.Formatters
if (fileBufferingWriteStream != null)
{
response.ContentLength = fileBufferingWriteStream.Length;
await fileBufferingWriteStream.DrainBufferAsync(response.Body);
}
}

View File

@ -94,7 +94,7 @@ namespace Microsoft.AspNetCore.Mvc.Formatters
/// <summary>
/// Called during serialization to create the <see cref="JsonSerializer"/>.The formatter context
/// that is passed gives an ability to create serializer specific to the context.
/// that is passed gives an ability to create serializer specific to the context.
/// </summary>
/// <returns>The <see cref="JsonSerializer"/> used during serialization and deserialization.</returns>
protected virtual JsonSerializer CreateJsonSerializer()
@ -109,7 +109,7 @@ namespace Microsoft.AspNetCore.Mvc.Formatters
/// <summary>
/// Called during serialization to create the <see cref="JsonSerializer"/>.The formatter context
/// that is passed gives an ability to create serializer specific to the context.
/// that is passed gives an ability to create serializer specific to the context.
/// </summary>
/// <param name="context">A context object for <see cref="IOutputFormatter.WriteAsync(OutputFormatterWriteContext)"/>.</param>
/// <returns>The <see cref="JsonSerializer"/> used during serialization and deserialization.</returns>
@ -154,6 +154,7 @@ namespace Microsoft.AspNetCore.Mvc.Formatters
if (fileBufferingWriteStream != null)
{
response.ContentLength = fileBufferingWriteStream.Length;
await fileBufferingWriteStream.DrainBufferAsync(response.Body);
}
}

View File

@ -4,6 +4,7 @@
using System.Net;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc.NewtonsoftJson;
using FormatterWebSite.Controllers;
using Newtonsoft.Json;
using Xunit;
@ -41,5 +42,16 @@ namespace Microsoft.AspNetCore.Mvc.FunctionalTests
var actualBody = await response.Content.ReadAsStringAsync();
Assert.Equal(expectedBody, actualBody);
}
[Fact]
public async Task JsonOutputFormatter_SetsContentLength()
{
// Act
var response = await Client.GetAsync($"/JsonOutputFormatter/{nameof(JsonOutputFormatterController.SimpleModelResult)}");
// Assert
await response.AssertStatusCodeAsync(HttpStatusCode.OK);
Assert.Equal(50, response.Content.Headers.ContentLength);
}
}
}

View File

@ -41,6 +41,7 @@ namespace Microsoft.AspNetCore.Mvc.FunctionalTests
"xmlns=\"http://schemas.datacontract.org/2004/07/FormatterWebSite\">" +
"<SampleInt>10</SampleInt></DummyClass>",
await response.Content.ReadAsStringAsync());
Assert.Equal(167, response.Content.Headers.ContentLength);
}
[Fact]
@ -61,6 +62,7 @@ namespace Microsoft.AspNetCore.Mvc.FunctionalTests
"<DummyClass xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" " +
"xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"><SampleInt>10</SampleInt></DummyClass>",
await response.Content.ReadAsStringAsync());
Assert.Equal(149, response.Content.Headers.ContentLength);
}
[ConditionalFact]