diff options
author | roncain <roncain@microsoft.com> | 2012-04-02 23:05:33 +0400 |
---|---|---|
committer | roncain <roncain@microsoft.com> | 2012-04-03 18:12:23 +0400 |
commit | 06f52b894414a3581dc424884c02c4d666ae8a07 (patch) | |
tree | 15ca2c3e94b5b7a7af466d5c627d440c04c64a85 /src | |
parent | f351672299a19e7571cb35ba24914e526bc181e1 (diff) |
DevDiv 388456 -- WebHost should not use Transfer-Encoding chunked when content length is known
Diffstat (limited to 'src')
-rw-r--r-- | src/System.Web.Http.WebHost/HttpControllerHandler.cs | 33 |
1 files changed, 20 insertions, 13 deletions
diff --git a/src/System.Web.Http.WebHost/HttpControllerHandler.cs b/src/System.Web.Http.WebHost/HttpControllerHandler.cs index b6b47c71..3e00b2f5 100644 --- a/src/System.Web.Http.WebHost/HttpControllerHandler.cs +++ b/src/System.Web.Http.WebHost/HttpControllerHandler.cs @@ -278,12 +278,19 @@ namespace System.Web.Http.WebHost if (response.Content != null) { - CopyHeaders(response.Content.Headers, httpContextBase); - - // Select output buffering by the kind of content + // Select output buffering based on the kind of HttpContent. + // This is done before CopyHeaders because the ContentLength + // property getter will evaluate the content length and set + // the Content-Length header if it has not already been set. + // Doing this before CopyHeaders ensures the headers contain a + // valid Content-Length before they are copied to HttpContextBase. + // Unless HttpContextBase headers contain a positive Content-Length, + // the Transfer-Encoding for streamed output will be chunked. isBuffered = IsOutputBufferingNecessary(response.Content); httpResponseBase.BufferOutput = isBuffered; + CopyHeaders(response.Content.Headers, httpContextBase); + responseTask = response.Content.CopyToAsync(httpResponseBase.OutputStream); } else @@ -328,24 +335,24 @@ namespace System.Web.Http.WebHost }); } - private static bool IsOutputBufferingNecessary(HttpContent httpContent) + /// <summary> + /// Determines whether the given <see cref="HttpContent"/> should use a buffered response. + /// </summary> + /// <param name="httpContent">The <see cref="HttpContent"/> of the response.</param> + /// <returns>A value of <c>true</c> indicates buffering should be used, otherwise a streamed response should be used.</returns> + internal static bool IsOutputBufferingNecessary(HttpContent httpContent) { - // Never buffer StreamContent. Either it's already buffered or - // is of indeterminate length. Neither calls for us to buffer. - if (httpContent == null || httpContent is StreamContent) - { - return false; - } + Contract.Assert(httpContent != null); - // Any content that knows its ContentLength is assumed to have - // buffered it already. + // Any HttpContent that knows its length is presumably already buffered internally. long? contentLength = httpContent.Headers.ContentLength; if (contentLength.HasValue && contentLength.Value >= 0) { return false; } - return true; + // Content length is null or -1 (meaning not known). Buffer any HttpContent except StreamContent. + return !(httpContent is StreamContent); } [SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope", Justification = "Caller becomes owner")] |