#167 Prevent duplicate Content-Length headers

This commit is contained in:
Chris R 2016-08-31 14:09:17 -07:00
parent 6522926c22
commit 88114568b9
3 changed files with 15 additions and 20 deletions

View File

@ -338,11 +338,6 @@ namespace Microsoft.Net.Http.Server
_responseState = ResponseState.Started; _responseState = ResponseState.Started;
var reasonPhrase = GetReasonPhrase(StatusCode); var reasonPhrase = GetReasonPhrase(StatusCode);
/*
if (m_BoundaryType==BoundaryType.Raw) {
use HTTP_SEND_RESPONSE_FLAG_RAW_HEADER;
}
*/
uint statusCode; uint statusCode;
uint bytesSent; uint bytesSent;
List<GCHandle> pinnedHeaders = SerializeHeaders(isOpaqueUpgrade); List<GCHandle> pinnedHeaders = SerializeHeaders(isOpaqueUpgrade);
@ -414,7 +409,7 @@ namespace Microsoft.Net.Http.Server
return statusCode; return statusCode;
} }
internal HttpApi.HTTP_FLAGS ComputeHeaders(bool endOfRequest = false) internal HttpApi.HTTP_FLAGS ComputeHeaders(long writeCount, bool endOfRequest = false)
{ {
// 401 // 401
if (StatusCode == (ushort)HttpStatusCode.Unauthorized) if (StatusCode == (ushort)HttpStatusCode.Unauthorized)
@ -456,6 +451,13 @@ namespace Microsoft.Net.Http.Server
_boundaryType = BoundaryType.ContentLength; _boundaryType = BoundaryType.ContentLength;
// ComputeLeftToWrite checks for HEAD requests when setting _leftToWrite // ComputeLeftToWrite checks for HEAD requests when setting _leftToWrite
_expectedBodyLength = responseContentLength.Value; _expectedBodyLength = responseContentLength.Value;
if (responseContentLength.Value == writeCount && !isHeadRequest)
{
// A single write with the whole content-length. Http.Sys will set the content-length for us in this scenario.
// If we don't remove it then range requests served from cache will have two.
// https://github.com/aspnet/WebListener/issues/167
ContentLength = null;
}
} }
else if (responseChunkedSet) else if (responseChunkedSet)
{ {
@ -495,7 +497,6 @@ namespace Microsoft.Net.Http.Server
flags = HttpApi.HTTP_FLAGS.HTTP_SEND_RESPONSE_FLAG_DISCONNECT; flags = HttpApi.HTTP_FLAGS.HTTP_SEND_RESPONSE_FLAG_DISCONNECT;
} }
Headers.IsReadOnly = true; // Prohibit further modifications.
return flags; return flags;
} }
@ -511,12 +512,7 @@ namespace Microsoft.Net.Http.Server
HttpApi.HTTP_RESPONSE_INFO[] knownHeaderInfo = null; HttpApi.HTTP_RESPONSE_INFO[] knownHeaderInfo = null;
List<GCHandle> pinnedHeaders; List<GCHandle> pinnedHeaders;
GCHandle gcHandle; GCHandle gcHandle;
/*
// here we would check for BoundaryType.Raw, in this case we wouldn't need to do anything
if (m_BoundaryType==BoundaryType.Raw) {
return null;
}
*/
if (Headers.Count == 0) if (Headers.Count == 0)
{ {
return null; return null;

View File

@ -137,7 +137,7 @@ namespace Microsoft.Net.Http.Server
} }
// Make sure all validation is performed before this computes the headers // Make sure all validation is performed before this computes the headers
var flags = ComputeLeftToWrite(endOfRequest); var flags = ComputeLeftToWrite(data.Count, endOfRequest);
if (!_inOpaqueMode && endOfRequest && _leftToWrite > 0) if (!_inOpaqueMode && endOfRequest && _leftToWrite > 0)
{ {
_requestContext.Abort(); _requestContext.Abort();
@ -315,7 +315,7 @@ namespace Microsoft.Net.Http.Server
} }
// Make sure all validation is performed before this computes the headers // Make sure all validation is performed before this computes the headers
var flags = ComputeLeftToWrite(); var flags = ComputeLeftToWrite(data.Count);
if (_leftToWrite != data.Count) if (_leftToWrite != data.Count)
{ {
flags |= HttpApi.HTTP_FLAGS.HTTP_SEND_RESPONSE_FLAG_MORE_DATA; flags |= HttpApi.HTTP_FLAGS.HTTP_SEND_RESPONSE_FLAG_MORE_DATA;
@ -438,12 +438,12 @@ namespace Microsoft.Net.Http.Server
_requestContext.Abort(); _requestContext.Abort();
} }
private HttpApi.HTTP_FLAGS ComputeLeftToWrite(bool endOfRequest = false) private HttpApi.HTTP_FLAGS ComputeLeftToWrite(long writeCount, bool endOfRequest = false)
{ {
var flags = HttpApi.HTTP_FLAGS.NONE; var flags = HttpApi.HTTP_FLAGS.NONE;
if (!_requestContext.Response.HasComputedHeaders) if (!_requestContext.Response.HasComputedHeaders)
{ {
flags = _requestContext.Response.ComputeHeaders(endOfRequest); flags = _requestContext.Response.ComputeHeaders(writeCount, endOfRequest);
} }
if (_leftToWrite == long.MinValue) if (_leftToWrite == long.MinValue)
{ {
@ -591,7 +591,7 @@ namespace Microsoft.Net.Http.Server
} }
// Make sure all validation is performed before this computes the headers // Make sure all validation is performed before this computes the headers
var flags = ComputeLeftToWrite(); var flags = ComputeLeftToWrite(count.Value);
uint statusCode; uint statusCode;
uint bytesSent = 0; uint bytesSent = 0;
var chunked = _requestContext.Response.BoundaryType == BoundaryType.Chunked; var chunked = _requestContext.Response.BoundaryType == BoundaryType.Chunked;

View File

@ -1000,8 +1000,7 @@ namespace Microsoft.Net.Http.Server
} }
} }
[ConditionalFact] [Fact]
[FrameworkSkipCondition(RuntimeFrameworks.CoreCLR, SkipReason = "Cached response contains duplicate Content-Length headers (#167).")]
public async Task Caching_RequestRangeFromCachedFile_ServedFromCache() public async Task Caching_RequestRangeFromCachedFile_ServedFromCache()
{ {
string address; string address;