diff --git a/src/Microsoft.AspNetCore.Server.Kestrel/Http/Frame.cs b/src/Microsoft.AspNetCore.Server.Kestrel/Http/Frame.cs index feeca29db9..e0696f82f6 100644 --- a/src/Microsoft.AspNetCore.Server.Kestrel/Http/Frame.cs +++ b/src/Microsoft.AspNetCore.Server.Kestrel/Http/Frame.cs @@ -30,12 +30,10 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Http private static readonly byte[] _bytesConnectionClose = Encoding.ASCII.GetBytes("\r\nConnection: close"); private static readonly byte[] _bytesConnectionKeepAlive = Encoding.ASCII.GetBytes("\r\nConnection: keep-alive"); private static readonly byte[] _bytesTransferEncodingChunked = Encoding.ASCII.GetBytes("\r\nTransfer-Encoding: chunked"); - private static readonly byte[] _bytesHttpVersion1_0 = Encoding.ASCII.GetBytes("HTTP/1.0 "); private static readonly byte[] _bytesHttpVersion1_1 = Encoding.ASCII.GetBytes("HTTP/1.1 "); private static readonly byte[] _bytesContentLengthZero = Encoding.ASCII.GetBytes("\r\nContent-Length: 0"); private static readonly byte[] _bytesSpace = Encoding.ASCII.GetBytes(" "); private static readonly byte[] _bytesEndHeaders = Encoding.ASCII.GetBytes("\r\n\r\n"); - private static readonly int _httpVersionLength = "HTTP/1.*".Length; private static Vector _vectorCRs = new Vector((byte)'\r'); private static Vector _vectorColons = new Vector((byte)':'); @@ -707,6 +705,13 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Http } else { + // Note for future reference: never change this to set _autoChunk to true on HTTP/1.0 + // connections, even if we were to infer the client supports it because an HTTP/1.0 request + // was received that used chunked encoding. Sending a chunked response to an HTTP/1.0 + // client would break compliance with RFC 7230 (section 3.3.1): + // + // A server MUST NOT send a response containing Transfer-Encoding unless the corresponding + // request indicates HTTP/1.1 (or later). if (_httpVersion == HttpVersionType.Http1_1) { _autoChunk = true; @@ -728,7 +733,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Http responseHeaders.SetRawConnection("keep-alive", _bytesConnectionKeepAlive); } - end.CopyFrom(_httpVersion == HttpVersionType.Http1_1 ? _bytesHttpVersion1_1 : _bytesHttpVersion1_0); + end.CopyFrom(_bytesHttpVersion1_1); end.CopyFrom(statusBytes); responseHeaders.CopyTo(ref end); end.CopyFrom(_bytesEndHeaders, 0, _bytesEndHeaders.Length); diff --git a/test/Microsoft.AspNetCore.Server.KestrelTests/BadHttpRequestTests.cs b/test/Microsoft.AspNetCore.Server.KestrelTests/BadHttpRequestTests.cs index af5b238e80..512e366688 100644 --- a/test/Microsoft.AspNetCore.Server.KestrelTests/BadHttpRequestTests.cs +++ b/test/Microsoft.AspNetCore.Server.KestrelTests/BadHttpRequestTests.cs @@ -42,7 +42,7 @@ namespace Microsoft.AspNetCore.Server.KestrelTests var receiveTask = Task.Run(async () => { await connection.Receive( - "HTTP/1.0 400 Bad Request", + "HTTP/1.1 400 Bad Request", ""); await connection.ReceiveStartsWith("Date: "); await connection.ReceiveForcedEnd( diff --git a/test/Microsoft.AspNetCore.Server.KestrelTests/ChunkedRequestTests.cs b/test/Microsoft.AspNetCore.Server.KestrelTests/ChunkedRequestTests.cs index 6cbe46b947..7acafa9883 100644 --- a/test/Microsoft.AspNetCore.Server.KestrelTests/ChunkedRequestTests.cs +++ b/test/Microsoft.AspNetCore.Server.KestrelTests/ChunkedRequestTests.cs @@ -77,7 +77,7 @@ namespace Microsoft.AspNetCore.Server.KestrelTests "0", ""); await connection.ReceiveEnd( - "HTTP/1.0 200 OK", + "HTTP/1.1 200 OK", "", "Hello World"); } @@ -105,13 +105,13 @@ namespace Microsoft.AspNetCore.Server.KestrelTests "", "Goodbye"); await connection.Receive( - "HTTP/1.0 200 OK", + "HTTP/1.1 200 OK", "Connection: keep-alive", "Content-Length: 11", "", "Hello World"); await connection.ReceiveEnd( - "HTTP/1.0 200 OK", + "HTTP/1.1 200 OK", "Content-Length: 7", "", "Goodbye"); diff --git a/test/Microsoft.AspNetCore.Server.KestrelTests/ConnectionFilterTests.cs b/test/Microsoft.AspNetCore.Server.KestrelTests/ConnectionFilterTests.cs index 8b9451fef8..cb1a7fa182 100644 --- a/test/Microsoft.AspNetCore.Server.KestrelTests/ConnectionFilterTests.cs +++ b/test/Microsoft.AspNetCore.Server.KestrelTests/ConnectionFilterTests.cs @@ -44,7 +44,7 @@ namespace Microsoft.AspNetCore.Server.KestrelTests // "?" changes to "!" await connection.SendEnd(sendString); await connection.ReceiveEnd( - "HTTP/1.0 200 OK", + "HTTP/1.1 200 OK", "", "Hello World!"); } @@ -67,7 +67,7 @@ namespace Microsoft.AspNetCore.Server.KestrelTests "", "Hello World?"); await connection.ReceiveEnd( - "HTTP/1.0 200 OK", + "HTTP/1.1 200 OK", "", "Hello World!"); } diff --git a/test/Microsoft.AspNetCore.Server.KestrelTests/EngineTests.cs b/test/Microsoft.AspNetCore.Server.KestrelTests/EngineTests.cs index a4508b8893..3432a75de3 100644 --- a/test/Microsoft.AspNetCore.Server.KestrelTests/EngineTests.cs +++ b/test/Microsoft.AspNetCore.Server.KestrelTests/EngineTests.cs @@ -121,7 +121,7 @@ namespace Microsoft.AspNetCore.Server.KestrelTests [Theory] [MemberData(nameof(ConnectionFilterData))] - public async Task Http10(ServiceContext testContext) + public async Task Http10RequestReceivesHttp11Response(ServiceContext testContext) { using (var server = new TestServer(App, testContext)) { @@ -132,7 +132,7 @@ namespace Microsoft.AspNetCore.Server.KestrelTests "", "Hello World"); await connection.ReceiveEnd( - "HTTP/1.0 200 OK", + "HTTP/1.1 200 OK", "", "Hello World"); } @@ -268,7 +268,7 @@ namespace Microsoft.AspNetCore.Server.KestrelTests "", "Hello World"); await connection.ReceiveEnd( - "HTTP/1.0 200 OK", + "HTTP/1.1 200 OK", "", "Hello World"); } @@ -291,12 +291,12 @@ namespace Microsoft.AspNetCore.Server.KestrelTests "", "Goodbye"); await connection.Receive( - "HTTP/1.0 200 OK", + "HTTP/1.1 200 OK", "Connection: keep-alive", "Content-Length: 0", "\r\n"); await connection.ReceiveEnd( - "HTTP/1.0 200 OK", + "HTTP/1.1 200 OK", "Content-Length: 7", "", "Goodbye"); @@ -322,12 +322,12 @@ namespace Microsoft.AspNetCore.Server.KestrelTests "", "Goodbye"); await connection.Receive( - "HTTP/1.0 200 OK", + "HTTP/1.1 200 OK", "Connection: keep-alive", "Content-Length: 0", "\r\n"); await connection.ReceiveEnd( - "HTTP/1.0 200 OK", + "HTTP/1.1 200 OK", "", "Goodbye"); } @@ -351,13 +351,13 @@ namespace Microsoft.AspNetCore.Server.KestrelTests "", "Goodbye"); await connection.Receive( - "HTTP/1.0 200 OK", + "HTTP/1.1 200 OK", "Connection: keep-alive", "Content-Length: 11", "", "Hello World"); await connection.ReceiveEnd( - "HTTP/1.0 200 OK", + "HTTP/1.1 200 OK", "Content-Length: 7", "", "Goodbye"); @@ -408,7 +408,7 @@ namespace Microsoft.AspNetCore.Server.KestrelTests "GET / HTTP/1.0", "\r\n"); await connection.ReceiveEnd( - "HTTP/1.0 200 OK", + "HTTP/1.1 200 OK", "\r\n"); } } @@ -433,7 +433,7 @@ namespace Microsoft.AspNetCore.Server.KestrelTests "HTTP/1.1 200 OK", "Content-Length: 0", "", - "HTTP/1.0 200 OK", + "HTTP/1.1 200 OK", "Connection: keep-alive", "Content-Length: 0", "", @@ -469,7 +469,7 @@ namespace Microsoft.AspNetCore.Server.KestrelTests "", ""); await connection.ReceiveEnd( - "HTTP/1.0 200 OK", + "HTTP/1.1 200 OK", "", ""); } @@ -729,7 +729,7 @@ namespace Microsoft.AspNetCore.Server.KestrelTests await connection.SendEnd( "GET /"); await connection.Receive( - "HTTP/1.0 400 Bad Request", + "HTTP/1.1 400 Bad Request", ""); await connection.ReceiveStartsWith("Date:"); await connection.ReceiveForcedEnd( @@ -749,7 +749,7 @@ namespace Microsoft.AspNetCore.Server.KestrelTests "HTTP/1.1 200 OK", "Content-Length: 0", "", - "HTTP/1.0 400 Bad Request", + "HTTP/1.1 400 Bad Request", ""); await connection.ReceiveStartsWith("Date:"); await connection.ReceiveForcedEnd( @@ -1063,7 +1063,7 @@ namespace Microsoft.AspNetCore.Server.KestrelTests "", ""); await connection.ReceiveForcedEnd( - "HTTP/1.0 200 OK", + "HTTP/1.1 200 OK", "Content-Length: 11", "", "Hello World"); diff --git a/test/Microsoft.AspNetCore.Server.KestrelTests/HttpsConnectionFilterTests.cs b/test/Microsoft.AspNetCore.Server.KestrelTests/HttpsConnectionFilterTests.cs index e41bced2e6..c0da2cbc5b 100644 --- a/test/Microsoft.AspNetCore.Server.KestrelTests/HttpsConnectionFilterTests.cs +++ b/test/Microsoft.AspNetCore.Server.KestrelTests/HttpsConnectionFilterTests.cs @@ -240,7 +240,7 @@ namespace Microsoft.AspNetCore.Server.KestrelTests var reader = new StreamReader(stream); var line = await reader.ReadLineAsync(); - Assert.Equal("HTTP/1.0 200 OK", line); + Assert.Equal("HTTP/1.1 200 OK", line); } } }