From d0cca519b45da4ac1ff209252d953d8797fd5110 Mon Sep 17 00:00:00 2001 From: Kahbazi Date: Fri, 31 Jul 2020 03:40:58 +0430 Subject: [PATCH] Set ContentLength for TestHost (#24107) --- src/Hosting/TestHost/src/ClientHandler.cs | 13 ++-- .../TestHost/test/ClientHandlerTests.cs | 61 +++++++++++++++++++ 2 files changed, 68 insertions(+), 6 deletions(-) diff --git a/src/Hosting/TestHost/src/ClientHandler.cs b/src/Hosting/TestHost/src/ClientHandler.cs index 5c4a42a5a8..5805493225 100644 --- a/src/Hosting/TestHost/src/ClientHandler.cs +++ b/src/Hosting/TestHost/src/ClientHandler.cs @@ -100,7 +100,7 @@ namespace Microsoft.AspNetCore.TestHost if (request.Version == HttpVersion.Version20) { // https://tools.ietf.org/html/rfc7540 - req.Protocol = HttpProtocol.Http2; + req.Protocol = HttpProtocol.Http2; } else { @@ -142,12 +142,13 @@ namespace Microsoft.AspNetCore.TestHost } req.QueryString = QueryString.FromUriComponent(request.RequestUri); - if (requestContent != null) + // Reading the ContentLength will add it to the Headers‼ + // https://github.com/dotnet/runtime/blob/874399ab15e47c2b4b7c6533cc37d27d47cb5242/src/libraries/System.Net.Http/src/System/Net/Http/Headers/HttpContentHeaders.cs#L68-L87 + _ = requestContent.Headers.ContentLength; + + foreach (var header in requestContent.Headers) { - foreach (var header in requestContent.Headers) - { - req.Headers.Append(header.Key, header.Value.ToArray()); - } + req.Headers.Append(header.Key, header.Value.ToArray()); } req.Body = new AsyncStreamWrapper(reader.AsStream(), () => contextBuilder.AllowSynchronousIO); diff --git a/src/Hosting/TestHost/test/ClientHandlerTests.cs b/src/Hosting/TestHost/test/ClientHandlerTests.cs index e94ffc16f4..3e3406e6f5 100644 --- a/src/Hosting/TestHost/test/ClientHandlerTests.cs +++ b/src/Hosting/TestHost/test/ClientHandlerTests.cs @@ -4,7 +4,9 @@ using System; using System.IO; using System.Linq; +using System.Net; using System.Net.Http; +using System.Text; using System.Threading; using System.Threading.Tasks; using Microsoft.AspNetCore.Builder; @@ -103,6 +105,51 @@ namespace Microsoft.AspNetCore.TestHost return httpClient.GetAsync("http://example.com"); } + [Fact] + public Task ContentLengthWithBodyWorks() + { + var contentBytes = Encoding.UTF8.GetBytes("This is a content!"); + var handler = new ClientHandler(new PathString(""), new DummyApplication(context => + { + Assert.Equal(contentBytes.LongLength, context.Request.ContentLength); + + return Task.CompletedTask; + })); + var httpClient = new HttpClient(handler); + var content = new ByteArrayContent(contentBytes); + + return httpClient.PostAsync("http://example.com", content); + } + + [Fact] + public Task ContentLengthWithNoBodyWorks() + { + var handler = new ClientHandler(new PathString(""), new DummyApplication(context => + { + Assert.Equal(0, context.Request.ContentLength); + + return Task.CompletedTask; + })); + var httpClient = new HttpClient(handler); + + return httpClient.GetAsync("http://example.com"); + } + + [Fact] + public Task ContentLengthWithChunkedTransferEncodingWorks() + { + var handler = new ClientHandler(new PathString(""), new DummyApplication(context => + { + Assert.Null(context.Request.ContentLength); + + return Task.CompletedTask; + })); + + var httpClient = new HttpClient(handler); + + return httpClient.PostAsync("http://example.com", new UnlimitedContent()); + } + [Fact] public async Task ServerTrailersSetOnResponseAfterContentRead() { @@ -566,5 +613,19 @@ namespace Microsoft.AspNetCore.TestHost } } } + + private class UnlimitedContent : HttpContent + { + protected override Task SerializeToStreamAsync(Stream stream, TransportContext context) + { + return Task.CompletedTask; + } + + protected override bool TryComputeLength(out long length) + { + length = -1; + return false; + } + } } }