From 7f96eab775d721a3bf8d05be446086dab4b45aae Mon Sep 17 00:00:00 2001 From: "Chris Ross (ASP.NET)" Date: Wed, 11 Oct 2017 15:31:00 -0700 Subject: [PATCH] #381 handle known headers with no value. --- .../RequestProcessing/NativeRequestContext.cs | 2 +- .../Listener/RequestHeaderTests.cs | 51 +++++++++++++++++++ 2 files changed, 52 insertions(+), 1 deletion(-) diff --git a/shared/Microsoft.AspNetCore.HttpSys.Sources/RequestProcessing/NativeRequestContext.cs b/shared/Microsoft.AspNetCore.HttpSys.Sources/RequestProcessing/NativeRequestContext.cs index 45d002e..a0985c8 100644 --- a/shared/Microsoft.AspNetCore.HttpSys.Sources/RequestProcessing/NativeRequestContext.cs +++ b/shared/Microsoft.AspNetCore.HttpSys.Sources/RequestProcessing/NativeRequestContext.cs @@ -259,7 +259,7 @@ private string GetKnowHeaderHelper(HttpSysRequestHeader header, long fixup, Http HttpApiTypes.HTTP_KNOWN_HEADER* pKnownHeader = (&request->Headers.KnownHeaders) + headerIndex; // For known headers, when header value is empty, RawValueLength will be 0 and // pRawValue will point to empty string ("\0") - if (pKnownHeader->pRawValue != null) + if (pKnownHeader->RawValueLength > 0) { value = HeaderEncoding.GetString(pKnownHeader->pRawValue + fixup, pKnownHeader->RawValueLength); } diff --git a/test/Microsoft.AspNetCore.Server.HttpSys.FunctionalTests/Listener/RequestHeaderTests.cs b/test/Microsoft.AspNetCore.Server.HttpSys.FunctionalTests/Listener/RequestHeaderTests.cs index a333179..4197d4f 100644 --- a/test/Microsoft.AspNetCore.Server.HttpSys.FunctionalTests/Listener/RequestHeaderTests.cs +++ b/test/Microsoft.AspNetCore.Server.HttpSys.FunctionalTests/Listener/RequestHeaderTests.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.Linq; using System.Net.Http; using System.Net.Sockets; using System.Text; @@ -93,6 +94,56 @@ public async Task RequestHeaders_ClientSendsUtf8Headers_Success() } } + [ConditionalFact] + public async Task RequestHeaders_ClientSendsKnownHeaderWithNoValue_Success() + { + string address; + using (var server = Utilities.CreateHttpServer(out address)) + { + string[] customValues = new string[] { "" }; + Task responseTask = SendRequestAsync(address, "If-None-Match", customValues); + + var context = await server.AcceptAsync(Utilities.DefaultTimeout); + var requestHeaders = context.Request.Headers; + Assert.Equal(3, requestHeaders.Count); + Assert.Equal(new Uri(address).Authority, requestHeaders["Host"]); + Assert.Equal(new[] { new Uri(address).Authority }, requestHeaders.GetValues("Host")); + Assert.Equal("close", requestHeaders["Connection"]); + Assert.Equal(new[] { "close" }, requestHeaders.GetValues("Connection")); + Assert.Equal(StringValues.Empty, requestHeaders["If-None-Match"]); + Assert.Empty(requestHeaders.GetValues("If-None-Match")); + Assert.Equal("spacervalue", requestHeaders["Spacer-Header"]); + context.Dispose(); + + await responseTask; + } + } + + [ConditionalFact] + public async Task RequestHeaders_ClientSendsUnknownHeaderWithNoValue_Success() + { + string address; + using (var server = Utilities.CreateHttpServer(out address)) + { + string[] customValues = new string[] { "" }; + Task responseTask = SendRequestAsync(address, "Custom-Header", customValues); + + var context = await server.AcceptAsync(Utilities.DefaultTimeout); + var requestHeaders = context.Request.Headers; + Assert.Equal(4, requestHeaders.Count); + Assert.Equal(new Uri(address).Authority, requestHeaders["Host"]); + Assert.Equal(new[] { new Uri(address).Authority }, requestHeaders.GetValues("Host")); + Assert.Equal("close", requestHeaders["Connection"]); + Assert.Equal(new[] { "close" }, requestHeaders.GetValues("Connection")); + Assert.Equal("", requestHeaders["Custom-Header"]); + Assert.Empty(requestHeaders.GetValues("Custom-Header")); + Assert.Equal("spacervalue", requestHeaders["Spacer-Header"]); + context.Dispose(); + + await responseTask; + } + } + private async Task SendRequestAsync(string uri) { using (HttpClient client = new HttpClient())