diff --git a/src/Microsoft.AspNetCore.Server.HttpSys/RequestProcessing/NativeRequestContext.cs b/src/Microsoft.AspNetCore.Server.HttpSys/RequestProcessing/NativeRequestContext.cs index 7bcbb25..9f7c5e5 100644 --- a/src/Microsoft.AspNetCore.Server.HttpSys/RequestProcessing/NativeRequestContext.cs +++ b/src/Microsoft.AspNetCore.Server.HttpSys/RequestProcessing/NativeRequestContext.cs @@ -272,7 +272,7 @@ internal string GetKnownHeader(HttpSysRequestHeader header) HttpApi.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..b60328d 100644 --- a/test/Microsoft.AspNetCore.Server.HttpSys.FunctionalTests/Listener/RequestHeaderTests.cs +++ b/test/Microsoft.AspNetCore.Server.HttpSys.FunctionalTests/Listener/RequestHeaderTests.cs @@ -93,6 +93,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())