Skip to content
This repository was archived by the owner on Mar 19, 2019. It is now read-only.

Cache the ContentLength header value #296

Merged
merged 1 commit into from
Jan 24, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/Microsoft.AspNetCore.Server.HttpSys/FeatureContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ internal FeatureContext(RequestContext requestContext, bool enableResponseCachin
_enableResponseCaching = enableResponseCaching;

// Pre-initialize any fields that are not lazy at the lower level.
_requestHeaders = new HeaderDictionary(Request.Headers);
_requestHeaders = Request.Headers;
_httpMethod = Request.Method;
_path = Request.Path;
_pathBase = Request.PathBase;
Expand All @@ -82,7 +82,7 @@ internal FeatureContext(RequestContext requestContext, bool enableResponseCachin
_user = _requestContext.User;

_responseStream = new ResponseStream(requestContext.Response.Body, OnStart);
_responseHeaders = new HeaderDictionary(Response.Headers);
_responseHeaders = Response.Headers;
}

internal IFeatureCollection Features => _features;
Expand Down
204 changes: 0 additions & 204 deletions src/Microsoft.AspNetCore.Server.HttpSys/HeaderDictionary.cs

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,17 @@
using System;
using System.Collections;
using System.Collections.Generic;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Primitives;
using Microsoft.Net.Http.Headers;

namespace Microsoft.AspNetCore.Server.HttpSys
{
internal class HeaderCollection : IDictionary<string, StringValues>
internal class HeaderCollection : IHeaderDictionary
{
private long? _contentLength;
private StringValues _contentLengthText;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Curious why this is kept as a StringValues? We will only store it when its count is 1 so why not store the string instead?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We check it against the raw header StringValues and this avoids the extra conversions


public HeaderCollection()
: this(new Dictionary<string, StringValues>(4, StringComparer.OrdinalIgnoreCase))
{
Expand Down Expand Up @@ -75,6 +80,52 @@ public ICollection<StringValues> Values
get { return Store.Values; }
}

public long? ContentLength
{
get
{
long value;
var rawValue = this[HttpKnownHeaderNames.ContentLength];

if (_contentLengthText.Equals(rawValue))
{
return _contentLength;
}

if (rawValue.Count == 1 &&
!string.IsNullOrWhiteSpace(rawValue[0]) &&
HeaderUtilities.TryParseInt64(new StringSegment(rawValue[0]).Trim(), out value))
{
_contentLengthText = rawValue;
_contentLength = value;
return value;
}

return null;
}
set
{
ThrowIfReadOnly();

if (value.HasValue)
{
if (value.Value < 0)
{
throw new ArgumentOutOfRangeException("value", value.Value, "Cannot be negative.");
}
_contentLengthText = HeaderUtilities.FormatInt64(value.Value);
this[HttpKnownHeaderNames.ContentLength] = _contentLengthText;
_contentLength = value;
}
else
{
Remove(HttpKnownHeaderNames.ContentLength);
_contentLengthText = StringValues.Empty;
_contentLength = null;
}
}
}

public void Add(KeyValuePair<string, StringValues> item)
{
ThrowIfReadOnly();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -147,48 +147,8 @@ internal long ExpectedBodyLength
// Header accessors
public long? ContentLength
{
get
{
string contentLengthString = Headers[HttpKnownHeaderNames.ContentLength];
long contentLength;
if (!string.IsNullOrWhiteSpace(contentLengthString))
{
contentLengthString = contentLengthString.Trim();
if (string.Equals(Constants.Zero, contentLengthString, StringComparison.Ordinal))
{
return 0;
}
else if (long.TryParse(contentLengthString, NumberStyles.None, CultureInfo.InvariantCulture.NumberFormat, out contentLength))
{
return contentLength;
}
}
return null;
}
set
{
CheckResponseStarted();
if (!value.HasValue)
{
Headers.Remove(HttpKnownHeaderNames.ContentLength);
}
else
{
if (value.Value < 0)
{
throw new ArgumentOutOfRangeException("value", value.Value, "Cannot be negative.");
}

if (value.Value == 0)
{
Headers[HttpKnownHeaderNames.ContentLength] = Constants.Zero;
}
else
{
Headers[HttpKnownHeaderNames.ContentLength] = value.Value.ToString(CultureInfo.InvariantCulture);
}
}
}
get { return Headers.ContentLength; }
set { Headers.ContentLength = value; }
}

/// <summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ public async Task Request_FieldsCanBeSet_Set()
Assert.Equal("TEST", requestInfo.Method);
requestInfo.Body = new MemoryStream();
Assert.IsType<MemoryStream>(requestInfo.Body);
var customHeaders = new HeaderDictionary(new HeaderCollection());
var customHeaders = new HeaderCollection();
requestInfo.Headers = customHeaders;
Assert.Same(customHeaders, requestInfo.Headers);
requestInfo.Scheme = "abcd";
Expand Down