From 3fb33119eec2550a9434e8761ad4c744bd528370 Mon Sep 17 00:00:00 2001 From: Stephen Halter Date: Fri, 31 Jul 2015 12:38:35 -0700 Subject: [PATCH] Initial non-optimized support for automatically chunking responses --- .../Http/Frame.cs | 65 +++++++++++++++++-- 1 file changed, 61 insertions(+), 4 deletions(-) diff --git a/src/Microsoft.AspNet.Server.Kestrel/Http/Frame.cs b/src/Microsoft.AspNet.Server.Kestrel/Http/Frame.cs index 7dc2603bc3..bb236f6846 100644 --- a/src/Microsoft.AspNet.Server.Kestrel/Http/Frame.cs +++ b/src/Microsoft.AspNet.Server.Kestrel/Http/Frame.cs @@ -27,6 +27,7 @@ namespace Microsoft.AspNet.Server.Kestrel.Http Mode _mode; private bool _responseStarted; private bool _keepAlive; + private bool _autoChunk; private readonly FrameRequestHeaders _requestHeaders = new FrameRequestHeaders(); private readonly FrameResponseHeaders _responseHeaders = new FrameResponseHeaders(); @@ -253,6 +254,12 @@ namespace Microsoft.AspNet.Server.Kestrel.Http { FireOnStarting(); } + + if (_autoChunk) + { + WriteChunkPrefix(numOctets: 0); + WriteChunkSuffix(); + } } catch (Exception ex) { @@ -265,11 +272,53 @@ namespace Microsoft.AspNet.Server.Kestrel.Http } } - public void Write(ArraySegment data, Action callback, object state) { 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 _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 options, Func 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") {