From 1b659958b259babbadf5ec4523c883d2bfb879cd Mon Sep 17 00:00:00 2001 From: Stephen Toub Date: Wed, 15 Apr 2020 11:21:54 -0400 Subject: [PATCH] Allow known values for HttpHeaderType.Custom in KnownHeaders --- .../tests/System/Net/Http/HttpClientHandlerTest.cs | 2 +- .../src/System/Net/Http/Headers/HeaderDescriptor.cs | 4 ++-- .../src/System/Net/Http/Headers/KnownHeader.cs | 1 - .../src/System/Net/Http/Headers/KnownHeaders.cs | 12 ++++++------ 4 files changed, 9 insertions(+), 10 deletions(-) diff --git a/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.cs b/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.cs index a866a5d076a995..258ca2f6f5c40c 100644 --- a/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.cs +++ b/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.cs @@ -989,7 +989,7 @@ await LoopbackServer.CreateClientAndServerAsync(async uri => Assert.Contains(new ViaHeaderValue("1.1", "example.com", null, "(Apache/1.1)"), resp.Headers.Via); Assert.Contains(new WarningHeaderValue(199, "-", "\"Miscellaneous warning\"", DateTimeOffset.Parse("Wed, 21 Oct 2015 07:28:00 GMT")), resp.Headers.Warning); Assert.Contains(new AuthenticationHeaderValue("Basic"), resp.Headers.WwwAuthenticate); - Assert.Contains("deny", resp.Headers.GetValues("X-Frame-Options")); + Assert.Contains("deny", resp.Headers.GetValues("X-Frame-Options"), StringComparer.OrdinalIgnoreCase); Assert.Contains("default-src 'self'", resp.Headers.GetValues("X-WebKit-CSP")); Assert.Contains("5; url=http://www.w3.org/pub/WWW/People.html", resp.Headers.GetValues("Refresh")); Assert.Contains("200 OK", resp.Headers.GetValues("Status")); diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/Headers/HeaderDescriptor.cs b/src/libraries/System.Net.Http/src/System/Net/Http/Headers/HeaderDescriptor.cs index 2b955dbd10774c..fb6d5ee59ecee5 100644 --- a/src/libraries/System.Net.Http/src/System/Net/Http/Headers/HeaderDescriptor.cs +++ b/src/libraries/System.Net.Http/src/System/Net/Http/Headers/HeaderDescriptor.cs @@ -126,9 +126,9 @@ public string GetHeaderValue(ReadOnlySpan headerValue) // If it's a known header value, use the known value instead of allocating a new string. if (_knownHeader != null) { - if (_knownHeader.KnownValues != null) + string[]? knownValues = _knownHeader.KnownValues; + if (knownValues != null) { - string[] knownValues = _knownHeader.KnownValues; for (int i = 0; i < knownValues.Length; i++) { if (ByteArrayHelpers.EqualsOrdinalAsciiIgnoreCase(knownValues[i], headerValue)) diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/Headers/KnownHeader.cs b/src/libraries/System.Net.Http/src/System/Net/Http/Headers/KnownHeader.cs index ce0705bbf5f19f..e166e71d8060ec 100644 --- a/src/libraries/System.Net.Http/src/System/Net/Http/Headers/KnownHeader.cs +++ b/src/libraries/System.Net.Http/src/System/Net/Http/Headers/KnownHeader.cs @@ -21,7 +21,6 @@ public KnownHeader(string name, HttpHeaderType headerType, HttpHeaderParser? par { Debug.Assert(!string.IsNullOrEmpty(name)); Debug.Assert(name[0] == ':' || HttpRuleParser.GetTokenLength(name, 0) == name.Length); - Debug.Assert(knownValues == null || (headerType & HttpHeaderType.Custom) != HttpHeaderType.Custom); Name = name; HeaderType = headerType; diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/Headers/KnownHeaders.cs b/src/libraries/System.Net.Http/src/System/Net/Http/Headers/KnownHeaders.cs index 654765e51be8a7..493e0b8bc64fd2 100644 --- a/src/libraries/System.Net.Http/src/System/Net/Http/Headers/KnownHeaders.cs +++ b/src/libraries/System.Net.Http/src/System/Net/Http/Headers/KnownHeaders.cs @@ -70,7 +70,7 @@ internal static class KnownHeaders public static readonly KnownHeader PublicKeyPins = new KnownHeader("Public-Key-Pins"); public static readonly KnownHeader Range = new KnownHeader("Range", HttpHeaderType.Request | HttpHeaderType.NonTrailing, GenericHeaderParser.RangeParser, null, H2StaticTable.Range, H3StaticTable.RangeBytes0ToAll); public static readonly KnownHeader Referer = new KnownHeader("Referer", HttpHeaderType.Request, UriHeaderParser.RelativeOrAbsoluteUriParser, null, H2StaticTable.Referer, H3StaticTable.Referer); // NB: The spelling-mistake "Referer" for "Referrer" must be matched. - public static readonly KnownHeader ReferrerPolicy = new KnownHeader("Referrer-Policy"); + public static readonly KnownHeader ReferrerPolicy = new KnownHeader("Referrer-Policy", HttpHeaderType.Custom, null, new string[] { "strict-origin-when-cross-origin", "origin-when-cross-origin", "strict-origin", "origin", "same-origin", "no-referrer-when-downgrade", "no-referrer", "unsafe-url" }); public static readonly KnownHeader Refresh = new KnownHeader("Refresh", H2StaticTable.Refresh); public static readonly KnownHeader RetryAfter = new KnownHeader("Retry-After", HttpHeaderType.Response | HttpHeaderType.NonTrailing, GenericHeaderParser.RetryConditionParser, null, H2StaticTable.RetryAfter); public static readonly KnownHeader SecWebSocketAccept = new KnownHeader("Sec-WebSocket-Accept"); @@ -88,22 +88,22 @@ internal static class KnownHeaders public static readonly KnownHeader Trailer = new KnownHeader("Trailer", HttpHeaderType.General | HttpHeaderType.NonTrailing, GenericHeaderParser.TokenListParser); public static readonly KnownHeader TransferEncoding = new KnownHeader("Transfer-Encoding", HttpHeaderType.General | HttpHeaderType.NonTrailing, TransferCodingHeaderParser.MultipleValueParser, new string[] { "chunked", "compress", "deflate", "gzip", "identity" }, H2StaticTable.TransferEncoding); public static readonly KnownHeader Upgrade = new KnownHeader("Upgrade", HttpHeaderType.General, GenericHeaderParser.MultipleValueProductParser); - public static readonly KnownHeader UpgradeInsecureRequests = new KnownHeader("Upgrade-Insecure-Requests", http3StaticTableIndex: H3StaticTable.UpgradeInsecureRequests1); + public static readonly KnownHeader UpgradeInsecureRequests = new KnownHeader("Upgrade-Insecure-Requests", HttpHeaderType.Custom, null, new string[] { "1" }, http3StaticTableIndex: H3StaticTable.UpgradeInsecureRequests1); public static readonly KnownHeader UserAgent = new KnownHeader("User-Agent", HttpHeaderType.Request, ProductInfoHeaderParser.MultipleValueParser, null, H2StaticTable.UserAgent, H3StaticTable.UserAgent); - public static readonly KnownHeader Vary = new KnownHeader("Vary", HttpHeaderType.Response | HttpHeaderType.NonTrailing, GenericHeaderParser.TokenListParser, null, H2StaticTable.Vary, H3StaticTable.VaryAcceptEncoding); + public static readonly KnownHeader Vary = new KnownHeader("Vary", HttpHeaderType.Response | HttpHeaderType.NonTrailing, GenericHeaderParser.TokenListParser, new string[] { "*" }, H2StaticTable.Vary, H3StaticTable.VaryAcceptEncoding); public static readonly KnownHeader Via = new KnownHeader("Via", HttpHeaderType.General, GenericHeaderParser.MultipleValueViaParser, null, H2StaticTable.Via); public static readonly KnownHeader WWWAuthenticate = new KnownHeader("WWW-Authenticate", HttpHeaderType.Response | HttpHeaderType.NonTrailing, GenericHeaderParser.MultipleValueAuthenticationParser, null, H2StaticTable.WwwAuthenticate); public static readonly KnownHeader Warning = new KnownHeader("Warning", HttpHeaderType.General | HttpHeaderType.NonTrailing, GenericHeaderParser.MultipleValueWarningParser); public static readonly KnownHeader XAspNetVersion = new KnownHeader("X-AspNet-Version"); public static readonly KnownHeader XCache = new KnownHeader("X-Cache"); public static readonly KnownHeader XContentDuration = new KnownHeader("X-Content-Duration"); - public static readonly KnownHeader XContentTypeOptions = new KnownHeader("X-Content-Type-Options", http3StaticTableIndex: H3StaticTable.XContentTypeOptionsNoSniff); - public static readonly KnownHeader XFrameOptions = new KnownHeader("X-Frame-Options", http3StaticTableIndex: H3StaticTable.XFrameOptionsDeny); + public static readonly KnownHeader XContentTypeOptions = new KnownHeader("X-Content-Type-Options", HttpHeaderType.Custom, null, new string[] { "nosniff" }, http3StaticTableIndex: H3StaticTable.XContentTypeOptionsNoSniff); + public static readonly KnownHeader XFrameOptions = new KnownHeader("X-Frame-Options", HttpHeaderType.Custom, null, new string[] { "DENY", "SAMEORIGIN" }, http3StaticTableIndex: H3StaticTable.XFrameOptionsDeny); public static readonly KnownHeader XMSEdgeRef = new KnownHeader("X-MSEdge-Ref"); public static readonly KnownHeader XPoweredBy = new KnownHeader("X-Powered-By"); public static readonly KnownHeader XRequestID = new KnownHeader("X-Request-ID"); public static readonly KnownHeader XUACompatible = new KnownHeader("X-UA-Compatible"); - public static readonly KnownHeader XXssProtection = new KnownHeader("X-XSS-Protection"); + public static readonly KnownHeader XXssProtection = new KnownHeader("X-XSS-Protection", HttpHeaderType.Custom, null, new string[] { "0", "1", "1; mode=block" }); // Helper interface for making GetCandidate generic over strings, utf8, etc private interface IHeaderNameAccessor