public async Task ThrowingAfterPartialWriteKillsConnection()
        {
            bool onStartingCalled = false;

            using (var server = new TestServer(async frame =>
            {
                frame.OnStarting(_ =>
                {
                    onStartingCalled = true;
                    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();
            }))
            {
                using (var connection = new TestConnection())
                {
                    await connection.Send(
                        "GET / HTTP/1.1",
                        "",
                        "");

                    await connection.ReceiveEnd(
                        "HTTP/1.1 200 OK",
                        "Content-Length: 11",
                        "",
                        "Hello");

                    Assert.True(onStartingCalled);
                }
            }
        }
 public async Task ResponsesAreChunkedAutomatically()
 {
     using (var server = new TestServer(async frame =>
     {
         frame.ResponseHeaders.Clear();
         await frame.ResponseBody.WriteAsync(Encoding.ASCII.GetBytes("Hello "), 0, 6);
         await frame.ResponseBody.WriteAsync(Encoding.ASCII.GetBytes("World!"), 0, 6);
     }))
     {
         using (var connection = new TestConnection())
         {
             await connection.SendEnd(
                 "GET / HTTP/1.1",
                 "",
                 "");
             await connection.ReceiveEnd(
                 "HTTP/1.1 200 OK",
                 "Transfer-Encoding: chunked",
                 "",
                 "6",
                 "Hello ",
                 "6",
                 "World!",
                 "0",
                 "",
                 "");
         }
     }
 }
        public async Task ThrowingResultsIn500Response(ServiceContext testContext)
        {
            bool onStartingCalled = false;

            var testLogger = new TestApplicationErrorLogger();

            testContext.Log = new KestrelTrace(testLogger);

            using (var server = new TestServer(frame =>
            {
                var response = frame.Get <IHttpResponseFeature>();
                response.OnStarting(_ =>
                {
                    onStartingCalled = true;
                    return(Task.FromResult <object>(null));
                }, null);

                // Anything added to the ResponseHeaders dictionary is ignored
                response.Headers.Clear();
                response.Headers["Content-Length"] = "11";
                throw new Exception();
            }, testContext))
            {
                using (var connection = new TestConnection())
                {
                    await connection.SendEnd(
                        "GET / HTTP/1.1",
                        "",
                        "GET / HTTP/1.1",
                        "Connection: close",
                        "",
                        "");

                    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",
                        "",
                        "");

                    Assert.False(onStartingCalled);
                    Assert.Equal(2, testLogger.ApplicationErrorsLogged);
                }
            }
        }
        public async Task ZeroLengthWritesAreIgnored()
        {
            using (var server = new TestServer(async frame =>
            {
                var response = frame.Get <IHttpResponseFeature>();
                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);
            }))
            {
                using (var connection = new TestConnection())
                {
                    await connection.SendEnd(
                        "GET / HTTP/1.1",
                        "",
                        "");

                    await connection.ReceiveEnd(
                        "HTTP/1.1 200 OK",
                        "Transfer-Encoding: chunked",
                        "",
                        "6",
                        "Hello ",
                        "6",
                        "World!",
                        "0",
                        "",
                        "");
                }
            }
        }
        public async Task ConnectionClosedIfExeptionThrownAfterZeroLengthWrite()
        {
            using (var server = new TestServer(async frame =>
            {
                var response = frame.Get <IHttpResponseFeature>();
                response.Headers.Clear();
                await response.Body.WriteAsync(new byte[0], 0, 0);
                throw new Exception();
            }))
            {
                using (var connection = new TestConnection())
                {
                    // SendEnd is not called, so it isn't the client closing the connection.
                    await connection.Send(
                        "GET / HTTP/1.1",
                        "",
                        "");

                    // Headers are sent before connection is closed, but chunked body terminator isn't sent
                    await connection.ReceiveEnd(
                        "HTTP/1.1 200 OK",
                        "Transfer-Encoding: chunked",
                        "",
                        "");
                }
            }
        }
        public async Task ConnectionClosedIfExeptionThrownAfterWrite()
        {
            using (var server = new TestServer(async frame =>
            {
                var response = frame.Get <IHttpResponseFeature>();
                response.Headers.Clear();
                await response.Body.WriteAsync(Encoding.ASCII.GetBytes("Hello World!"), 0, 12);
                throw new Exception();
            }))
            {
                using (var connection = new TestConnection())
                {
                    // SendEnd is not called, so it isn't the client closing the connection.
                    // client closing the connection.
                    await connection.Send(
                        "GET / HTTP/1.1",
                        "",
                        "");

                    await connection.ReceiveEnd(
                        "HTTP/1.1 200 OK",
                        "Transfer-Encoding: chunked",
                        "",
                        "c",
                        "Hello World!",
                        "");
                }
            }
        }
Beispiel #7
0
        public async Task ResponsesAreChunkedAutomatically()
        {
            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);
            }))
            {
                using (var connection = new TestConnection())
                {
                    await connection.SendEnd(
                        "GET / HTTP/1.1",
                        "",
                        "");

                    await connection.ReceiveEnd(
                        "HTTP/1.1 200 OK",
                        "Transfer-Encoding: chunked",
                        "",
                        "6",
                        "Hello ",
                        "6",
                        "World!",
                        "0",
                        "",
                        "");
                }
            }
        }
        public async Task EmptyResponseBodyHandledCorrectlyWithZeroLengthWrite()
        {
            using (var server = new TestServer(async frame =>
            {
                var response = frame.Get <IHttpResponseFeature>();
                response.Headers.Clear();
                await response.Body.WriteAsync(new byte[0], 0, 0);
            }))
            {
                using (var connection = new TestConnection())
                {
                    await connection.SendEnd(
                        "GET / HTTP/1.1",
                        "",
                        "");

                    await connection.ReceiveEnd(
                        "HTTP/1.1 200 OK",
                        "Transfer-Encoding: chunked",
                        "",
                        "0",
                        "",
                        "");
                }
            }
        }
Beispiel #9
0
        public async Task ZeroContentLengthSetAutomaticallyAfterNoWrites(ServiceContext testContext)
        {
            using (var server = new TestServer(EmptyApp, testContext))
            {
                using (var connection = new TestConnection())
                {
                    await connection.SendEnd(
                        "GET / HTTP/1.1",
                        "",
                        "GET / HTTP/1.0",
                        "Connection: keep-alive",
                        "",
                        "");

                    await connection.ReceiveEnd(
                        "HTTP/1.1 200 OK",
                        "Content-Length: 0",
                        "",
                        "HTTP/1.0 200 OK",
                        "Connection: keep-alive",
                        "Content-Length: 0",
                        "",
                        "");
                }
            }
        }
        public async Task Http10KeepAlive()
        {
            using (var server = new TestServer(AppChunked))
            {
                using (var connection = new TestConnection())
                {
                    await connection.SendEnd(
                        "GET / HTTP/1.0",
                        "Connection: keep-alive",
                        "",
                        "POST / HTTP/1.0",
                        "",
                        "Goodbye");

                    await connection.Receive(
                        "HTTP/1.0 200 OK",
                        "Content-Length: 0",
                        "Connection: keep-alive",
                        "\r\n");

                    await connection.ReceiveEnd(
                        "HTTP/1.0 200 OK",
                        "Content-Length: 7",
                        "",
                        "Goodbye");
                }
            }
        }
        public async Task DisconnectingClient()
        {
            using (var server = new TestServer(App))
            {
                var socket = new Socket(SocketType.Stream, ProtocolType.IP);
                socket.Connect(IPAddress.Loopback, 54321);
                await Task.Delay(200);

                socket.Disconnect(false);
                socket.Dispose();

                await Task.Delay(200);

                using (var connection = new TestConnection())
                {
                    await connection.SendEnd(
                        "GET / HTTP/1.0",
                        "\r\n");

                    await connection.ReceiveEnd(
                        "HTTP/1.0 200 OK",
                        "\r\n");
                }
            }
        }
Beispiel #12
0
        public async Task ConnectionClosesWhenFinReceived(ServiceContext testContext)
        {
            using (var server = new TestServer(AppChunked, testContext))
            {
                using (var connection = new TestConnection())
                {
                    await connection.SendEnd(
                        "GET / HTTP/1.1",
                        "",
                        "Post / HTTP/1.1",
                        "Content-Length: 7",
                        "",
                        "Goodbye");

                    await connection.ReceiveEnd(
                        "HTTP/1.1 200 OK",
                        "Content-Length: 0",
                        "",
                        "HTTP/1.1 200 OK",
                        "Content-Length: 7",
                        "",
                        "Goodbye");
                }
            }
        }
        public async Task Http10KeepAliveTransferEncoding()
        {
            using (var server = new TestServer(AppChunked))
            {
                using (var connection = new TestConnection())
                {
                    await connection.SendEnd(
                        "POST / HTTP/1.0",
                        "Transfer-Encoding: chunked",
                        "Connection: keep-alive",
                        "",
                        "5", "Hello", "6", " World", "0",
                        "POST / HTTP/1.0",
                        "",
                        "Goodbye");

                    await connection.Receive(
                        "HTTP/1.0 200 OK",
                        "Content-Length: 11",
                        "Connection: keep-alive",
                        "",
                        "Hello World");

                    await connection.ReceiveEnd(
                        "HTTP/1.0 200 OK",
                        "Content-Length: 7",
                        "",
                        "Goodbye");
                }
            }
        }
Beispiel #14
0
        public async Task ZeroContentLengthNotSetAutomaticallyForNonKeepAliveRequests(ServiceContext testContext)
        {
            using (var server = new TestServer(EmptyApp, testContext))
            {
                using (var connection = new TestConnection())
                {
                    await connection.SendEnd(
                        "GET / HTTP/1.1",
                        "Connection: close",
                        "",
                        "");

                    await connection.ReceiveEnd(
                        "HTTP/1.1 200 OK",
                        "Connection: close",
                        "",
                        "");
                }

                using (var connection = new TestConnection())
                {
                    await connection.SendEnd(
                        "GET / HTTP/1.0",
                        "",
                        "");

                    await connection.ReceiveEnd(
                        "HTTP/1.0 200 OK",
                        "",
                        "");
                }
            }
        }
Beispiel #15
0
        public async Task Http10KeepAliveContentLength(ServiceContext testContext)
        {
            using (var server = new TestServer(AppChunked, testContext))
            {
                using (var connection = new TestConnection())
                {
                    await connection.SendEnd(
                        "POST / HTTP/1.0",
                        "Content-Length: 11",
                        "Connection: keep-alive",
                        "",
                        "Hello WorldPOST / HTTP/1.0",
                        "",
                        "Goodbye");

                    await connection.Receive(
                        "HTTP/1.0 200 OK",
                        "Connection: keep-alive",
                        "Content-Length: 11",
                        "",
                        "Hello World");

                    await connection.ReceiveEnd(
                        "HTTP/1.0 200 OK",
                        "Content-Length: 7",
                        "",
                        "Goodbye");
                }
            }
        }
Beispiel #16
0
        public async Task Http10KeepAliveNotUsedIfResponseContentLengthNotSet(ServiceContext testContext)
        {
            using (var server = new TestServer(App, testContext))
            {
                using (var connection = new TestConnection())
                {
                    await connection.SendEnd(
                        "GET / HTTP/1.0",
                        "Connection: keep-alive",
                        "",
                        "POST / HTTP/1.0",
                        "Content-Length: 7",
                        "Connection: keep-alive",
                        "",
                        "Goodbye");

                    await connection.Receive(
                        "HTTP/1.0 200 OK",
                        "Connection: keep-alive",
                        "Content-Length: 0",
                        "\r\n");

                    await connection.ReceiveEnd(
                        "HTTP/1.0 200 OK",
                        "",
                        "Goodbye");
                }
            }
        }
        public async Task Http11()
        {
            using (var server = new TestServer(AppChunked))
            {
                using (var connection = new TestConnection())
                {
                    await connection.SendEnd(
                        "GET / HTTP/1.1",
                        "",
                        "GET / HTTP/1.1",
                        "Connection: close",
                        "",
                        "Goodbye");

                    await connection.ReceiveEnd(
                        "HTTP/1.1 200 OK",
                        "Content-Length: 0",
                        "",
                        "HTTP/1.1 200 OK",
                        "Content-Length: 7",
                        "Connection: close",
                        "",
                        "Goodbye");
                }
            }
        }
 public async Task ZeroLengthWritesAreIgnored()
 {
     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);
     }))
     {
         using (var connection = new TestConnection())
         {
             await connection.SendEnd(
                 "GET / HTTP/1.1",
                 "",
                 "");
             await connection.ReceiveEnd(
                 "HTTP/1.1 200 OK",
                 "Transfer-Encoding: chunked",
                 "",
                 "6",
                 "Hello ",
                 "6",
                 "World!",
                 "0",
                 "",
                 "");
         }
     }
 }
        public async Task CanReadAndWriteWithRewritingConnectionFilter()
        {
            var filter         = new RewritingConnectionFilter();
            var serviceContext = new TestServiceContext()
            {
                ConnectionFilter = filter
            };
            var sendString = "POST / HTTP/1.0\r\n\r\nHello World?";

            using (var server = new TestServer(App, serviceContext))
            {
                using (var connection = new TestConnection())
                {
                    // "?" changes to "!"
                    await connection.SendEnd(sendString);

                    await connection.ReceiveEnd(
                        "HTTP/1.0 200 OK",
                        "",
                        "Hello World!");
                }
            }

            Assert.Equal(sendString.Length, filter.BytesRead);
        }
        public async Task ThrowingResultsIn500Response()
        {
            bool onStartingCalled = false;

            using (var server = new TestServer(frame =>
            {
                frame.OnStarting(_ =>
                {
                    onStartingCalled = true;
                    return(Task.FromResult <object>(null));
                }, null);

                // Anything added to the ResponseHeaders dictionary is ignored
                frame.ResponseHeaders.Clear();
                frame.ResponseHeaders["Content-Length"] = new[] { "11" };
                throw new Exception();
            }))
            {
                using (var connection = new TestConnection())
                {
                    await connection.SendEnd(
                        "GET / HTTP/1.1",
                        "",
                        "GET / HTTP/1.1",
                        "Connection: close",
                        "",
                        "");

                    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",
                        "",
                        "");

                    Assert.False(onStartingCalled);
                }
            }
        }
        public async Task ThrowingInOnStartingResultsIn500Response()
        {
            using (var server = new TestServer(frame =>
            {
                frame.OnStarting(_ =>
                {
                    throw new Exception();
                }, null);

                frame.ResponseHeaders.Clear();
                frame.ResponseHeaders["Content-Length"] = new[] { "11" };

                // If we write to the response stream, we will not get a 500.

                return(Task.FromResult <object>(null));
            }))
            {
                using (var connection = new TestConnection())
                {
                    await connection.SendEnd(
                        "GET / HTTP/1.1",
                        "",
                        "GET / HTTP/1.1",
                        "Connection: close",
                        "",
                        "");

                    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",
                        "",
                        "");
                }
            }
        }
Beispiel #22
0
        public async Task ZeroContentLengthNotSetAutomaticallyForCertainStatusCodes(ServiceContext testContext)
        {
            using (var server = new TestServer(async httpContext =>
            {
                var request = httpContext.Request;
                var response = httpContext.Response;
                response.Headers.Clear();

                using (var reader = new StreamReader(request.Body, Encoding.ASCII))
                {
                    var statusString = await reader.ReadLineAsync();
                    response.StatusCode = int.Parse(statusString);
                }
            }, testContext))
            {
                using (var connection = new TestConnection())
                {
                    await connection.SendEnd(
                        "POST / HTTP/1.1",
                        "Content-Length: 3",
                        "",
                        "101POST / HTTP/1.1",
                        "Content-Length: 3",
                        "",
                        "204POST / HTTP/1.1",
                        "Content-Length: 3",
                        "",
                        "205POST / HTTP/1.1",
                        "Content-Length: 3",
                        "",
                        "304POST / HTTP/1.1",
                        "Content-Length: 3",
                        "",
                        "200");

                    await connection.ReceiveEnd(
                        "HTTP/1.1 101 Switching Protocols",
                        "",
                        "HTTP/1.1 204 No Content",
                        "",
                        "HTTP/1.1 205 Reset Content",
                        "",
                        "HTTP/1.1 304 Not Modified",
                        "",
                        "HTTP/1.1 200 OK",
                        "Content-Length: 0",
                        "",
                        "");
                }
            }
        }
Beispiel #23
0
        public async Task ThrowingInOnCompletedIsLoggedAndClosesConnection(ServiceContext testContext)
        {
            var onCompletedCalled1 = false;
            var onCompletedCalled2 = false;

            var testLogger = new TestApplicationErrorLogger();

            testContext.Log = new KestrelTrace(testLogger);

            using (var server = new TestServer(async httpContext =>
            {
                var response = httpContext.Response;
                response.OnCompleted(_ =>
                {
                    onCompletedCalled1 = true;
                    throw new Exception();
                }, null);
                response.OnCompleted(_ =>
                {
                    onCompletedCalled2 = true;
                    throw new Exception();
                }, null);

                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())
                {
                    await connection.Send(
                        "GET / HTTP/1.1",
                        "",
                        "");

                    await connection.ReceiveEnd(
                        "HTTP/1.1 200 OK",
                        "Content-Length: 11",
                        "",
                        "Hello World");
                }

                // All OnCompleted callbacks should be called even if they throw.
                Assert.Equal(2, testLogger.ApplicationErrorsLogged);
                Assert.True(onCompletedCalled1);
                Assert.True(onCompletedCalled2);
            }
        }
        public async Task Http10()
        {
            using (var server = new TestServer(App))
            {
                using (var connection = new TestConnection())
                {
                    await connection.SendEnd(
                        "POST / HTTP/1.0",
                        "",
                        "Hello World");

                    await connection.ReceiveEnd(
                        "HTTP/1.0 200 OK",
                        "",
                        "Hello World");
                }
            }
        }
Beispiel #25
0
        public async Task ZeroContentLengthNotSetAutomaticallyForHeadRequests(ServiceContext testContext)
        {
            using (var server = new TestServer(EmptyApp, testContext))
            {
                using (var connection = new TestConnection())
                {
                    await connection.SendEnd(
                        "HEAD / HTTP/1.1",
                        "",
                        "");

                    await connection.ReceiveEnd(
                        "HTTP/1.1 200 OK",
                        "",
                        "");
                }
            }
        }
Beispiel #26
0
        public async Task RequestBodyIsConsumedAutomaticallyIfAppDoesntConsumeItFully(ServiceContext testContext)
        {
            using (var server = new TestServer(async httpContext =>
            {
                var response = httpContext.Response;
                var request = httpContext.Request;

                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())
                {
                    await connection.SendEnd(
                        "POST / HTTP/1.1",
                        "Content-Length: 5",
                        "",
                        "HelloPOST / HTTP/1.1",
                        "Transfer-Encoding: chunked",
                        "",
                        "C", "HelloChunked", "0",
                        "POST / HTTP/1.1",
                        "Content-Length: 7",
                        "",
                        "Goodbye");

                    await connection.ReceiveEnd(
                        "HTTP/1.1 200 OK",
                        "Content-Length: 11",
                        "",
                        "Hello WorldHTTP/1.1 200 OK",
                        "Content-Length: 11",
                        "",
                        "Hello WorldHTTP/1.1 200 OK",
                        "Content-Length: 11",
                        "",
                        "Hello World");
                }
            }
        }
        public async Task Http10TransferEncoding()
        {
            using (var server = new TestServer(App))
            {
                using (var connection = new TestConnection())
                {
                    await connection.Send(
                        "POST / HTTP/1.0",
                        "Transfer-Encoding: chunked",
                        "",
                        "5", "Hello", "6", " World", "0\r\n");

                    await connection.ReceiveEnd(
                        "HTTP/1.0 200 OK",
                        "",
                        "Hello World");
                }
            }
        }
Beispiel #28
0
        public async Task Http10ContentLength(ServiceContext testContext)
        {
            using (var server = new TestServer(App, testContext))
            {
                using (var connection = new TestConnection())
                {
                    await connection.Send(
                        "POST / HTTP/1.0",
                        "Content-Length: 11",
                        "",
                        "Hello World");

                    await connection.ReceiveEnd(
                        "HTTP/1.0 200 OK",
                        "",
                        "Hello World");
                }
            }
        }
        public async Task ConnectionClosesWhenFinReceivedBeforeRequestCompletes()
        {
            using (var server = new TestServer(AppChunked))
            {
                using (var connection = new TestConnection())
                {
                    await connection.SendEnd(
                        "GET /");

                    await connection.ReceiveEnd();
                }

                using (var connection = new TestConnection())
                {
                    await connection.SendEnd(
                        "GET / HTTP/1.1",
                        "",
                        "Post / HTTP/1.1");

                    await connection.ReceiveEnd(
                        "HTTP/1.1 200 OK",
                        "Content-Length: 0",
                        "",
                        "");
                }

                using (var connection = new TestConnection())
                {
                    await connection.SendEnd(
                        "GET / HTTP/1.1",
                        "",
                        "Post / HTTP/1.1",
                        "Content-Length: 7");

                    await connection.ReceiveEnd(
                        "HTTP/1.1 200 OK",
                        "Content-Length: 0",
                        "",
                        "");
                }
            }
        }
Beispiel #30
0
        public async Task ThrowingAfterPartialWriteKillsConnection(ServiceContext testContext)
        {
            bool onStartingCalled = false;

            var testLogger = new TestApplicationErrorLogger();

            testContext.Log = new KestrelTrace(testLogger);

            using (var server = new TestServer(async httpContext =>
            {
                var response = httpContext.Response;
                response.OnStarting(_ =>
                {
                    onStartingCalled = true;
                    return(Task.FromResult <object>(null));
                }, null);

                response.Headers.Clear();
                response.Headers["Content-Length"] = new[] { "11" };
                await response.Body.WriteAsync(Encoding.ASCII.GetBytes("Hello"), 0, 5);
                throw new Exception();
            }, testContext))
            {
                using (var connection = new TestConnection())
                {
                    await connection.Send(
                        "GET / HTTP/1.1",
                        "",
                        "");

                    await connection.ReceiveEnd(
                        "HTTP/1.1 200 OK",
                        "Content-Length: 11",
                        "",
                        "Hello");

                    Assert.True(onStartingCalled);
                    Assert.Equal(1, testLogger.ApplicationErrorsLogged);
                }
            }
        }
Beispiel #31
0
        public async Task ReuseStreamsOff(ServiceContext testContext)
        {
            testContext.ReuseStreams = false;

            var    streamCount = 0;
            var    loopCount   = 20;
            Stream lastStream  = null;

            using (var server = new TestServer(
                       context =>
            {
                if (context.Request.Body != lastStream)
                {
                    lastStream = context.Request.Body;
                    streamCount++;
                }
                context.Response.Headers.Clear();
                return(context.Request.Body.CopyToAsync(context.Response.Body));
            },
                       testContext))
            {
                using (var connection = new TestConnection())
                {
                    var requestData =
                        Enumerable.Repeat("GET / HTTP/1.1\r\n", loopCount)
                        .Concat(new[] { "GET / HTTP/1.1\r\nConnection: close\r\n\r\nGoodbye" });

                    var responseData =
                        Enumerable.Repeat("HTTP/1.1 200 OK\r\nContent-Length: 0\r\n", loopCount)
                        .Concat(new[] { "HTTP/1.1 200 OK\r\nConnection: close\r\n\r\nGoodbye" });

                    await connection.SendEnd(requestData.ToArray());

                    await connection.ReceiveEnd(responseData.ToArray());
                }

                Assert.Equal(loopCount + 1, streamCount);
            }
        }
        public async Task CanReadAndWriteWithAsyncConnectionFilter()
        {
            var serviceContext = new TestServiceContext()
            {
                ConnectionFilter = new AsyncConnectionFilter()
            };

            using (var server = new TestServer(App, serviceContext))
            {
                using (var connection = new TestConnection())
                {
                    await connection.SendEnd(
                        "POST / HTTP/1.0",
                        "",
                        "Hello World?");
                    await connection.ReceiveEnd(
                        "HTTP/1.0 200 OK",
                        "",
                        "Hello World!");
                }
            }
       }
        public async Task CanReadAndWriteWithAsyncConnectionFilter()
        {
            var serviceContext = new TestServiceContext()
            {
                ConnectionFilter = new AsyncConnectionFilter()
            };

            using (var server = new TestServer(App, serviceContext))
            {
                using (var connection = new TestConnection())
                {
                    await connection.SendEnd(
                        "POST / HTTP/1.0",
                        "",
                        "Hello World?");

                    await connection.ReceiveEnd(
                        "HTTP/1.0 200 OK",
                        "",
                        "Hello World!");
                }
            }
        }
        public async Task CanReadAndWriteWithRewritingConnectionFilter()
        {
            var filter = new RewritingConnectionFilter();
            var serviceContext = new TestServiceContext()
            {
                ConnectionFilter = filter
            };
            var sendString = "POST / HTTP/1.0\r\n\r\nHello World?";

            using (var server = new TestServer(App, serviceContext))
            {
                using (var connection = new TestConnection())
                {
                    // "?" changes to "!"
                    await connection.SendEnd(sendString);
                    await connection.ReceiveEnd(
                        "HTTP/1.0 200 OK",
                        "",
                        "Hello World!");
                }
            }

            Assert.Equal(sendString.Length, filter.BytesRead);
        }
        public async Task ConnectionClosesWhenFinReceivedBeforeRequestCompletes()
        {
            using (var server = new TestServer(AppChunked))
            {
                using (var connection = new TestConnection())
                {
                    await connection.SendEnd(
                        "GET /");
                    await connection.ReceiveEnd();
                }

                using (var connection = new TestConnection())
                {
                    await connection.SendEnd(
                        "GET / HTTP/1.1",
                        "",
                        "Post / HTTP/1.1");
                    await connection.ReceiveEnd(
                        "HTTP/1.1 200 OK",
                        "Content-Length: 0",
                        "",
                        "");
                }

                using (var connection = new TestConnection())
                {
                    await connection.SendEnd(
                        "GET / HTTP/1.1",
                        "",
                        "Post / HTTP/1.1",
                        "Content-Length: 7");
                    await connection.ReceiveEnd(
                        "HTTP/1.1 200 OK",
                        "Content-Length: 0",
                        "",
                        "");
                }
            }
        }
        public async Task ThrowingResultsIn500Response()
        {
            bool onStartingCalled = false;

            using (var server = new TestServer(frame =>
            {
                frame.OnStarting(_ =>
                {
                    onStartingCalled = true;
                    return Task.FromResult<object>(null);
                }, null);

                // Anything added to the ResponseHeaders dictionary is ignored
                frame.ResponseHeaders.Clear();
                frame.ResponseHeaders["Content-Length"] = new[] { "11" };
                throw new Exception();
            }))
            {
                using (var connection = new TestConnection())
                {
                    await connection.SendEnd(
                        "GET / HTTP/1.1",
                        "",
                        "GET / HTTP/1.1",
                        "Connection: close",
                        "",
                        "");
                    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",
                        "",
                        "");

                    Assert.False(onStartingCalled);
                }
            }
        }
 public async Task ZeroContentLengthNotSetAutomaticallyForHeadRequests()
 {
     using (var server = new TestServer(EmptyApp))
     {
         using (var connection = new TestConnection())
         {
             await connection.SendEnd(
                 "HEAD / HTTP/1.1",
                 "",
                 "");
             await connection.ReceiveEnd(
                 "HTTP/1.1 200 OK",
                 "",
                 "");
         }
     }
 }
 public async Task ZeroContentLengthSetAutomaticallyAfterNoWrites()
 {
     using (var server = new TestServer(EmptyApp))
     {
         using (var connection = new TestConnection())
         {
             await connection.SendEnd(
                 "GET / HTTP/1.1",
                 "",
                 "GET / HTTP/1.0",
                 "Connection: keep-alive",
                 "",
                 "");
             await connection.ReceiveEnd(
                 "HTTP/1.1 200 OK",
                 "Content-Length: 0",
                 "",
                 "HTTP/1.0 200 OK",
                 "Content-Length: 0",
                 "Connection: keep-alive",
                 "",
                 "");
         }
     }
 }
 public async Task Http10KeepAliveTransferEncoding()
 {
     using (var server = new TestServer(AppChunked))
     {
         using (var connection = new TestConnection())
         {
             await connection.SendEnd(
                 "POST / HTTP/1.0",
                 "Transfer-Encoding: chunked",
                 "Connection: keep-alive",
                 "",
                 "5", "Hello", "6", " World", "0",
                 "POST / HTTP/1.0",
                 "",
                 "Goodbye");
             await connection.Receive(
                 "HTTP/1.0 200 OK",
                 "Content-Length: 11",
                 "Connection: keep-alive",
                 "",
                 "Hello World");
             await connection.ReceiveEnd(
                 "HTTP/1.0 200 OK",
                 "Content-Length: 7",
                 "",
                 "Goodbye");
         }
     }
 }
 public async Task Http10TransferEncoding()
 {
     using (var server = new TestServer(App))
     {
         using (var connection = new TestConnection())
         {
             await connection.Send(
                 "POST / HTTP/1.0",
                 "Transfer-Encoding: chunked",
                 "",
                 "5", "Hello", "6", " World", "0\r\n");
             await connection.ReceiveEnd(
                 "HTTP/1.0 200 OK",
                 "",
                 "Hello World");
         }
     }
 }
 public async Task Http11()
 {
     using (var server = new TestServer(AppChunked))
     {
         using (var connection = new TestConnection())
         {
             await connection.SendEnd(
                 "GET / HTTP/1.1",
                 "",
                 "GET / HTTP/1.1",
                 "Connection: close",
                 "",
                 "Goodbye");
             await connection.ReceiveEnd(
                 "HTTP/1.1 200 OK",
                 "Content-Length: 0",
                 "",
                 "HTTP/1.1 200 OK",
                 "Content-Length: 7",
                 "Connection: close",
                 "",
                 "Goodbye");
         }
     }
 }
        public async Task ConnectionClosedIfExeptionThrownAfterZeroLengthWrite()
        {
            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();
            }))
            {
                using (var connection = new TestConnection())
                {
                    // SendEnd is not called, so it isn't the client closing the connection.
                    await connection.Send(
                        "GET / HTTP/1.1",
                        "",
                        "");

                    // Headers are sent before connection is closed, but chunked body terminator isn't sent
                    await connection.ReceiveEnd(
                        "HTTP/1.1 200 OK",
                        "Transfer-Encoding: chunked",
                        "",
                        "");
                }
            }
        }
 public async Task ConnectionClosedIfExeptionThrownAfterWrite()
 {
     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();
     }))
     {
         using (var connection = new TestConnection())
         {
             // SendEnd is not called, so it isn't the client closing the connection.
             // client closing the connection.
             await connection.Send(
                 "GET / HTTP/1.1",
                 "",
                 "");
             await connection.ReceiveEnd(
                 "HTTP/1.1 200 OK",
                 "Transfer-Encoding: chunked",
                 "",
                 "c",
                 "Hello World!",
                 "");
         }
     }
 }
        public async Task ThrowingInOnCompletedIsLoggedAndClosesConnection(ServiceContext testContext)
        {
            var onCompletedCalled1 = false;
            var onCompletedCalled2 = false;

            var testLogger = new TestApplicationErrorLogger();
            testContext.Log = new KestrelTrace(testLogger);

            using (var server = new TestServer(async frame =>
            {
                var response = frame.Get<IHttpResponseFeature>();
                response.OnCompleted(_ =>
                {
                    onCompletedCalled1 = true;
                    throw new Exception();
                }, null);
                response.OnCompleted(_ =>
                {
                    onCompletedCalled2 = true;
                    throw new Exception();
                }, null);

                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())
                {
                    await connection.Send(
                        "GET / HTTP/1.1",
                        "",
                        "");
                    await connection.ReceiveEnd(
                        "HTTP/1.1 200 OK",
                        "Content-Length: 11",
                        "",
                        "Hello World");
                }

                // All OnCompleted callbacks should be called even if they throw.
                Assert.Equal(2, testLogger.ApplicationErrorsLogged);
                Assert.True(onCompletedCalled1);
                Assert.True(onCompletedCalled2);
            }
        }
        public async Task RequestBodyIsConsumedAutomaticallyIfAppDoesntConsumeItFully(ServiceContext testContext)
        {
            using (var server = new TestServer(async frame =>
            {
                var response = frame.Get<IHttpResponseFeature>();
                var request = frame.Get<IHttpRequestFeature>();

                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())
                {
                    await connection.SendEnd(
                        "POST / HTTP/1.1",
                        "Content-Length: 5",
                        "",
                        "HelloPOST / HTTP/1.1",
                        "Transfer-Encoding: chunked",
                        "",
                        "C", "HelloChunked", "0",
                        "POST / HTTP/1.1",
                        "Content-Length: 7",
                        "",
                        "Goodbye");
                    await connection.ReceiveEnd(
                        "HTTP/1.1 200 OK",
                        "Content-Length: 11",
                        "",
                        "Hello WorldHTTP/1.1 200 OK",
                        "Content-Length: 11",
                        "",
                        "Hello WorldHTTP/1.1 200 OK",
                        "Content-Length: 11",
                        "",
                        "Hello World");
                }
            }
        }
 public async Task EmptyResponseBodyHandledCorrectlyWithZeroLengthWrite()
 {
     using (var server = new TestServer(async httpContext =>
     {
         var response = httpContext.Response;
         response.Headers.Clear();
         await response.Body.WriteAsync(new byte[0], 0, 0);
     }))
     {
         using (var connection = new TestConnection())
         {
             await connection.SendEnd(
                 "GET / HTTP/1.1",
                 "",
                 "");
             await connection.ReceiveEnd(
                 "HTTP/1.1 200 OK",
                 "Transfer-Encoding: chunked",
                 "",
                 "0",
                 "",
                 "");
         }
     }
 }
 public async Task Http10ContentLength()
 {
     using (var server = new TestServer(App))
     {
         using (var connection = new TestConnection())
         {
             await connection.Send(
                 "POST / HTTP/1.0",
                 "Content-Length: 11",
                 "",
                 "Hello World");
             await connection.ReceiveEnd(
                 "HTTP/1.0 200 OK",
                 "",
                 "Hello World");
         }
     }
 }
 public async Task Http10(ServiceContext testContext)
 {
     using (var server = new TestServer(App, testContext))
     {
         using (var connection = new TestConnection())
         {
             await connection.SendEnd(
                 "POST / HTTP/1.0",
                 "",
                 "Hello World");
             await connection.ReceiveEnd(
                 "HTTP/1.0 200 OK",
                 "",
                 "Hello World");
         }
     }
 }
 public async Task Http10KeepAliveNotUsedIfResponseContentLengthNotSet()
 {
     using (var server = new TestServer(App))
     {
         using (var connection = new TestConnection())
         {
             await connection.SendEnd(
                 "GET / HTTP/1.0",
                 "Connection: keep-alive",
                 "",
                 "POST / HTTP/1.0",
                 "Connection: keep-alive",
                 "Content-Length: 7",
                 "",
                 "Goodbye");
             await connection.Receive(
                 "HTTP/1.0 200 OK",
                 "Content-Length: 0",
                 "Connection: keep-alive",
                 "\r\n");
             await connection.ReceiveEnd(
                 "HTTP/1.0 200 OK",
                 "",
                 "Goodbye");
         }
     }
 }
 public async Task Http10KeepAliveContentLength(ServiceContext testContext)
 {
     using (var server = new TestServer(AppChunked, testContext))
     {
         using (var connection = new TestConnection())
         {
             await connection.SendEnd(
                 "POST / HTTP/1.0",
                 "Connection: keep-alive",
                 "Content-Length: 11",
                 "",
                 "Hello WorldPOST / HTTP/1.0",
                 "",
                 "Goodbye");
             await connection.Receive(
                 "HTTP/1.0 200 OK",
                 "Content-Length: 11",
                 "Connection: keep-alive",
                 "",
                 "Hello World");
             await connection.ReceiveEnd(
                 "HTTP/1.0 200 OK",
                 "Content-Length: 7",
                 "",
                 "Goodbye");
         }
     }
 }
        public async Task DisconnectingClient()
        {
            using (var server = new TestServer(App))
            {
                var socket = new Socket(SocketType.Stream, ProtocolType.IP);
                socket.Connect(IPAddress.Loopback, 54321);
                await Task.Delay(200);
                socket.Disconnect(false);
                socket.Dispose();

                await Task.Delay(200);
                using (var connection = new TestConnection())
                {
                    await connection.SendEnd(
                        "GET / HTTP/1.0",
                        "\r\n");
                    await connection.ReceiveEnd(
                        "HTTP/1.0 200 OK",
                        "\r\n");
                }
            }
        }
        public async Task ThrowingResultsIn500Response(ServiceContext testContext)
        {
            bool onStartingCalled = false;

            var testLogger = new TestApplicationErrorLogger();
            testContext.Log = new KestrelTrace(testLogger);

            using (var server = new TestServer(frame =>
            {
                var response = frame.Get<IHttpResponseFeature>();
                response.OnStarting(_ =>
                {
                    onStartingCalled = true;
                    return Task.FromResult<object>(null);
                }, null);

                // Anything added to the ResponseHeaders dictionary is ignored
                response.Headers.Clear();
                response.Headers["Content-Length"] = "11";
                throw new Exception();
            }, testContext))
            {
                using (var connection = new TestConnection())
                {
                    await connection.SendEnd(
                        "GET / HTTP/1.1",
                        "",
                        "GET / HTTP/1.1",
                        "Connection: close",
                        "",
                        "");
                    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",
                        "",
                        "");

                    Assert.False(onStartingCalled);
                    Assert.Equal(2, testLogger.ApplicationErrorsLogged);
                }
            }
        }
        public async Task ZeroContentLengthNotSetAutomaticallyForNonKeepAliveRequests()
        {
            using (var server = new TestServer(EmptyApp))
            {
                using (var connection = new TestConnection())
                {
                    await connection.SendEnd(
                        "GET / HTTP/1.1",
                        "Connection: close",
                        "",
                        "");
                    await connection.ReceiveEnd(
                        "HTTP/1.1 200 OK",
                        "Connection: close",
                        "",
                        "");
                }

                using (var connection = new TestConnection())
                {
                    await connection.SendEnd(
                        "GET / HTTP/1.0",
                        "",
                        "");
                    await connection.ReceiveEnd(
                        "HTTP/1.0 200 OK",
                        "",
                        "");
                }
            }
        }
        public async Task ThrowingAfterPartialWriteKillsConnection(ServiceContext testContext)
        {
            bool onStartingCalled = false;

            var testLogger = new TestApplicationErrorLogger();
            testContext.Log = new KestrelTrace(testLogger);

            using (var server = new TestServer(async frame =>
            {
                var response = frame.Get<IHttpResponseFeature>();
                response.OnStarting(_ =>
                {
                    onStartingCalled = true;
                    return Task.FromResult<object>(null);
                }, null);

                response.Headers.Clear();
                response.Headers["Content-Length"] = new[] { "11" };
                await response.Body.WriteAsync(Encoding.ASCII.GetBytes("Hello"), 0, 5);
                throw new Exception();
            }, testContext))
            {
                using (var connection = new TestConnection())
                {
                    await connection.Send(
                        "GET / HTTP/1.1",
                        "",
                        "");
                    await connection.ReceiveEnd(
                        "HTTP/1.1 200 OK",
                        "Content-Length: 11",
                        "",
                        "Hello");

                    Assert.True(onStartingCalled);
                    Assert.Equal(1, testLogger.ApplicationErrorsLogged);
                }
            }
        }
        public async Task ZeroContentLengthNotSetAutomaticallyForCertainStatusCodes()
        {
            using (var server = new TestServer(async frame =>
            {
                frame.ResponseHeaders.Clear();

                using (var reader = new StreamReader(frame.RequestBody, Encoding.ASCII))
                {
                    var statusString = await reader.ReadLineAsync();
                    frame.StatusCode = int.Parse(statusString);
                }
            }))
            {
                using (var connection = new TestConnection())
                {
                    await connection.SendEnd(
                        "POST / HTTP/1.1",
                        "Content-Length: 3",
                        "",
                        "101POST / HTTP/1.1",
                        "Content-Length: 3",
                        "",
                        "204POST / HTTP/1.1",
                        "Content-Length: 3",
                        "",
                        "205POST / HTTP/1.1",
                        "Content-Length: 3",
                        "",
                        "304POST / HTTP/1.1",
                        "Content-Length: 3",
                        "",
                        "200");
                    await connection.ReceiveEnd(
                        "HTTP/1.1 101 Switching Protocols",
                        "",
                        "HTTP/1.1 204 No Content",
                        "",
                        "HTTP/1.1 205 Reset Content",
                        "",
                        "HTTP/1.1 304 Not Modified",
                        "",
                        "HTTP/1.1 200 OK",
                        "Content-Length: 0",
                        "",
                        "");
                }
            }
        }
 public async Task ConnectionClosesWhenFinReceived(ServiceContext testContext)
 {
     using (var server = new TestServer(AppChunked, testContext))
     {
         using (var connection = new TestConnection())
         {
             await connection.SendEnd(
                 "GET / HTTP/1.1",
                 "",
                 "Post / HTTP/1.1",
                 "Content-Length: 7",
                 "",
                 "Goodbye");
             await connection.ReceiveEnd(
                 "HTTP/1.1 200 OK",
                 "Content-Length: 0",
                 "",
                 "HTTP/1.1 200 OK",
                 "Content-Length: 7",
                 "",
                 "Goodbye");
         }
     }
 }
        public async Task ThrowingAfterPartialWriteKillsConnection()
        {
            bool onStartingCalled = false;

            using (var server = new TestServer(async frame =>
            {
                frame.OnStarting(_ =>
                {
                    onStartingCalled = true;
                    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();
            }))
            {
                using (var connection = new TestConnection())
                {
                    await connection.Send(
                        "GET / HTTP/1.1",
                        "",
                        "");
                    await connection.ReceiveEnd(
                        "HTTP/1.1 200 OK",
                        "Content-Length: 11",
                        "",
                        "Hello");

                    Assert.True(onStartingCalled);
                }
            }
        }
        public async Task ThrowingInOnStartingResultsInFailedWritesAnd500Response(ServiceContext testContext)
        {
            var onStartingCallCount1 = 0;
            var onStartingCallCount2 = 0;
            var failedWriteCount = 0;

            var testLogger = new TestApplicationErrorLogger();
            testContext.Log = new KestrelTrace(testLogger);

            using (var server = new TestServer(async frame =>
            {
                var onStartingException = new Exception();

                var response = frame.Get<IHttpResponseFeature>();
                response.OnStarting(_ =>
                {
                    onStartingCallCount1++;
                    throw onStartingException;
                }, null);
                response.OnStarting(_ =>
                {
                    onStartingCallCount2++;
                    throw onStartingException;
                }, null);

                response.Headers.Clear();
                response.Headers["Content-Length"] = new[] { "11" };

                var writeException = await Assert.ThrowsAsync<ObjectDisposedException>(async () =>
                    await response.Body.WriteAsync(Encoding.ASCII.GetBytes("Hello World"), 0, 11));

                Assert.Same(onStartingException, writeException.InnerException);

                failedWriteCount++;
            }, testContext))
            {
                using (var connection = new TestConnection())
                {
                    await connection.SendEnd(
                        "GET / HTTP/1.1",
                        "",
                        "GET / HTTP/1.1",
                        "Connection: close",
                        "",
                        "");
                    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",
                        "",
                        "");

                    Assert.Equal(2, onStartingCallCount1);
                    // The second OnStarting callback should not be called since the first failed.
                    Assert.Equal(0, onStartingCallCount2);
                    Assert.Equal(2, testLogger.ApplicationErrorsLogged);
                }
            }
        }
        public async Task ThrowingInOnStartingResultsIn500Response()
        {
            using (var server = new TestServer(frame =>
            {
                frame.OnStarting(_ =>
                {
                    throw new Exception();
                }, null);

                frame.ResponseHeaders.Clear();
                frame.ResponseHeaders["Content-Length"] = new[] { "11" };

                // If we write to the response stream, we will not get a 500.

                return Task.FromResult<object>(null);
            }))
            {
                using (var connection = new TestConnection())
                {
                    await connection.SendEnd(
                        "GET / HTTP/1.1",
                        "",
                        "GET / HTTP/1.1",
                        "Connection: close",
                        "",
                        "");
                    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",
                        "",
                        "");
                }
            }
        }
        public async Task ConnectionClosedIfExeptionThrownAfterZeroLengthWrite()
        {
            using (var server = new TestServer(async frame =>
            {
                frame.ResponseHeaders.Clear();
                await frame.ResponseBody.WriteAsync(new byte[0], 0, 0);
                throw new Exception();
            }))
            {
                using (var connection = new TestConnection())
                {
                    // SendEnd is not called, so it isn't the client closing the connection.
                    await connection.Send(
                        "GET / HTTP/1.1",
                        "",
                        "");

                    // Nothing (not even headers) are written, but the connection is closed.
                    await connection.ReceiveEnd();
                }
            }
        }