diff --git a/src/Microsoft.AspNetCore.Server.Kestrel/Internal/Http/Frame.cs b/src/Microsoft.AspNetCore.Server.Kestrel/Internal/Http/Frame.cs index 9e45c3f69..d014f3d2b 100644 --- a/src/Microsoft.AspNetCore.Server.Kestrel/Internal/Http/Frame.cs +++ b/src/Microsoft.AspNetCore.Server.Kestrel/Internal/Http/Frame.cs @@ -242,11 +242,12 @@ public void InitializeStreams(MessageBody messageBody) if (_frameStreams == null) { _frameStreams = new Streams(this); - RequestBody = _frameStreams.RequestBody; - ResponseBody = _frameStreams.ResponseBody; - DuplexStream = _frameStreams.DuplexStream; } + RequestBody = _frameStreams.RequestBody; + ResponseBody = _frameStreams.ResponseBody; + DuplexStream = _frameStreams.DuplexStream; + _frameStreams.RequestBody.StartAcceptingReads(messageBody); _frameStreams.ResponseBody.StartAcceptingWrites(); } diff --git a/test/Microsoft.AspNetCore.Server.Kestrel.FunctionalTests/RequestTests.cs b/test/Microsoft.AspNetCore.Server.Kestrel.FunctionalTests/RequestTests.cs index 487306a38..a01b84f7b 100644 --- a/test/Microsoft.AspNetCore.Server.Kestrel.FunctionalTests/RequestTests.cs +++ b/test/Microsoft.AspNetCore.Server.Kestrel.FunctionalTests/RequestTests.cs @@ -1,7 +1,9 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using System; using System.Globalization; +using System.IO; using System.Net; using System.Net.Http; using System.Net.Sockets; @@ -137,6 +139,51 @@ public async Task DoesNotHangOnConnectionCloseRequest() } } + [Fact] + public async Task StreamsAreNotPersistedAcrossRequests() + { + var requestBodyPersisted = false; + var responseBodyPersisted = false; + + var builder = new WebHostBuilder() + .UseKestrel() + .UseUrls($"http://127.0.0.1:0") + .Configure(app => + { + app.Run(async context => + { + if (context.Request.Body is MemoryStream) + { + requestBodyPersisted = true; + } + + if (context.Response.Body is MemoryStream) + { + responseBodyPersisted = true; + } + + context.Request.Body = new MemoryStream(); + context.Response.Body = new MemoryStream(); + + await context.Response.WriteAsync("hello, world"); + }); + }); + + using (var host = builder.Build()) + { + host.Start(); + + using (var client = new HttpClient { BaseAddress = new Uri($"http://127.0.0.1:{host.GetPort()}") }) + { + await client.GetAsync("/"); + await client.GetAsync("/"); + + Assert.False(requestBodyPersisted); + Assert.False(responseBodyPersisted); + } + } + } + private async Task TestRemoteIPAddress(string registerAddress, string requestAddress, string expectAddress) { var builder = new WebHostBuilder() diff --git a/test/Microsoft.AspNetCore.Server.KestrelTests/FrameTests.cs b/test/Microsoft.AspNetCore.Server.KestrelTests/FrameTests.cs index 52c44bb2b..c7ada3524 100644 --- a/test/Microsoft.AspNetCore.Server.KestrelTests/FrameTests.cs +++ b/test/Microsoft.AspNetCore.Server.KestrelTests/FrameTests.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; +using System.IO; using System.Text; using Microsoft.AspNetCore.Http.Features; using Microsoft.AspNetCore.Server.Kestrel; @@ -453,9 +454,10 @@ public void InitializeHeadersResetsRequestHeaders() var frame = new Frame(application: null, context: connectionContext); frame.InitializeHeaders(); - // Act var originalRequestHeaders = frame.RequestHeaders; frame.RequestHeaders = new FrameRequestHeaders(); + + // Act frame.InitializeHeaders(); // Assert @@ -476,13 +478,47 @@ public void InitializeHeadersResetsResponseHeaders() var frame = new Frame(application: null, context: connectionContext); frame.InitializeHeaders(); - // Act var originalResponseHeaders = frame.ResponseHeaders; frame.ResponseHeaders = new FrameResponseHeaders(); + + // Act frame.InitializeHeaders(); // Assert Assert.Same(originalResponseHeaders, frame.ResponseHeaders); } + + [Fact] + public void InitializeStreamsResetsStreams() + { + // Arrange + var connectionContext = new ConnectionContext() + { + DateHeaderValueManager = new DateHeaderValueManager(), + ServerAddress = ServerAddress.FromUrl("http://localhost:5000"), + ServerOptions = new KestrelServerOptions(), + SocketOutput = new MockSocketOuptut() + }; + var frame = new Frame(application: null, context: connectionContext); + frame.InitializeHeaders(); + + var messageBody = MessageBody.For("HTTP/1.1", (FrameRequestHeaders)frame.RequestHeaders, frame); + frame.InitializeStreams(messageBody); + + var originalRequestBody = frame.RequestBody; + var originalResponseBody = frame.ResponseBody; + var originalDuplexStream = frame.DuplexStream; + frame.RequestBody = new MemoryStream(); + frame.ResponseBody = new MemoryStream(); + frame.DuplexStream = new MemoryStream(); + + // Act + frame.InitializeStreams(messageBody); + + // Assert + Assert.Same(originalRequestBody, frame.RequestBody); + Assert.Same(originalResponseBody, frame.ResponseBody); + Assert.Same(originalDuplexStream, frame.DuplexStream); + } } }