diff --git a/src/Microsoft.AspNetCore.Server.Kestrel/Http/DateHeaderValueManager.cs b/src/Microsoft.AspNetCore.Server.Kestrel/Http/DateHeaderValueManager.cs
index 87a2e60de..42f3de4d7 100644
--- a/src/Microsoft.AspNetCore.Server.Kestrel/Http/DateHeaderValueManager.cs
+++ b/src/Microsoft.AspNetCore.Server.Kestrel/Http/DateHeaderValueManager.cs
@@ -32,22 +32,24 @@ public class DateHeaderValueManager : IDisposable
/// Initializes a new instance of the class.
///
public DateHeaderValueManager()
- : this(
- systemClock: new SystemClock(),
- timeWithoutRequestsUntilIdle: TimeSpan.FromSeconds(10),
- timerInterval: TimeSpan.FromSeconds(1))
+ : this(systemClock: new SystemClock())
{
}
// Internal for testing
internal DateHeaderValueManager(
ISystemClock systemClock,
- TimeSpan timeWithoutRequestsUntilIdle,
- TimeSpan timerInterval)
+ TimeSpan? timeWithoutRequestsUntilIdle = null,
+ TimeSpan? timerInterval = null)
{
+ if (systemClock == null)
+ {
+ throw new ArgumentNullException(nameof(systemClock));
+ }
+
_systemClock = systemClock;
- _timeWithoutRequestsUntilIdle = timeWithoutRequestsUntilIdle;
- _timerInterval = timerInterval;
+ _timeWithoutRequestsUntilIdle = timeWithoutRequestsUntilIdle ?? TimeSpan.FromSeconds(10);
+ _timerInterval = timerInterval ?? TimeSpan.FromSeconds(1);
_dateValueTimer = new Timer(TimerLoop, state: null, dueTime: Timeout.Infinite, period: Timeout.Infinite);
}
diff --git a/src/Microsoft.AspNetCore.Server.Kestrel/Http/Frame.cs b/src/Microsoft.AspNetCore.Server.Kestrel/Http/Frame.cs
index 2716a94e5..63ada0446 100644
--- a/src/Microsoft.AspNetCore.Server.Kestrel/Http/Frame.cs
+++ b/src/Microsoft.AspNetCore.Server.Kestrel/Http/Frame.cs
@@ -33,6 +33,7 @@ public abstract partial class Frame : ConnectionContext, IFrameControl
private static readonly byte[] _bytesHttpVersion11 = Encoding.ASCII.GetBytes("HTTP/1.1 ");
private static readonly byte[] _bytesContentLengthZero = Encoding.ASCII.GetBytes("\r\nContent-Length: 0");
private static readonly byte[] _bytesEndHeaders = Encoding.ASCII.GetBytes("\r\n\r\n");
+ private static readonly byte[] _bytesServer = Encoding.ASCII.GetBytes("\r\nServer: Kestrel");
private static Vector _vectorCRs = new Vector((byte)'\r');
private static Vector _vectorColons = new Vector((byte)':');
@@ -44,7 +45,6 @@ public abstract partial class Frame : ConnectionContext, IFrameControl
private readonly object _onCompletedSync = new Object();
private bool _requestRejected;
- private Headers _frameHeaders;
private Streams _frameStreams;
protected List, object>> _onStarting;
@@ -210,21 +210,23 @@ public bool HasResponseStarted
get { return _requestProcessingStatus == RequestProcessingStatus.ResponseStarted; }
}
- protected FrameRequestHeaders FrameRequestHeaders => _frameHeaders.RequestHeaders;
+ protected FrameRequestHeaders FrameRequestHeaders { get; private set; }
+
+ protected FrameResponseHeaders FrameResponseHeaders { get; private set; }
public void InitializeHeaders()
{
- if (_frameHeaders == null)
+ if (FrameRequestHeaders == null)
{
- _frameHeaders = new Headers(ServerOptions);
- RequestHeaders = _frameHeaders.RequestHeaders;
- ResponseHeaders = _frameHeaders.ResponseHeaders;
+ RequestHeaders = FrameRequestHeaders = new FrameRequestHeaders();
}
- _frameHeaders.Initialize(DateHeaderValueManager);
+ if (FrameResponseHeaders == null)
+ {
+ ResponseHeaders = FrameResponseHeaders = new FrameResponseHeaders();
+ }
}
-
public void InitializeStreams(MessageBody messageBody)
{
if (_frameStreams == null)
@@ -259,7 +261,8 @@ public void StopStreams()
public void Reset()
{
- _frameHeaders?.Reset();
+ FrameRequestHeaders?.Reset();
+ FrameResponseHeaders?.Reset();
_onStarting = null;
_onCompleted = null;
@@ -598,7 +601,7 @@ protected Task TryProduceInvalidRequestResponse()
{
if (_requestProcessingStatus == RequestProcessingStatus.RequestStarted && _requestRejected)
{
- if (_frameHeaders == null)
+ if (FrameRequestHeaders == null || FrameResponseHeaders == null)
{
InitializeHeaders();
}
@@ -634,7 +637,7 @@ protected Task ProduceEnd()
ReasonPhrase = null;
- var responseHeaders = _frameHeaders.ResponseHeaders;
+ var responseHeaders = FrameResponseHeaders;
responseHeaders.Reset();
var dateHeaderValues = DateHeaderValueManager.GetDateHeaderValues();
@@ -643,7 +646,7 @@ protected Task ProduceEnd()
if (ServerOptions.AddServerHeader)
{
- responseHeaders.SetRawServer(Constants.ServerName, Headers.BytesServer);
+ responseHeaders.SetRawServer(Constants.ServerName, _bytesServer);
}
ResponseHeaders = responseHeaders;
@@ -698,7 +701,7 @@ private void CreateResponseHeader(
byte[] statusBytes,
bool appCompleted)
{
- var responseHeaders = _frameHeaders.ResponseHeaders;
+ var responseHeaders = FrameResponseHeaders;
responseHeaders.SetReadOnly();
var hasConnection = responseHeaders.HasConnection;
@@ -759,6 +762,17 @@ private void CreateResponseHeader(
responseHeaders.SetRawConnection("keep-alive", _bytesConnectionKeepAlive);
}
+ if (ServerOptions.AddServerHeader && !responseHeaders.HasServer)
+ {
+ responseHeaders.SetRawServer(Constants.ServerName, _bytesServer);
+ }
+
+ if (!responseHeaders.HasDate)
+ {
+ var dateHeaderValues = DateHeaderValueManager.GetDateHeaderValues();
+ responseHeaders.SetRawDate(dateHeaderValues.String, dateHeaderValues.Bytes);
+ }
+
end.CopyFrom(_bytesHttpVersion11);
end.CopyFrom(statusBytes);
responseHeaders.CopyTo(ref end);
diff --git a/src/Microsoft.AspNetCore.Server.Kestrel/Http/FrameResponseHeaders.cs b/src/Microsoft.AspNetCore.Server.Kestrel/Http/FrameResponseHeaders.cs
index c843e9625..9697ad0e6 100644
--- a/src/Microsoft.AspNetCore.Server.Kestrel/Http/FrameResponseHeaders.cs
+++ b/src/Microsoft.AspNetCore.Server.Kestrel/Http/FrameResponseHeaders.cs
@@ -19,6 +19,9 @@ public partial class FrameResponseHeaders : FrameHeaders
public bool HasContentLength => HeaderContentLength.Count != 0;
+ public bool HasServer => HeaderServer.Count != 0;
+
+ public bool HasDate => HeaderDate.Count != 0;
public Enumerator GetEnumerator()
{
diff --git a/src/Microsoft.AspNetCore.Server.Kestrel/Infrastructure/Headers.cs b/src/Microsoft.AspNetCore.Server.Kestrel/Infrastructure/Headers.cs
deleted file mode 100644
index 1f81dcdea..000000000
--- a/src/Microsoft.AspNetCore.Server.Kestrel/Infrastructure/Headers.cs
+++ /dev/null
@@ -1,40 +0,0 @@
-// 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.Text;
-using Microsoft.AspNetCore.Server.Kestrel.Http;
-
-namespace Microsoft.AspNetCore.Server.Kestrel.Infrastructure
-{
- class Headers
- {
- public static readonly byte[] BytesServer = Encoding.ASCII.GetBytes("\r\nServer: Kestrel");
-
- private readonly KestrelServerOptions _options;
-
- public Headers(KestrelServerOptions options)
- {
- _options = options;
- }
-
- public void Initialize(DateHeaderValueManager dateValueManager)
- {
- var dateHeaderValues = dateValueManager.GetDateHeaderValues();
- ResponseHeaders.SetRawDate(dateHeaderValues.String, dateHeaderValues.Bytes);
-
- if (_options.AddServerHeader)
- {
- ResponseHeaders.SetRawServer("Kestrel", BytesServer);
- }
- }
-
- public FrameRequestHeaders RequestHeaders { get; } = new FrameRequestHeaders();
- public FrameResponseHeaders ResponseHeaders { get; } = new FrameResponseHeaders();
-
- public void Reset()
- {
- RequestHeaders.Reset();
- ResponseHeaders.Reset();
- }
- }
-}
diff --git a/test/Microsoft.AspNetCore.Server.KestrelTests/BadHttpRequestTests.cs b/test/Microsoft.AspNetCore.Server.KestrelTests/BadHttpRequestTests.cs
index adc90857d..a239e7102 100644
--- a/test/Microsoft.AspNetCore.Server.KestrelTests/BadHttpRequestTests.cs
+++ b/test/Microsoft.AspNetCore.Server.KestrelTests/BadHttpRequestTests.cs
@@ -70,7 +70,7 @@ public async Task TestBadRequestLines(string request)
{
using (var server = new TestServer(context => { return Task.FromResult(0); }))
{
- using (var connection = new TestConnection(server.Port))
+ using (var connection = server.CreateConnection())
{
await connection.SendEnd(request);
await ReceiveBadRequestResponse(connection);
@@ -87,7 +87,7 @@ public async Task ServerClosesConnectionAsSoonAsBadRequestLineIsDetected(string
{
using (var server = new TestServer(context => { return Task.FromResult(0); }))
{
- using (var connection = new TestConnection(server.Port))
+ using (var connection = server.CreateConnection())
{
await connection.Send(request);
await ReceiveBadRequestResponse(connection);
@@ -103,10 +103,9 @@ await connection.Receive(
await connection.Receive(
"Connection: close",
"");
- await connection.ReceiveStartsWith("Date: ");
await connection.ReceiveEnd(
+ $"Date: {connection.Server.Context.DateHeaderValue}",
"Content-Length: 0",
- "Server: Kestrel",
"",
"");
}
diff --git a/test/Microsoft.AspNetCore.Server.KestrelTests/ChunkedRequestTests.cs b/test/Microsoft.AspNetCore.Server.KestrelTests/ChunkedRequestTests.cs
index 217af83a6..173912d59 100644
--- a/test/Microsoft.AspNetCore.Server.KestrelTests/ChunkedRequestTests.cs
+++ b/test/Microsoft.AspNetCore.Server.KestrelTests/ChunkedRequestTests.cs
@@ -14,11 +14,11 @@ namespace Microsoft.AspNetCore.Server.KestrelTests
{
public class ChunkedRequestTests
{
- public static TheoryData ConnectionFilterData
+ public static TheoryData ConnectionFilterData
{
get
{
- return new TheoryData
+ return new TheoryData
{
{
new TestServiceContext()
@@ -34,7 +34,6 @@ private async Task App(HttpContext httpContext)
{
var request = httpContext.Request;
var response = httpContext.Response;
- response.Headers.Clear();
while (true)
{
var buffer = new byte[8192];
@@ -55,18 +54,17 @@ private async Task AppChunked(HttpContext httpContext)
await request.Body.CopyToAsync(data);
var bytes = data.ToArray();
- response.Headers.Clear();
response.Headers["Content-Length"] = bytes.Length.ToString();
await response.Body.WriteAsync(bytes, 0, bytes.Length);
}
[Theory]
[MemberData(nameof(ConnectionFilterData))]
- public async Task Http10TransferEncoding(ServiceContext testContext)
+ public async Task Http10TransferEncoding(TestServiceContext testContext)
{
using (var server = new TestServer(App, testContext))
{
- using (var connection = new TestConnection(server.Port))
+ using (var connection = server.CreateConnection())
{
await connection.SendEnd(
"POST / HTTP/1.0",
@@ -78,6 +76,7 @@ await connection.SendEnd(
"");
await connection.ReceiveEnd(
"HTTP/1.1 200 OK",
+ $"Date: {testContext.DateHeaderValue}",
"",
"Hello World");
}
@@ -86,11 +85,11 @@ await connection.ReceiveEnd(
[Theory]
[MemberData(nameof(ConnectionFilterData))]
- public async Task Http10KeepAliveTransferEncoding(ServiceContext testContext)
+ public async Task Http10KeepAliveTransferEncoding(TestServiceContext testContext)
{
using (var server = new TestServer(AppChunked, testContext))
{
- using (var connection = new TestConnection(server.Port))
+ using (var connection = server.CreateConnection())
{
await connection.SendEnd(
"POST / HTTP/1.0",
@@ -107,11 +106,13 @@ await connection.SendEnd(
await connection.Receive(
"HTTP/1.1 200 OK",
"Connection: keep-alive",
+ $"Date: {testContext.DateHeaderValue}",
"Content-Length: 11",
"",
"Hello World");
await connection.ReceiveEnd(
"HTTP/1.1 200 OK",
+ $"Date: {testContext.DateHeaderValue}",
"Content-Length: 7",
"",
"Goodbye");
@@ -121,7 +122,7 @@ await connection.ReceiveEnd(
[Theory]
[MemberData(nameof(ConnectionFilterData))]
- public async Task RequestBodyIsConsumedAutomaticallyIfAppDoesntConsumeItFully(ServiceContext testContext)
+ public async Task RequestBodyIsConsumedAutomaticallyIfAppDoesntConsumeItFully(TestServiceContext testContext)
{
using (var server = new TestServer(async httpContext =>
{
@@ -130,13 +131,12 @@ public async Task RequestBodyIsConsumedAutomaticallyIfAppDoesntConsumeItFully(Se
Assert.Equal("POST", request.Method);
- response.Headers.Clear();
response.Headers["Content-Length"] = new[] { "11" };
await response.Body.WriteAsync(Encoding.ASCII.GetBytes("Hello World"), 0, 11);
}, testContext))
{
- using (var connection = new TestConnection(server.Port))
+ using (var connection = server.CreateConnection())
{
await connection.SendEnd(
"POST / HTTP/1.1",
@@ -154,12 +154,15 @@ await connection.SendEnd(
"Goodbye");
await connection.ReceiveEnd(
"HTTP/1.1 200 OK",
+ $"Date: {testContext.DateHeaderValue}",
"Content-Length: 11",
"",
"Hello WorldHTTP/1.1 200 OK",
+ $"Date: {testContext.DateHeaderValue}",
"Content-Length: 11",
"",
"Hello WorldHTTP/1.1 200 OK",
+ $"Date: {testContext.DateHeaderValue}",
"Content-Length: 11",
"",
"Hello World");
@@ -169,7 +172,7 @@ await connection.ReceiveEnd(
[Theory]
[MemberData(nameof(ConnectionFilterData))]
- public async Task TrailingHeadersAreParsed(ServiceContext testContext)
+ public async Task TrailingHeadersAreParsed(TestServiceContext testContext)
{
var requestCount = 10;
var requestsReceived = 0;
@@ -199,7 +202,6 @@ public async Task TrailingHeadersAreParsed(ServiceContext testContext)
requestsReceived++;
- response.Headers.Clear();
response.Headers["Content-Length"] = new[] { "11" };
await response.Body.WriteAsync(Encoding.ASCII.GetBytes("Hello World"), 0, 11);
@@ -207,6 +209,7 @@ public async Task TrailingHeadersAreParsed(ServiceContext testContext)
{
var response = string.Join("\r\n", new string[] {
"HTTP/1.1 200 OK",
+ $"Date: {testContext.DateHeaderValue}",
"Content-Length: 11",
"",
"Hello World"});
@@ -244,7 +247,7 @@ public async Task TrailingHeadersAreParsed(ServiceContext testContext)
var fullRequest = sendSequence.ToArray();
- using (var connection = new TestConnection(server.Port))
+ using (var connection = server.CreateConnection())
{
await connection.SendEnd(fullRequest);
@@ -255,7 +258,7 @@ public async Task TrailingHeadersAreParsed(ServiceContext testContext)
[Theory]
[MemberData(nameof(ConnectionFilterData))]
- public async Task ExtensionsAreIgnored(ServiceContext testContext)
+ public async Task ExtensionsAreIgnored(TestServiceContext testContext)
{
var requestCount = 10;
var requestsReceived = 0;
@@ -285,7 +288,6 @@ public async Task ExtensionsAreIgnored(ServiceContext testContext)
requestsReceived++;
- response.Headers.Clear();
response.Headers["Content-Length"] = new[] { "11" };
await response.Body.WriteAsync(Encoding.ASCII.GetBytes("Hello World"), 0, 11);
@@ -293,6 +295,7 @@ public async Task ExtensionsAreIgnored(ServiceContext testContext)
{
var response = string.Join("\r\n", new string[] {
"HTTP/1.1 200 OK",
+ $"Date: {testContext.DateHeaderValue}",
"Content-Length: 11",
"",
"Hello World"});
@@ -330,7 +333,7 @@ public async Task ExtensionsAreIgnored(ServiceContext testContext)
var fullRequest = sendSequence.ToArray();
- using (var connection = new TestConnection(server.Port))
+ using (var connection = server.CreateConnection())
{
await connection.SendEnd(fullRequest);
@@ -341,7 +344,7 @@ public async Task ExtensionsAreIgnored(ServiceContext testContext)
[Theory]
[MemberData(nameof(ConnectionFilterData))]
- public async Task InvalidLengthResultsIn400(ServiceContext testContext)
+ public async Task InvalidLengthResultsIn400(TestServiceContext testContext)
{
using (var server = new TestServer(async httpContext =>
{
@@ -355,13 +358,12 @@ public async Task InvalidLengthResultsIn400(ServiceContext testContext)
;// read to end
}
- response.Headers.Clear();
response.Headers["Content-Length"] = new[] { "11" };
await response.Body.WriteAsync(Encoding.ASCII.GetBytes("Hello World"), 0, 11);
}, testContext))
{
- using (var connection = new TestConnection(server.Port))
+ using (var connection = server.CreateConnection())
{
await connection.Send(
"POST / HTTP/1.1",
@@ -373,10 +375,9 @@ await connection.Receive(
"HTTP/1.1 400 Bad Request",
"Connection: close",
"");
- await connection.ReceiveStartsWith("Date:");
await connection.ReceiveForcedEnd(
+ $"Date: {testContext.DateHeaderValue}",
"Content-Length: 0",
- "Server: Kestrel",
"",
"");
}
@@ -385,7 +386,7 @@ await connection.ReceiveForcedEnd(
[Theory]
[MemberData(nameof(ConnectionFilterData))]
- public async Task InvalidSizedDataResultsIn400(ServiceContext testContext)
+ public async Task InvalidSizedDataResultsIn400(TestServiceContext testContext)
{
using (var server = new TestServer(async httpContext =>
{
@@ -399,13 +400,12 @@ public async Task InvalidSizedDataResultsIn400(ServiceContext testContext)
;// read to end
}
- response.Headers.Clear();
response.Headers["Content-Length"] = new[] { "11" };
await response.Body.WriteAsync(Encoding.ASCII.GetBytes("Hello World"), 0, 11);
}, testContext))
{
- using (var connection = new TestConnection(server.Port))
+ using (var connection = server.CreateConnection())
{
await connection.Send(
"POST / HTTP/1.1",
@@ -418,10 +418,9 @@ await connection.Receive(
"HTTP/1.1 400 Bad Request",
"Connection: close",
"");
- await connection.ReceiveStartsWith("Date:");
await connection.ReceiveForcedEnd(
+ $"Date: {testContext.DateHeaderValue}",
"Content-Length: 0",
- "Server: Kestrel",
"",
"");
}
diff --git a/test/Microsoft.AspNetCore.Server.KestrelTests/ChunkedResponseTests.cs b/test/Microsoft.AspNetCore.Server.KestrelTests/ChunkedResponseTests.cs
index fd4035cc3..62758e36a 100644
--- a/test/Microsoft.AspNetCore.Server.KestrelTests/ChunkedResponseTests.cs
+++ b/test/Microsoft.AspNetCore.Server.KestrelTests/ChunkedResponseTests.cs
@@ -12,11 +12,11 @@ namespace Microsoft.AspNetCore.Server.KestrelTests
{
public class ChunkedResponseTests
{
- public static TheoryData ConnectionFilterData
+ public static TheoryData ConnectionFilterData
{
get
{
- return new TheoryData
+ return new TheoryData
{
{
new TestServiceContext()
@@ -30,17 +30,16 @@ public static TheoryData ConnectionFilterData
[Theory]
[MemberData(nameof(ConnectionFilterData))]
- public async Task ResponsesAreChunkedAutomatically(ServiceContext testContext)
+ public async Task ResponsesAreChunkedAutomatically(TestServiceContext testContext)
{
using (var server = new TestServer(async httpContext =>
{
var response = httpContext.Response;
- response.Headers.Clear();
await response.Body.WriteAsync(Encoding.ASCII.GetBytes("Hello "), 0, 6);
await response.Body.WriteAsync(Encoding.ASCII.GetBytes("World!"), 0, 6);
}, testContext))
{
- using (var connection = new TestConnection(server.Port))
+ using (var connection = server.CreateConnection())
{
await connection.SendEnd(
"GET / HTTP/1.1",
@@ -48,6 +47,7 @@ await connection.SendEnd(
"");
await connection.ReceiveEnd(
"HTTP/1.1 200 OK",
+ $"Date: {testContext.DateHeaderValue}",
"Transfer-Encoding: chunked",
"",
"6",
@@ -63,18 +63,17 @@ await connection.ReceiveEnd(
[Theory]
[MemberData(nameof(ConnectionFilterData))]
- public async Task ZeroLengthWritesAreIgnored(ServiceContext testContext)
+ public async Task ZeroLengthWritesAreIgnored(TestServiceContext testContext)
{
using (var server = new TestServer(async httpContext =>
{
var response = httpContext.Response;
- response.Headers.Clear();
await response.Body.WriteAsync(Encoding.ASCII.GetBytes("Hello "), 0, 6);
await response.Body.WriteAsync(new byte[0], 0, 0);
await response.Body.WriteAsync(Encoding.ASCII.GetBytes("World!"), 0, 6);
}, testContext))
{
- using (var connection = new TestConnection(server.Port))
+ using (var connection = server.CreateConnection())
{
await connection.SendEnd(
"GET / HTTP/1.1",
@@ -82,6 +81,7 @@ await connection.SendEnd(
"");
await connection.ReceiveEnd(
"HTTP/1.1 200 OK",
+ $"Date: {testContext.DateHeaderValue}",
"Transfer-Encoding: chunked",
"",
"6",
@@ -97,16 +97,15 @@ await connection.ReceiveEnd(
[Theory]
[MemberData(nameof(ConnectionFilterData))]
- public async Task EmptyResponseBodyHandledCorrectlyWithZeroLengthWrite(ServiceContext testContext)
+ public async Task EmptyResponseBodyHandledCorrectlyWithZeroLengthWrite(TestServiceContext testContext)
{
using (var server = new TestServer(async httpContext =>
{
var response = httpContext.Response;
- response.Headers.Clear();
await response.Body.WriteAsync(new byte[0], 0, 0);
}, testContext))
{
- using (var connection = new TestConnection(server.Port))
+ using (var connection = server.CreateConnection())
{
await connection.SendEnd(
"GET / HTTP/1.1",
@@ -114,6 +113,7 @@ await connection.SendEnd(
"");
await connection.ReceiveEnd(
"HTTP/1.1 200 OK",
+ $"Date: {testContext.DateHeaderValue}",
"Transfer-Encoding: chunked",
"",
"0",
@@ -125,17 +125,16 @@ await connection.ReceiveEnd(
[Theory]
[MemberData(nameof(ConnectionFilterData))]
- public async Task ConnectionClosedIfExeptionThrownAfterWrite(ServiceContext testContext)
+ public async Task ConnectionClosedIfExeptionThrownAfterWrite(TestServiceContext testContext)
{
using (var server = new TestServer(async httpContext =>
{
var response = httpContext.Response;
- response.Headers.Clear();
await response.Body.WriteAsync(Encoding.ASCII.GetBytes("Hello World!"), 0, 12);
throw new Exception();
}, testContext))
{
- using (var connection = new TestConnection(server.Port))
+ using (var connection = server.CreateConnection())
{
// SendEnd is not called, so it isn't the client closing the connection.
// client closing the connection.
@@ -145,6 +144,7 @@ await connection.Send(
"");
await connection.ReceiveForcedEnd(
"HTTP/1.1 200 OK",
+ $"Date: {testContext.DateHeaderValue}",
"Transfer-Encoding: chunked",
"",
"c",
@@ -156,17 +156,16 @@ await connection.ReceiveForcedEnd(
[Theory]
[MemberData(nameof(ConnectionFilterData))]
- public async Task ConnectionClosedIfExeptionThrownAfterZeroLengthWrite(ServiceContext testContext)
+ public async Task ConnectionClosedIfExeptionThrownAfterZeroLengthWrite(TestServiceContext testContext)
{
using (var server = new TestServer(async httpContext =>
{
var response = httpContext.Response;
- response.Headers.Clear();
await response.Body.WriteAsync(new byte[0], 0, 0);
throw new Exception();
}, testContext))
{
- using (var connection = new TestConnection(server.Port))
+ using (var connection = server.CreateConnection())
{
// SendEnd is not called, so it isn't the client closing the connection.
await connection.Send(
@@ -177,6 +176,7 @@ await connection.Send(
// Headers are sent before connection is closed, but chunked body terminator isn't sent
await connection.ReceiveForcedEnd(
"HTTP/1.1 200 OK",
+ $"Date: {testContext.DateHeaderValue}",
"Transfer-Encoding: chunked",
"",
"");
@@ -186,14 +186,13 @@ await connection.ReceiveForcedEnd(
[Theory]
[MemberData(nameof(ConnectionFilterData))]
- public async Task WritesAreFlushedPriorToResponseCompletion(ServiceContext testContext)
+ public async Task WritesAreFlushedPriorToResponseCompletion(TestServiceContext testContext)
{
var flushWh = new ManualResetEventSlim();
using (var server = new TestServer(async httpContext =>
{
var response = httpContext.Response;
- response.Headers.Clear();
await response.Body.WriteAsync(Encoding.ASCII.GetBytes("Hello "), 0, 6);
// Don't complete response until client has received the first chunk.
@@ -202,7 +201,7 @@ public async Task WritesAreFlushedPriorToResponseCompletion(ServiceContext testC
await response.Body.WriteAsync(Encoding.ASCII.GetBytes("World!"), 0, 6);
}, testContext))
{
- using (var connection = new TestConnection(server.Port))
+ using (var connection = server.CreateConnection())
{
await connection.SendEnd(
"GET / HTTP/1.1",
@@ -210,6 +209,7 @@ await connection.SendEnd(
"");
await connection.Receive(
"HTTP/1.1 200 OK",
+ $"Date: {testContext.DateHeaderValue}",
"Transfer-Encoding: chunked",
"",
"6",
diff --git a/test/Microsoft.AspNetCore.Server.KestrelTests/ConnectionFilterTests.cs b/test/Microsoft.AspNetCore.Server.KestrelTests/ConnectionFilterTests.cs
index cb1a7fa18..2d32fd6c6 100644
--- a/test/Microsoft.AspNetCore.Server.KestrelTests/ConnectionFilterTests.cs
+++ b/test/Microsoft.AspNetCore.Server.KestrelTests/ConnectionFilterTests.cs
@@ -16,7 +16,6 @@ private async Task App(HttpContext httpContext)
{
var request = httpContext.Request;
var response = httpContext.Response;
- response.Headers.Clear();
while (true)
{
var buffer = new byte[8192];
@@ -39,12 +38,13 @@ public async Task CanReadAndWriteWithRewritingConnectionFilter()
using (var server = new TestServer(App, serviceContext))
{
- using (var connection = new TestConnection(server.Port))
+ using (var connection = server.CreateConnection())
{
// "?" changes to "!"
await connection.SendEnd(sendString);
await connection.ReceiveEnd(
"HTTP/1.1 200 OK",
+ $"Date: {serviceContext.DateHeaderValue}",
"",
"Hello World!");
}
@@ -60,7 +60,7 @@ public async Task CanReadAndWriteWithAsyncConnectionFilter()
using (var server = new TestServer(App, serviceContext))
{
- using (var connection = new TestConnection(server.Port))
+ using (var connection = server.CreateConnection())
{
await connection.SendEnd(
"POST / HTTP/1.0",
@@ -68,6 +68,7 @@ await connection.SendEnd(
"Hello World?");
await connection.ReceiveEnd(
"HTTP/1.1 200 OK",
+ $"Date: {serviceContext.DateHeaderValue}",
"",
"Hello World!");
}
@@ -81,7 +82,7 @@ public async Task ThrowingSynchronousConnectionFilterDoesNotCrashServer()
using (var server = new TestServer(App, serviceContext))
{
- using (var connection = new TestConnection(server.Port))
+ using (var connection = server.CreateConnection())
{
try
{
diff --git a/test/Microsoft.AspNetCore.Server.KestrelTests/DefaultHeaderTests.cs b/test/Microsoft.AspNetCore.Server.KestrelTests/DefaultHeaderTests.cs
new file mode 100644
index 000000000..b682dd35d
--- /dev/null
+++ b/test/Microsoft.AspNetCore.Server.KestrelTests/DefaultHeaderTests.cs
@@ -0,0 +1,41 @@
+// 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.Threading.Tasks;
+using Microsoft.AspNetCore.Http;
+using Microsoft.AspNetCore.Server.Kestrel;
+using Microsoft.AspNetCore.Server.Kestrel.Infrastructure;
+using Xunit;
+
+namespace Microsoft.AspNetCore.Server.KestrelTests
+{
+ public class DefaultHeaderTests
+ {
+ [Fact]
+ public async Task TestDefaultHeaders()
+ {
+ var testContext = new TestServiceContext()
+ {
+ ServerOptions = { AddServerHeader = true }
+ };
+
+ using (var server = new TestServer(ctx => TaskUtilities.CompletedTask, testContext))
+ {
+ using (var connection = server.CreateConnection())
+ {
+ await connection.SendEnd(
+ "GET / HTTP/1.0",
+ "",
+ "");
+
+ await connection.ReceiveEnd(
+ "HTTP/1.1 200 OK",
+ $"Date: {testContext.DateHeaderValue}",
+ "Server: Kestrel",
+ "",
+ "");
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/test/Microsoft.AspNetCore.Server.KestrelTests/EngineTests.cs b/test/Microsoft.AspNetCore.Server.KestrelTests/EngineTests.cs
index f6894e7df..a611f8305 100644
--- a/test/Microsoft.AspNetCore.Server.KestrelTests/EngineTests.cs
+++ b/test/Microsoft.AspNetCore.Server.KestrelTests/EngineTests.cs
@@ -20,11 +20,11 @@ namespace Microsoft.AspNetCore.Server.KestrelTests
///
public class EngineTests
{
- public static TheoryData ConnectionFilterData
+ public static TheoryData ConnectionFilterData
{
get
{
- return new TheoryData
+ return new TheoryData
{
{
new TestServiceContext()
@@ -40,7 +40,6 @@ private async Task App(HttpContext httpContext)
{
var request = httpContext.Request;
var response = httpContext.Response;
- response.Headers.Clear();
while (true)
{
var buffer = new byte[8192];
@@ -61,20 +60,18 @@ private async Task AppChunked(HttpContext httpContext)
await request.Body.CopyToAsync(data);
var bytes = data.ToArray();
- response.Headers.Clear();
response.Headers["Content-Length"] = bytes.Length.ToString();
await response.Body.WriteAsync(bytes, 0, bytes.Length);
}
private Task EmptyApp(HttpContext httpContext)
{
- httpContext.Response.Headers.Clear();
return Task.FromResult