Ignore zero length writes when automatically chunking responses
- Zero length writes would previously be interpreted as the end of response - Optimize writing the chunked response suffix - Add tests for automatic response chunking
This commit is contained in:
parent
3fb33119ee
commit
753d64660d
|
|
@ -257,8 +257,7 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
|
|||
|
||||
if (_autoChunk)
|
||||
{
|
||||
WriteChunkPrefix(numOctets: 0);
|
||||
WriteChunkSuffix();
|
||||
WriteChunkedResponseSuffix();
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
|
|
@ -278,6 +277,12 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
|
|||
|
||||
if (_autoChunk)
|
||||
{
|
||||
if (data.Count == 0)
|
||||
{
|
||||
callback(null, state);
|
||||
return;
|
||||
}
|
||||
|
||||
WriteChunkPrefix(data.Count);
|
||||
}
|
||||
|
||||
|
|
@ -306,6 +311,7 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
|
|||
}
|
||||
|
||||
private static readonly ArraySegment<byte> _endChunkBytes = CreateAsciiByteArraySegment("\r\n");
|
||||
private static readonly ArraySegment<byte> _endChunkedResponseBytes = CreateAsciiByteArraySegment("0\r\n\r\n");
|
||||
|
||||
private void WriteChunkSuffix()
|
||||
{
|
||||
|
|
@ -321,6 +327,20 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
|
|||
immediate: true);
|
||||
}
|
||||
|
||||
private void WriteChunkedResponseSuffix()
|
||||
{
|
||||
SocketOutput.Write(_endChunkedResponseBytes,
|
||||
(error, _) =>
|
||||
{
|
||||
if (error != null)
|
||||
{
|
||||
Trace.WriteLine("WriteChunkedResponseSuffix" + error.ToString());
|
||||
}
|
||||
},
|
||||
null,
|
||||
immediate: true);
|
||||
}
|
||||
|
||||
public void Upgrade(IDictionary<string, object> options, Func<object, Task> callback)
|
||||
{
|
||||
_keepAlive = false;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,75 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNet.Server.KestrelTests
|
||||
{
|
||||
public class ChunkedResponseTests
|
||||
{
|
||||
[Fact]
|
||||
public async Task ResponsesAreChunkedAutomatically()
|
||||
{
|
||||
using (var server = new TestServer(async frame =>
|
||||
{
|
||||
frame.ResponseHeaders.Clear();
|
||||
await frame.ResponseBody.WriteAsync(Encoding.ASCII.GetBytes("Hello "), 0, 6);
|
||||
await frame.ResponseBody.WriteAsync(Encoding.ASCII.GetBytes("World!"), 0, 6);
|
||||
}))
|
||||
{
|
||||
using (var connection = new TestConnection())
|
||||
{
|
||||
await connection.SendEnd(
|
||||
"GET / HTTP/1.1",
|
||||
"",
|
||||
"");
|
||||
await connection.ReceiveEnd(
|
||||
"HTTP/1.1 200 OK",
|
||||
"Transfer-Encoding: chunked",
|
||||
"",
|
||||
"6",
|
||||
"Hello ",
|
||||
"6",
|
||||
"World!",
|
||||
"0",
|
||||
"",
|
||||
"");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ZeroLengthWritesAreIgnored()
|
||||
{
|
||||
using (var server = new TestServer(async frame =>
|
||||
{
|
||||
frame.ResponseHeaders.Clear();
|
||||
await frame.ResponseBody.WriteAsync(Encoding.ASCII.GetBytes("Hello "), 0, 6);
|
||||
await frame.ResponseBody.WriteAsync(new byte[0], 0, 0);
|
||||
await frame.ResponseBody.WriteAsync(Encoding.ASCII.GetBytes("World!"), 0, 6);
|
||||
}))
|
||||
{
|
||||
using (var connection = new TestConnection())
|
||||
{
|
||||
await connection.SendEnd(
|
||||
"GET / HTTP/1.1",
|
||||
"",
|
||||
"");
|
||||
await connection.ReceiveEnd(
|
||||
"HTTP/1.1 200 OK",
|
||||
"Transfer-Encoding: chunked",
|
||||
"",
|
||||
"6",
|
||||
"Hello ",
|
||||
"6",
|
||||
"World!",
|
||||
"0",
|
||||
"",
|
||||
"");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue