Include Server and Date in the initial response header dictionary

This commit is contained in:
Stephen Halter 2015-07-30 20:46:02 -07:00
parent 978dd39924
commit e5144e3139
6 changed files with 118 additions and 3 deletions

View File

@ -170,7 +170,20 @@ using System;
using System.Collections.Generic;
namespace Microsoft.AspNet.Server.Kestrel.Http
{{{Each(loops, loop => $@"
{{
public partial class FrameResponseHeaders
{{
public FrameResponseHeaders()
{{
_Server = new[] {{ ""Kestrel"" }};
_Date = new[] {{ DateTime.UtcNow.ToString(""r"") }};
_bits = {
1L << responseHeaders.First(header => header.Name == "Server").Index |
1L << responseHeaders.First(header => header.Name == "Date").Index
}L;
}}
}}
{Each(loops, loop => $@"
public partial class {loop.ClassName}
{{
long _bits = 0;

View File

@ -338,7 +338,7 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
// the app func has failed. https://github.com/aspnet/KestrelHttpServer/issues/43
_onStarting = null;
ResponseHeaders.Clear();
ResponseHeaders = new FrameResponseHeaders();
ResponseHeaders["Content-Length"] = new[] { "0" };
}
}

View File

@ -4,6 +4,16 @@ using System.Collections.Generic;
namespace Microsoft.AspNet.Server.Kestrel.Http
{
public partial class FrameResponseHeaders
{
public FrameResponseHeaders()
{
_Server = new[] { "Kestrel" };
_Date = new[] { DateTime.UtcNow.ToString("r") };
_bits = 67108868L;
}
}
public partial class FrameRequestHeaders
{
long _bits = 0;

View File

@ -22,6 +22,7 @@ namespace Microsoft.AspNet.Server.KestrelTests
{
private async Task App(Frame frame)
{
frame.ResponseHeaders.Clear();
for (; ;)
{
var buffer = new byte[8192];
@ -59,6 +60,7 @@ namespace Microsoft.AspNet.Server.KestrelTests
private async Task AppChunked(Frame frame)
{
frame.ResponseHeaders.Clear();
var data = new MemoryStream();
for (; ;)
{
@ -358,6 +360,7 @@ namespace Microsoft.AspNet.Server.KestrelTests
}, null);
// Anything added to the ResponseHeaders dictionary is ignored
frame.ResponseHeaders.Clear();
frame.ResponseHeaders["Content-Length"] = new[] { "11" };
throw new Exception();
}))
@ -371,12 +374,20 @@ namespace Microsoft.AspNet.Server.KestrelTests
"Connection: close",
"",
"");
await connection.ReceiveEnd(
await connection.Receive(
"HTTP/1.1 500 Internal Server Error",
"");
await connection.ReceiveStartsWith("Date:");
await connection.Receive(
"Content-Length: 0",
"Server: Kestrel",
"",
"HTTP/1.1 500 Internal Server Error",
"");
await connection.ReceiveStartsWith("Date:");
await connection.ReceiveEnd(
"Content-Length: 0",
"Server: Kestrel",
"Connection: close",
"",
"");
@ -399,6 +410,7 @@ namespace Microsoft.AspNet.Server.KestrelTests
return Task.FromResult<object>(null);
}, null);
frame.ResponseHeaders.Clear();
frame.ResponseHeaders["Content-Length"] = new[] { "11" };
await frame.ResponseBody.WriteAsync(Encoding.ASCII.GetBytes("Hello World"), 0, 11);
throw new Exception();
@ -434,6 +446,7 @@ namespace Microsoft.AspNet.Server.KestrelTests
return Task.FromResult<object>(null);
}, null);
frame.ResponseHeaders.Clear();
frame.ResponseHeaders["Content-Length"] = new[] { "11" };
await frame.ResponseBody.WriteAsync(Encoding.ASCII.GetBytes("Hello"), 0, 5);
throw new Exception();

View File

@ -0,0 +1,47 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using Microsoft.AspNet.Server.Kestrel.Http;
using Xunit;
namespace Microsoft.AspNet.Server.KestrelTests
{
public class FrameResponseHeadersTests
{
[Fact]
public void InitialDictionaryContainsServerAndDate()
{
IDictionary<string, string[]> headers = new FrameResponseHeaders();
Assert.Equal(2, headers.Count);
string[] serverHeader;
Assert.True(headers.TryGetValue("Server", out serverHeader));
Assert.Equal(1, serverHeader.Length);
Assert.Equal("Kestrel", serverHeader[0]);
string[] dateHeader;
DateTime date;
Assert.True(headers.TryGetValue("Date", out dateHeader));
Assert.Equal(1, dateHeader.Length);
Assert.True(DateTime.TryParse(dateHeader[0], out date));
Assert.True(DateTime.Now - date <= TimeSpan.FromMinutes(1));
Assert.False(headers.IsReadOnly);
}
[Fact]
public void InitialEntriesCanBeCleared()
{
IDictionary<string, string[]> headers = new FrameResponseHeaders();
headers.Clear();
Assert.Equal(0, headers.Count);
Assert.False(headers.ContainsKey("Server"));
Assert.False(headers.ContainsKey("Date"));
}
}
}

View File

@ -84,6 +84,38 @@ namespace Microsoft.AspNet.Server.KestrelTests
Assert.Equal(expected, new String(actual, 0, offset));
}
public async Task ReceiveStartsWith(string prefix, int maxLineLength = 1024)
{
var actual = new char[maxLineLength];
var offset = 0;
while (offset < maxLineLength)
{
// Read one char at a time so we don't read past the end of the line.
var task = _reader.ReadAsync(actual, offset, 1);
if (!Debugger.IsAttached)
{
Assert.True(task.Wait(1000), "timeout");
}
var count = await task;
if (count == 0)
{
break;
}
Assert.True(count == 1);
offset++;
if (actual[offset - 1] == '\n')
{
break;
}
}
var actualLine = new string(actual, 0, offset);
Assert.StartsWith(prefix, actualLine);
}
public async Task ReceiveEnd(params string[] lines)
{
await Receive(lines);