Initial non-optimized support for automatically chunking responses

This commit is contained in:
Stephen Halter 2015-07-31 12:38:35 -07:00
parent 32c4f314b6
commit 3fb33119ee
1 changed files with 61 additions and 4 deletions

View File

@ -27,6 +27,7 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
Mode _mode; Mode _mode;
private bool _responseStarted; private bool _responseStarted;
private bool _keepAlive; private bool _keepAlive;
private bool _autoChunk;
private readonly FrameRequestHeaders _requestHeaders = new FrameRequestHeaders(); private readonly FrameRequestHeaders _requestHeaders = new FrameRequestHeaders();
private readonly FrameResponseHeaders _responseHeaders = new FrameResponseHeaders(); private readonly FrameResponseHeaders _responseHeaders = new FrameResponseHeaders();
@ -253,6 +254,12 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
{ {
FireOnStarting(); FireOnStarting();
} }
if (_autoChunk)
{
WriteChunkPrefix(numOctets: 0);
WriteChunkSuffix();
}
} }
catch (Exception ex) catch (Exception ex)
{ {
@ -265,11 +272,53 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
} }
} }
public void Write(ArraySegment<byte> data, Action<Exception, object> callback, object state) public void Write(ArraySegment<byte> data, Action<Exception, object> callback, object state)
{ {
ProduceStart(immediate: false); ProduceStart(immediate: false);
SocketOutput.Write(data, callback, state);
if (_autoChunk)
{
WriteChunkPrefix(data.Count);
}
SocketOutput.Write(data, callback, state, immediate: !_autoChunk);
if (_autoChunk)
{
WriteChunkSuffix();
}
}
private void WriteChunkPrefix(int numOctets)
{
var numOctetBytes = CreateAsciiByteArraySegment(numOctets.ToString("x") + "\r\n");
SocketOutput.Write(numOctetBytes,
(error, _) =>
{
if (error != null)
{
Trace.WriteLine("WriteChunkPrefix" + error.ToString());
}
},
null,
immediate: false);
}
private static readonly ArraySegment<byte> _endChunkBytes = CreateAsciiByteArraySegment("\r\n");
private void WriteChunkSuffix()
{
SocketOutput.Write(_endChunkBytes,
(error, _) =>
{
if (error != null)
{
Trace.WriteLine("WriteChunkSuffix" + error.ToString());
}
},
null,
immediate: true);
} }
public void Upgrade(IDictionary<string, object> options, Func<object, Task> callback) public void Upgrade(IDictionary<string, object> options, Func<object, Task> callback)
@ -421,9 +470,17 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
} }
} }
if (hasTransferEncoding == false && hasContentLength == false) if (_keepAlive && !hasTransferEncoding && !hasContentLength)
{ {
_keepAlive = false; if (HttpVersion == "HTTP/1.1")
{
_autoChunk = true;
writer.Write("Transfer-Encoding: chunked\r\n");
}
else
{
_keepAlive = false;
}
} }
if (_keepAlive == false && hasConnection == false && HttpVersion == "HTTP/1.1") if (_keepAlive == false && hasConnection == false && HttpVersion == "HTTP/1.1")
{ {