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 b7af4667d59c46..cb2e30c52baf95 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 @@ -207,19 +207,25 @@ public string GetHeaderValue(ReadOnlySpan headerValue, Encoding? valueEnco break; case 10: - switch (contentTypeValue[0]) + switch (contentTypeValue[6]) { - case (byte)'t': candidate = "text/plain"; break; // [t]ext/plain - case (byte)'i': candidate = "image/jpeg"; break; // [i]mage/jpeg + case (byte)'l': candidate = "text/plain"; break; // text/p[l]ain + case (byte)'j': candidate = "image/jpeg"; break; // image/[j]peg + case (byte)'w': candidate = "image/webp"; break; // image/[w]ebp } break; + case 13: + candidate = "image/svg+xml"; // image/svg+xml + break; + case 15: switch (contentTypeValue[12]) { case (byte)'p': candidate = "application/pdf"; break; // application/[p]df case (byte)'x': candidate = "application/xml"; break; // application/[x]ml case (byte)'z': candidate = "application/zip"; break; // application/[z]ip + case (byte)'i': candidate = "text/javascript"; break; // text/javascr[i]pt } break; @@ -231,6 +237,10 @@ public string GetHeaderValue(ReadOnlySpan headerValue, Encoding? valueEnco } break; + case 17: + candidate = "text/event-stream"; // text/event-stream + break; + case 19: candidate = "multipart/form-data"; // multipart/form-data break; @@ -239,17 +249,47 @@ public string GetHeaderValue(ReadOnlySpan headerValue, Encoding? valueEnco candidate = "application/javascript"; // application/javascript break; + case 23: + switch (contentTypeValue[18]) + { + case (byte)'u': candidate = "text/html;charset=utf-8"; break; // text/html;charset=[u]tf-8 + case (byte)'U': candidate = "text/html;charset=UTF-8"; break; // text/html;charset=[U]TF-8 + } + break; + case 24: - switch (contentTypeValue[19]) + switch (contentTypeValue[10] ^ contentTypeValue[19]) { - case (byte)'t': candidate = "application/octet-stream"; break; // application/octet-s[t]ream - case (byte)'u': candidate = "text/html; charset=utf-8"; break; // text/html; charset=[u]tf-8 - case (byte)'U': candidate = "text/html; charset=UTF-8"; break; // text/html; charset=[U]TF-8 + case 'n' ^ 't': candidate = "application/octet-stream"; break; // applicatio[n]/octet-s[t]ream + case ' ' ^ 'u': candidate = "text/html; charset=utf-8"; break; // text/html;[ ]charset=[u]tf-8 + case ' ' ^ 'U': candidate = "text/html; charset=UTF-8"; break; // text/html;[ ]charset=[U]TF-8 + case ';' ^ 'u': candidate = "text/plain;charset=utf-8"; break; // text/plain[;]charset=[u]tf-8 + case ';' ^ 'U': candidate = "text/plain;charset=UTF-8"; break; // text/plain[;]charset=[U]TF-8 } break; case 25: - candidate = "text/plain; charset=utf-8"; // text/plain; charset=utf-8 + switch (contentTypeValue[20]) + { + case (byte)'u': candidate = "text/plain; charset=utf-8"; break; // text/plain; charset=[u]tf-8 + case (byte)'U': candidate = "text/plain; charset=UTF-8"; break; // text/plain; charset=[U]TF-8 + } + break; + + case 29: + switch (contentTypeValue[19]) + { + case (byte)'I': candidate = "text/html; charset=ISO-8859-1"; break; // text/html; charset=[I]SO-8859-1 + case (byte)'i': candidate = "text/html; charset=iso-8859-1"; break; // text/html; charset=[i]so-8859-1 + } + break; + + case 30: + switch (contentTypeValue[25]) + { + case (byte)'u': candidate = "text/javascript; charset=utf-8"; break; // text/javascript; charset=[u]tf-8 + case (byte)'U': candidate = "text/javascript; charset=UTF-8"; break; // text/javascript; charset=[U]TF-8 + } break; case 31: 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 ab78688af1e0c1..bc968d8cf5a7eb 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 @@ -8,12 +8,9 @@ namespace System.Net.Http.Headers { internal sealed partial class KnownHeader { - public KnownHeader(string name, int? http2StaticTableIndex = null, int? http3StaticTableIndex = null) : - this(name, HttpHeaderType.Custom, parser: null, knownValues: null, http2StaticTableIndex, http3StaticTableIndex) - { - Debug.Assert(!string.IsNullOrEmpty(name)); - Debug.Assert(name[0] == ':' || HttpRuleParser.IsToken(name)); - } + public KnownHeader(string name, string[]? knownValues = null, int? http2StaticTableIndex = null, int? http3StaticTableIndex = null) + : this(name, HttpHeaderType.Custom, parser: null, knownValues, http2StaticTableIndex, http3StaticTableIndex) + { } public KnownHeader(string name, HttpHeaderType headerType, HttpHeaderParser? parser, string[]? knownValues = null, int? http2StaticTableIndex = null, int? http3StaticTableIndex = null) { 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 395a9c766306ac..c9dbd00e58e3f0 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 @@ -13,101 +13,104 @@ internal static class KnownHeaders { // If you add a new entry here, you need to add it to TryGetKnownHeader below as well. - public static readonly KnownHeader PseudoStatus = new KnownHeader(":status", HttpHeaderType.Response, parser: null); - public static readonly KnownHeader Accept = new KnownHeader("Accept", HttpHeaderType.Request, MediaTypeHeaderParser.MultipleValuesParser, null, H2StaticTable.Accept, H3StaticTable.AcceptAny); - public static readonly KnownHeader AcceptCharset = new KnownHeader("Accept-Charset", HttpHeaderType.Request, GenericHeaderParser.MultipleValueStringWithQualityParser, null, H2StaticTable.AcceptCharset); - public static readonly KnownHeader AcceptEncoding = new KnownHeader("Accept-Encoding", HttpHeaderType.Request, GenericHeaderParser.MultipleValueStringWithQualityParser, null, H2StaticTable.AcceptEncoding, H3StaticTable.AcceptEncodingGzipDeflateBr); - public static readonly KnownHeader AcceptLanguage = new KnownHeader("Accept-Language", HttpHeaderType.Request, GenericHeaderParser.MultipleValueStringWithQualityParser, null, H2StaticTable.AcceptLanguage, H3StaticTable.AcceptLanguage); - public static readonly KnownHeader AcceptPatch = new KnownHeader("Accept-Patch"); - public static readonly KnownHeader AcceptRanges = new KnownHeader("Accept-Ranges", HttpHeaderType.Response, GenericHeaderParser.TokenListParser, null, H2StaticTable.AcceptRanges, H3StaticTable.AcceptRangesBytes); - public static readonly KnownHeader AccessControlAllowCredentials = new KnownHeader("Access-Control-Allow-Credentials", HttpHeaderType.Response, parser: null, new string[] { "true" }, http3StaticTableIndex: H3StaticTable.AccessControlAllowCredentials); - public static readonly KnownHeader AccessControlAllowHeaders = new KnownHeader("Access-Control-Allow-Headers", HttpHeaderType.Response, parser: null, new string[] { "*" }, http3StaticTableIndex: H3StaticTable.AccessControlAllowHeadersCacheControl); - public static readonly KnownHeader AccessControlAllowMethods = new KnownHeader("Access-Control-Allow-Methods", HttpHeaderType.Response, parser: null, new string[] { "*" }, http3StaticTableIndex: H3StaticTable.AccessControlAllowMethodsGet); - public static readonly KnownHeader AccessControlAllowOrigin = new KnownHeader("Access-Control-Allow-Origin", HttpHeaderType.Response, parser: null, new string[] { "*", "null" }, H2StaticTable.AccessControlAllowOrigin, H3StaticTable.AccessControlAllowOriginAny); - public static readonly KnownHeader AccessControlExposeHeaders = new KnownHeader("Access-Control-Expose-Headers", HttpHeaderType.Response, parser: null, new string[] { "*" }, H3StaticTable.AccessControlExposeHeadersContentLength); - public static readonly KnownHeader AccessControlMaxAge = new KnownHeader("Access-Control-Max-Age"); - public static readonly KnownHeader Age = new KnownHeader("Age", HttpHeaderType.Response | HttpHeaderType.NonTrailing, TimeSpanHeaderParser.Parser, null, H2StaticTable.Age, H3StaticTable.Age0); - public static readonly KnownHeader Allow = new KnownHeader("Allow", HttpHeaderType.Content, GenericHeaderParser.TokenListParser, null, H2StaticTable.Allow); - public static readonly KnownHeader AltSvc = new KnownHeader("Alt-Svc", HttpHeaderType.Response, GetAltSvcHeaderParser(), http3StaticTableIndex: H3StaticTable.AltSvcClear); - public static readonly KnownHeader AltUsed = new KnownHeader("Alt-Used", HttpHeaderType.Request, parser: null); - public static readonly KnownHeader Authorization = new KnownHeader("Authorization", HttpHeaderType.Request | HttpHeaderType.NonTrailing, GenericHeaderParser.SingleValueAuthenticationParser, null, H2StaticTable.Authorization, H3StaticTable.Authorization); - public static readonly KnownHeader CacheControl = new KnownHeader("Cache-Control", HttpHeaderType.General | HttpHeaderType.NonTrailing, CacheControlHeaderParser.Parser, new string[] { "must-revalidate", "no-cache", "no-store", "no-transform", "private", "proxy-revalidate", "public" }, H2StaticTable.CacheControl, H3StaticTable.CacheControlMaxAge0); - public static readonly KnownHeader Connection = new KnownHeader("Connection", HttpHeaderType.General, GenericHeaderParser.TokenListParser, new string[] { "close" }); - public static readonly KnownHeader ContentDisposition = new KnownHeader("Content-Disposition", HttpHeaderType.Content | HttpHeaderType.NonTrailing, GenericHeaderParser.ContentDispositionParser, new string[] { "inline", "attachment" }, H2StaticTable.ContentDisposition, H3StaticTable.ContentDisposition); - public static readonly KnownHeader ContentEncoding = new KnownHeader("Content-Encoding", HttpHeaderType.Content | HttpHeaderType.NonTrailing, GenericHeaderParser.TokenListParser, new string[] { "gzip", "deflate", "br", "compress", "identity" }, H2StaticTable.ContentEncoding, H3StaticTable.ContentEncodingBr); - public static readonly KnownHeader ContentLanguage = new KnownHeader("Content-Language", HttpHeaderType.Content, GenericHeaderParser.TokenListParser, null, H2StaticTable.ContentLanguage); - public static readonly KnownHeader ContentLength = new KnownHeader("Content-Length", HttpHeaderType.Content | HttpHeaderType.NonTrailing, Int64NumberHeaderParser.Parser, null, H2StaticTable.ContentLength, H3StaticTable.ContentLength0); - public static readonly KnownHeader ContentLocation = new KnownHeader("Content-Location", HttpHeaderType.Content | HttpHeaderType.NonTrailing, UriHeaderParser.RelativeOrAbsoluteUriParser, null, H2StaticTable.ContentLocation); - public static readonly KnownHeader ContentMD5 = new KnownHeader("Content-MD5", HttpHeaderType.Content, ByteArrayHeaderParser.Parser); - public static readonly KnownHeader ContentRange = new KnownHeader("Content-Range", HttpHeaderType.Content | HttpHeaderType.NonTrailing, GenericHeaderParser.ContentRangeParser, null, H2StaticTable.ContentRange); - public static readonly KnownHeader ContentSecurityPolicy = new KnownHeader("Content-Security-Policy", http3StaticTableIndex: H3StaticTable.ContentSecurityPolicyAllNone); - public static readonly KnownHeader ContentType = new KnownHeader("Content-Type", HttpHeaderType.Content | HttpHeaderType.NonTrailing, MediaTypeHeaderParser.SingleValueParser, null, H2StaticTable.ContentType, H3StaticTable.ContentTypeApplicationDnsMessage); - public static readonly KnownHeader Cookie = new KnownHeader("Cookie", HttpHeaderType.Custom, CookieHeaderParser.Parser, null, H2StaticTable.Cookie, H3StaticTable.Cookie); - public static readonly KnownHeader Cookie2 = new KnownHeader("Cookie2"); - public static readonly KnownHeader Date = new KnownHeader("Date", HttpHeaderType.General | HttpHeaderType.NonTrailing, DateHeaderParser.Parser, null, H2StaticTable.Date, H3StaticTable.Date); - public static readonly KnownHeader ETag = new KnownHeader("ETag", HttpHeaderType.Response, GenericHeaderParser.SingleValueEntityTagParser, null, H2StaticTable.ETag, H3StaticTable.ETag); - public static readonly KnownHeader Expect = new KnownHeader("Expect", HttpHeaderType.Request | HttpHeaderType.NonTrailing, GenericHeaderParser.MultipleValueNameValueWithParametersParser, new string[] { "100-continue" }, H2StaticTable.Expect); - public static readonly KnownHeader ExpectCT = new KnownHeader("Expect-CT"); - public static readonly KnownHeader Expires = new KnownHeader("Expires", HttpHeaderType.Content | HttpHeaderType.NonTrailing, DateHeaderParser.Parser, null, H2StaticTable.Expires); - public static readonly KnownHeader From = new KnownHeader("From", HttpHeaderType.Request, GenericHeaderParser.SingleValueParserWithoutValidation, null, H2StaticTable.From); - public static readonly KnownHeader GrpcEncoding = new KnownHeader("grpc-encoding", HttpHeaderType.Custom, null, new string[] { "identity", "gzip", "deflate" }); - public static readonly KnownHeader GrpcMessage = new KnownHeader("grpc-message"); - public static readonly KnownHeader GrpcStatus = new KnownHeader("grpc-status", HttpHeaderType.Custom, null, new string[] { "0" }); - public static readonly KnownHeader Host = new KnownHeader("Host", HttpHeaderType.Request | HttpHeaderType.NonTrailing, GenericHeaderParser.HostParser, null, H2StaticTable.Host); - public static readonly KnownHeader IfMatch = new KnownHeader("If-Match", HttpHeaderType.Request | HttpHeaderType.NonTrailing, GenericHeaderParser.MultipleValueEntityTagParser, null, H2StaticTable.IfMatch); - public static readonly KnownHeader IfModifiedSince = new KnownHeader("If-Modified-Since", HttpHeaderType.Request | HttpHeaderType.NonTrailing, DateHeaderParser.Parser, null, H2StaticTable.IfModifiedSince, H3StaticTable.IfModifiedSince); - public static readonly KnownHeader IfNoneMatch = new KnownHeader("If-None-Match", HttpHeaderType.Request | HttpHeaderType.NonTrailing, GenericHeaderParser.MultipleValueEntityTagParser, null, H2StaticTable.IfNoneMatch, H3StaticTable.IfNoneMatch); - public static readonly KnownHeader IfRange = new KnownHeader("If-Range", HttpHeaderType.Request | HttpHeaderType.NonTrailing, GenericHeaderParser.RangeConditionParser, null, H2StaticTable.IfRange, H3StaticTable.IfRange); - public static readonly KnownHeader IfUnmodifiedSince = new KnownHeader("If-Unmodified-Since", HttpHeaderType.Request | HttpHeaderType.NonTrailing, DateHeaderParser.Parser, null, H2StaticTable.IfUnmodifiedSince); - public static readonly KnownHeader KeepAlive = new KnownHeader("Keep-Alive"); - public static readonly KnownHeader LastModified = new KnownHeader("Last-Modified", HttpHeaderType.Content, DateHeaderParser.Parser, null, H2StaticTable.LastModified, H3StaticTable.LastModified); - public static readonly KnownHeader Link = new KnownHeader("Link", H2StaticTable.Link, H3StaticTable.Link); - public static readonly KnownHeader Location = new KnownHeader("Location", HttpHeaderType.Response | HttpHeaderType.NonTrailing, UriHeaderParser.RelativeOrAbsoluteUriParser, null, H2StaticTable.Location, H3StaticTable.Location); - public static readonly KnownHeader MaxForwards = new KnownHeader("Max-Forwards", HttpHeaderType.Request | HttpHeaderType.NonTrailing, Int32NumberHeaderParser.Parser, null, H2StaticTable.MaxForwards); - public static readonly KnownHeader Origin = new KnownHeader("Origin", http3StaticTableIndex: H3StaticTable.Origin); - public static readonly KnownHeader P3P = new KnownHeader("P3P"); - public static readonly KnownHeader Pragma = new KnownHeader("Pragma", HttpHeaderType.General | HttpHeaderType.NonTrailing, GenericHeaderParser.MultipleValueNameValueParser, new string[] { "no-cache" }); - public static readonly KnownHeader ProxyAuthenticate = new KnownHeader("Proxy-Authenticate", HttpHeaderType.Response | HttpHeaderType.NonTrailing, GenericHeaderParser.MultipleValueAuthenticationParser, null, H2StaticTable.ProxyAuthenticate); - public static readonly KnownHeader ProxyAuthorization = new KnownHeader("Proxy-Authorization", HttpHeaderType.Request | HttpHeaderType.NonTrailing, GenericHeaderParser.SingleValueAuthenticationParser, null, H2StaticTable.ProxyAuthorization); - public static readonly KnownHeader ProxyConnection = new KnownHeader("Proxy-Connection"); - public static readonly KnownHeader ProxySupport = new KnownHeader("Proxy-Support"); - 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", 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"); - public static readonly KnownHeader SecWebSocketExtensions = new KnownHeader("Sec-WebSocket-Extensions"); - public static readonly KnownHeader SecWebSocketKey = new KnownHeader("Sec-WebSocket-Key"); - public static readonly KnownHeader SecWebSocketProtocol = new KnownHeader("Sec-WebSocket-Protocol"); - public static readonly KnownHeader SecWebSocketVersion = new KnownHeader("Sec-WebSocket-Version"); - public static readonly KnownHeader Server = new KnownHeader("Server", HttpHeaderType.Response, ProductInfoHeaderParser.MultipleValueParser, null, H2StaticTable.Server, H3StaticTable.Server); - public static readonly KnownHeader ServerTiming = new KnownHeader("Server-Timing"); - public static readonly KnownHeader SetCookie = new KnownHeader("Set-Cookie", HttpHeaderType.Custom | HttpHeaderType.NonTrailing, null, null, H2StaticTable.SetCookie, H3StaticTable.SetCookie); - public static readonly KnownHeader SetCookie2 = new KnownHeader("Set-Cookie2", HttpHeaderType.Custom | HttpHeaderType.NonTrailing, null, null); - public static readonly KnownHeader StrictTransportSecurity = new KnownHeader("Strict-Transport-Security", H2StaticTable.StrictTransportSecurity, H3StaticTable.StrictTransportSecurityMaxAge31536000); - public static readonly KnownHeader TE = new KnownHeader("TE", HttpHeaderType.Request | HttpHeaderType.NonTrailing, TransferCodingHeaderParser.MultipleValueWithQualityParser, new string[] { "trailers", "compress", "deflate", "gzip" }); - public static readonly KnownHeader TSV = new KnownHeader("TSV"); - 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", 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, 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", 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", HttpHeaderType.Custom, null, new string[] { "0", "1", "1; mode=block" }); + public static readonly KnownHeader PseudoStatus = new(":status", HttpHeaderType.Response, parser: null); + public static readonly KnownHeader Accept = new("Accept", HttpHeaderType.Request, MediaTypeHeaderParser.MultipleValuesParser, null, H2StaticTable.Accept, H3StaticTable.AcceptAny); + public static readonly KnownHeader AcceptCharset = new("Accept-Charset", HttpHeaderType.Request, GenericHeaderParser.MultipleValueStringWithQualityParser, null, H2StaticTable.AcceptCharset); + public static readonly KnownHeader AcceptEncoding = new("Accept-Encoding", HttpHeaderType.Request, GenericHeaderParser.MultipleValueStringWithQualityParser, null, H2StaticTable.AcceptEncoding, H3StaticTable.AcceptEncodingGzipDeflateBr); + public static readonly KnownHeader AcceptLanguage = new("Accept-Language", HttpHeaderType.Request, GenericHeaderParser.MultipleValueStringWithQualityParser, null, H2StaticTable.AcceptLanguage, H3StaticTable.AcceptLanguage); + public static readonly KnownHeader AcceptPatch = new("Accept-Patch"); + public static readonly KnownHeader AcceptRanges = new("Accept-Ranges", HttpHeaderType.Response, GenericHeaderParser.TokenListParser, ["bytes", "none"], H2StaticTable.AcceptRanges, H3StaticTable.AcceptRangesBytes); + public static readonly KnownHeader AccessControlAllowCredentials = new("Access-Control-Allow-Credentials", HttpHeaderType.Response, parser: null, ["true"], http3StaticTableIndex: H3StaticTable.AccessControlAllowCredentials); + public static readonly KnownHeader AccessControlAllowHeaders = new("Access-Control-Allow-Headers", HttpHeaderType.Response, parser: null, ["*"], http3StaticTableIndex: H3StaticTable.AccessControlAllowHeadersCacheControl); + public static readonly KnownHeader AccessControlAllowMethods = new("Access-Control-Allow-Methods", HttpHeaderType.Response, parser: null, ["POST", "*"], http3StaticTableIndex: H3StaticTable.AccessControlAllowMethodsGet); + public static readonly KnownHeader AccessControlAllowOrigin = new("Access-Control-Allow-Origin", HttpHeaderType.Response, parser: null, ["*", "null"], H2StaticTable.AccessControlAllowOrigin, H3StaticTable.AccessControlAllowOriginAny); + public static readonly KnownHeader AccessControlExposeHeaders = new("Access-Control-Expose-Headers", HttpHeaderType.Response, parser: null, ["*"], H3StaticTable.AccessControlExposeHeadersContentLength); + public static readonly KnownHeader AccessControlMaxAge = new("Access-Control-Max-Age"); + public static readonly KnownHeader Age = new("Age", HttpHeaderType.Response | HttpHeaderType.NonTrailing, TimeSpanHeaderParser.Parser, ["0"], H2StaticTable.Age, H3StaticTable.Age0); + public static readonly KnownHeader Allow = new("Allow", HttpHeaderType.Content, GenericHeaderParser.TokenListParser, null, H2StaticTable.Allow); + public static readonly KnownHeader AltSvc = new("Alt-Svc", HttpHeaderType.Response, GetAltSvcHeaderParser(), ["h3=\":443\"", "h3=\":443\"; ma=2592000", "clear"], http3StaticTableIndex: H3StaticTable.AltSvcClear); + public static readonly KnownHeader AltUsed = new("Alt-Used", HttpHeaderType.Request, parser: null); + public static readonly KnownHeader Authorization = new("Authorization", HttpHeaderType.Request | HttpHeaderType.NonTrailing, GenericHeaderParser.SingleValueAuthenticationParser, null, H2StaticTable.Authorization, H3StaticTable.Authorization); + public static readonly KnownHeader CacheControl = new("Cache-Control", HttpHeaderType.General | HttpHeaderType.NonTrailing, CacheControlHeaderParser.Parser, ["must-revalidate", "no-cache", "no-store", "no-transform", "private", "proxy-revalidate", "public"], H2StaticTable.CacheControl, H3StaticTable.CacheControlMaxAge0); + public static readonly KnownHeader Connection = new("Connection", HttpHeaderType.General, GenericHeaderParser.TokenListParser, ["keep-alive", "close", "Upgrade", "Transfer-Encoding"]); + public static readonly KnownHeader ContentDisposition = new("Content-Disposition", HttpHeaderType.Content | HttpHeaderType.NonTrailing, GenericHeaderParser.ContentDispositionParser, ["inline", "attachment"], H2StaticTable.ContentDisposition, H3StaticTable.ContentDisposition); + public static readonly KnownHeader ContentEncoding = new("Content-Encoding", HttpHeaderType.Content | HttpHeaderType.NonTrailing, GenericHeaderParser.TokenListParser, ["gzip", "deflate", "br", "zstd", "compress", "identity"], H2StaticTable.ContentEncoding, H3StaticTable.ContentEncodingBr); + public static readonly KnownHeader ContentLanguage = new("Content-Language", HttpHeaderType.Content, GenericHeaderParser.TokenListParser, null, H2StaticTable.ContentLanguage); + public static readonly KnownHeader ContentLength = new("Content-Length", HttpHeaderType.Content | HttpHeaderType.NonTrailing, Int64NumberHeaderParser.Parser, null, H2StaticTable.ContentLength, H3StaticTable.ContentLength0); + public static readonly KnownHeader ContentLocation = new("Content-Location", HttpHeaderType.Content | HttpHeaderType.NonTrailing, UriHeaderParser.RelativeOrAbsoluteUriParser, null, H2StaticTable.ContentLocation); + public static readonly KnownHeader ContentMD5 = new("Content-MD5", HttpHeaderType.Content, ByteArrayHeaderParser.Parser); + public static readonly KnownHeader ContentRange = new("Content-Range", HttpHeaderType.Content | HttpHeaderType.NonTrailing, GenericHeaderParser.ContentRangeParser, null, H2StaticTable.ContentRange); + public static readonly KnownHeader ContentSecurityPolicy = new("Content-Security-Policy", ["upgrade-insecure-requests", "frame-ancestors 'self'"], http3StaticTableIndex: H3StaticTable.ContentSecurityPolicyAllNone); + public static readonly KnownHeader ContentType = new("Content-Type", HttpHeaderType.Content | HttpHeaderType.NonTrailing, MediaTypeHeaderParser.SingleValueParser, null, H2StaticTable.ContentType, H3StaticTable.ContentTypeApplicationDnsMessage); + public static readonly KnownHeader Cookie = new("Cookie", HttpHeaderType.Custom, CookieHeaderParser.Parser, null, H2StaticTable.Cookie, H3StaticTable.Cookie); + public static readonly KnownHeader Cookie2 = new("Cookie2"); + public static readonly KnownHeader CrossOriginResourcePolicy = new("Cross-Origin-Resource-Policy", ["cross-origin", "same-site", "same-origin"]); + public static readonly KnownHeader Date = new("Date", HttpHeaderType.General | HttpHeaderType.NonTrailing, DateHeaderParser.Parser, null, H2StaticTable.Date, H3StaticTable.Date); + public static readonly KnownHeader ETag = new("ETag", HttpHeaderType.Response, GenericHeaderParser.SingleValueEntityTagParser, null, H2StaticTable.ETag, H3StaticTable.ETag); + public static readonly KnownHeader Expect = new("Expect", HttpHeaderType.Request | HttpHeaderType.NonTrailing, GenericHeaderParser.MultipleValueNameValueWithParametersParser, ["100-continue"], H2StaticTable.Expect); + public static readonly KnownHeader ExpectCT = new("Expect-CT"); + public static readonly KnownHeader Expires = new("Expires", HttpHeaderType.Content | HttpHeaderType.NonTrailing, DateHeaderParser.Parser, ["Thu, 01 Jan 1970 00:00:01 GMT", "Mon, 01 Jan 1990 00:00:00 GMT"], H2StaticTable.Expires); + public static readonly KnownHeader From = new("From", HttpHeaderType.Request, GenericHeaderParser.SingleValueParserWithoutValidation, null, H2StaticTable.From); + public static readonly KnownHeader GrpcEncoding = new("grpc-encoding", ["identity", "gzip", "deflate"]); + public static readonly KnownHeader GrpcMessage = new("grpc-message"); + public static readonly KnownHeader GrpcStatus = new("grpc-status", ["0"]); + public static readonly KnownHeader Host = new("Host", HttpHeaderType.Request | HttpHeaderType.NonTrailing, GenericHeaderParser.HostParser, null, H2StaticTable.Host); + public static readonly KnownHeader IfMatch = new("If-Match", HttpHeaderType.Request | HttpHeaderType.NonTrailing, GenericHeaderParser.MultipleValueEntityTagParser, null, H2StaticTable.IfMatch); + public static readonly KnownHeader IfModifiedSince = new("If-Modified-Since", HttpHeaderType.Request | HttpHeaderType.NonTrailing, DateHeaderParser.Parser, null, H2StaticTable.IfModifiedSince, H3StaticTable.IfModifiedSince); + public static readonly KnownHeader IfNoneMatch = new("If-None-Match", HttpHeaderType.Request | HttpHeaderType.NonTrailing, GenericHeaderParser.MultipleValueEntityTagParser, null, H2StaticTable.IfNoneMatch, H3StaticTable.IfNoneMatch); + public static readonly KnownHeader IfRange = new("If-Range", HttpHeaderType.Request | HttpHeaderType.NonTrailing, GenericHeaderParser.RangeConditionParser, null, H2StaticTable.IfRange, H3StaticTable.IfRange); + public static readonly KnownHeader IfUnmodifiedSince = new("If-Unmodified-Since", HttpHeaderType.Request | HttpHeaderType.NonTrailing, DateHeaderParser.Parser, null, H2StaticTable.IfUnmodifiedSince); + public static readonly KnownHeader KeepAlive = new("Keep-Alive"); + public static readonly KnownHeader LastModified = new("Last-Modified", HttpHeaderType.Content, DateHeaderParser.Parser, null, H2StaticTable.LastModified, H3StaticTable.LastModified); + public static readonly KnownHeader Link = new("Link", null, H2StaticTable.Link, H3StaticTable.Link); + public static readonly KnownHeader Location = new("Location", HttpHeaderType.Response | HttpHeaderType.NonTrailing, UriHeaderParser.RelativeOrAbsoluteUriParser, null, H2StaticTable.Location, H3StaticTable.Location); + public static readonly KnownHeader MaxForwards = new("Max-Forwards", HttpHeaderType.Request | HttpHeaderType.NonTrailing, Int32NumberHeaderParser.Parser, null, H2StaticTable.MaxForwards); + public static readonly KnownHeader Origin = new("Origin", http3StaticTableIndex: H3StaticTable.Origin); + public static readonly KnownHeader P3P = new("P3P"); + public static readonly KnownHeader Pragma = new("Pragma", HttpHeaderType.General | HttpHeaderType.NonTrailing, GenericHeaderParser.MultipleValueNameValueParser, ["no-cache"]); + public static readonly KnownHeader ProxyAuthenticate = new("Proxy-Authenticate", HttpHeaderType.Response | HttpHeaderType.NonTrailing, GenericHeaderParser.MultipleValueAuthenticationParser, null, H2StaticTable.ProxyAuthenticate); + public static readonly KnownHeader ProxyAuthorization = new("Proxy-Authorization", HttpHeaderType.Request | HttpHeaderType.NonTrailing, GenericHeaderParser.SingleValueAuthenticationParser, null, H2StaticTable.ProxyAuthorization); + public static readonly KnownHeader ProxyConnection = new("Proxy-Connection"); + public static readonly KnownHeader ProxySupport = new("Proxy-Support"); + public static readonly KnownHeader PublicKeyPins = new("Public-Key-Pins"); + public static readonly KnownHeader Range = new("Range", HttpHeaderType.Request | HttpHeaderType.NonTrailing, GenericHeaderParser.RangeParser, null, H2StaticTable.Range, H3StaticTable.RangeBytes0ToAll); + public static readonly KnownHeader Referer = new("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("Referrer-Policy", ["same-origin", "strict-origin-when-cross-origin", "no-referrer-when-downgrade", "origin-when-cross-origin", "strict-origin", "origin", "no-referrer", "unsafe-url"]); + public static readonly KnownHeader Refresh = new("Refresh", null, H2StaticTable.Refresh); + public static readonly KnownHeader RetryAfter = new("Retry-After", HttpHeaderType.Response | HttpHeaderType.NonTrailing, GenericHeaderParser.RetryConditionParser, null, H2StaticTable.RetryAfter); + public static readonly KnownHeader SecWebSocketAccept = new("Sec-WebSocket-Accept"); + public static readonly KnownHeader SecWebSocketExtensions = new("Sec-WebSocket-Extensions", ["permessage-deflate"]); + public static readonly KnownHeader SecWebSocketKey = new("Sec-WebSocket-Key"); + public static readonly KnownHeader SecWebSocketProtocol = new("Sec-WebSocket-Protocol"); + public static readonly KnownHeader SecWebSocketVersion = new("Sec-WebSocket-Version"); + public static readonly KnownHeader Server = new("Server", HttpHeaderType.Response, ProductInfoHeaderParser.MultipleValueParser, null, H2StaticTable.Server, H3StaticTable.Server); + public static readonly KnownHeader ServerTiming = new("Server-Timing"); + public static readonly KnownHeader SetCookie = new("Set-Cookie", HttpHeaderType.Custom | HttpHeaderType.NonTrailing, null, null, H2StaticTable.SetCookie, H3StaticTable.SetCookie); + public static readonly KnownHeader SetCookie2 = new("Set-Cookie2", HttpHeaderType.Custom | HttpHeaderType.NonTrailing, null); + public static readonly KnownHeader StrictTransportSecurity = new("Strict-Transport-Security", ["max-age=31536000", "max-age=31536000; includeSubDomains; preload", "max-age=31536000; includeSubDomains", "max-age=63072000; includeSubDomains; preload"], H2StaticTable.StrictTransportSecurity, H3StaticTable.StrictTransportSecurityMaxAge31536000); + public static readonly KnownHeader TE = new("TE", HttpHeaderType.Request | HttpHeaderType.NonTrailing, TransferCodingHeaderParser.MultipleValueWithQualityParser, ["trailers", "compress", "deflate", "gzip"]); + public static readonly KnownHeader TimingAllowOrigin = new("Timing-Allow-Origin", ["*"]); + public static readonly KnownHeader Trailer = new("Trailer", HttpHeaderType.General | HttpHeaderType.NonTrailing, GenericHeaderParser.TokenListParser); + public static readonly KnownHeader TransferEncoding = new("Transfer-Encoding", HttpHeaderType.General | HttpHeaderType.NonTrailing, TransferCodingHeaderParser.MultipleValueParser, ["chunked", "compress", "deflate", "gzip", "identity"], H2StaticTable.TransferEncoding); + public static readonly KnownHeader TSV = new("TSV"); + public static readonly KnownHeader Upgrade = new("Upgrade", HttpHeaderType.General, GenericHeaderParser.MultipleValueProductParser); + public static readonly KnownHeader UpgradeInsecureRequests = new("Upgrade-Insecure-Requests", ["1"], http3StaticTableIndex: H3StaticTable.UpgradeInsecureRequests1); + public static readonly KnownHeader UserAgent = new("User-Agent", HttpHeaderType.Request, ProductInfoHeaderParser.MultipleValueParser, null, H2StaticTable.UserAgent, H3StaticTable.UserAgent); + public static readonly KnownHeader Vary = new("Vary", HttpHeaderType.Response | HttpHeaderType.NonTrailing, GenericHeaderParser.TokenListParser, ["Accept-Encoding", "accept-encoding", "Origin", "Referer", "*"], H2StaticTable.Vary, H3StaticTable.VaryAcceptEncoding); + public static readonly KnownHeader Via = new("Via", HttpHeaderType.General, GenericHeaderParser.MultipleValueViaParser, null, H2StaticTable.Via); + public static readonly KnownHeader WWWAuthenticate = new("WWW-Authenticate", HttpHeaderType.Response | HttpHeaderType.NonTrailing, GenericHeaderParser.MultipleValueAuthenticationParser, null, H2StaticTable.WwwAuthenticate); + public static readonly KnownHeader Warning = new("Warning", HttpHeaderType.General | HttpHeaderType.NonTrailing, GenericHeaderParser.MultipleValueWarningParser); + public static readonly KnownHeader XAspNetVersion = new("X-AspNet-Version"); + public static readonly KnownHeader XCache = new("X-Cache", ["HIT", "MISS", "hit", "miss"]); + public static readonly KnownHeader XContentDuration = new("X-Content-Duration"); + public static readonly KnownHeader XContentTypeOptions = new("X-Content-Type-Options", ["nosniff"], http3StaticTableIndex: H3StaticTable.XContentTypeOptionsNoSniff); + public static readonly KnownHeader XFrameOptions = new("X-Frame-Options", ["SAMEORIGIN", "DENY", "sameorigin", "deny"], http3StaticTableIndex: H3StaticTable.XFrameOptionsDeny); + public static readonly KnownHeader XMSEdgeRef = new("X-MSEdge-Ref"); + public static readonly KnownHeader XPoweredBy = new("X-Powered-By"); + public static readonly KnownHeader XRequestID = new("X-Request-ID"); + public static readonly KnownHeader XServedBy = new("X-Served-By"); + public static readonly KnownHeader XUACompatible = new("X-UA-Compatible"); + public static readonly KnownHeader XXssProtection = new("X-XSS-Protection", ["1; mode=block", "0", "1"]); #if TARGET_BROWSER || TARGET_WASI private static HttpHeaderParser? GetAltSvcHeaderParser() => null; // Allow for the AltSvcHeaderParser to be trimmed on Browser since Alt-Svc is only for SocketsHttpHandler, which isn't used on Browser. @@ -229,6 +232,7 @@ internal static class KnownHeaders case 'g': return GrpcStatus; // [g]rpc-status case 'r': return RetryAfter; // [R]etry-After case 's': return SetCookie2; // [S]et-Cookie2 + case 'x': return XServedBy; // [X]-Served-By } break; @@ -326,6 +330,7 @@ internal static class KnownHeaders case 'c': return ContentDisposition; // [C]ontent-Disposition case 'i': return IfUnmodifiedSince; // [I]f-Unmodified-Since case 'p': return ProxyAuthorization; // [P]roxy-Authorization + case 't': return TimingAllowOrigin; // [T]iming-Allow-Origin } break; @@ -366,6 +371,7 @@ internal static class KnownHeaders { case 'h': return AccessControlAllowHeaders; // Access-Control-Allow-[H]eaders case 'm': return AccessControlAllowMethods; // Access-Control-Allow-[M]ethods + case '-': return CrossOriginResourcePolicy; // Cross-Origin-Resource[-]Policy } break; diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/Headers/QPackStaticTable.cs b/src/libraries/System.Net.Http/src/System/Net/Http/Headers/QPackStaticTable.cs index e6664bdbf3b6a3..ff590143dbca6c 100644 --- a/src/libraries/System.Net.Http/src/System/Net/Http/Headers/QPackStaticTable.cs +++ b/src/libraries/System.Net.Http/src/System/Net/Http/Headers/QPackStaticTable.cs @@ -102,7 +102,7 @@ internal static class QPackStaticTable (new HeaderDescriptor(KnownHeaders.Origin), ""), // 90 (new HeaderDescriptor("purpose"), "prefetch"), // 91 (new HeaderDescriptor(KnownHeaders.Server), ""), // 92 - (new HeaderDescriptor("timing-allow-origin"), "*"), // 93 + (new HeaderDescriptor(KnownHeaders.TimingAllowOrigin), "*"), // 93 (new HeaderDescriptor(KnownHeaders.UpgradeInsecureRequests), "1"), // 94 (new HeaderDescriptor(KnownHeaders.UserAgent), ""), // 95 (new HeaderDescriptor("x-forwarded-for"), ""), // 96 diff --git a/src/libraries/System.Net.Http/tests/UnitTests/Headers/KnownHeadersTest.cs b/src/libraries/System.Net.Http/tests/UnitTests/Headers/KnownHeadersTest.cs index aac0f0fec5d1c3..d4c645812cd03a 100644 --- a/src/libraries/System.Net.Http/tests/UnitTests/Headers/KnownHeadersTest.cs +++ b/src/libraries/System.Net.Http/tests/UnitTests/Headers/KnownHeadersTest.cs @@ -41,6 +41,7 @@ public class KnownHeadersTest [InlineData("Content-Type")] [InlineData("Cookie")] [InlineData("Cookie2")] + [InlineData("Cross-Origin-Resource-Policy")] [InlineData("Date")] [InlineData("ETag")] [InlineData("Expect")] @@ -85,6 +86,7 @@ public class KnownHeadersTest [InlineData("Set-Cookie2")] [InlineData("Strict-Transport-Security")] [InlineData("TE")] + [InlineData("Timing-Allow-Origin")] [InlineData("Trailer")] [InlineData("Transfer-Encoding")] [InlineData("TSV")] @@ -103,6 +105,7 @@ public class KnownHeadersTest [InlineData("X-MSEdge-Ref")] [InlineData("X-Powered-By")] [InlineData("X-Request-ID")] + [InlineData("X-Served-By")] [InlineData("X-UA-Compatible")] [InlineData("X-XSS-Protection")] public void TryGetKnownHeader_Known_Found(string name) @@ -168,17 +171,30 @@ public void TryGetKnownHeader_Unknown_NotFound(string name) [InlineData("Content-Type", "text/html")] [InlineData("Content-Type", "text/plain")] [InlineData("Content-Type", "image/jpeg")] + [InlineData("Content-Type", "image/webp")] + [InlineData("Content-Type", "image/svg+xml")] + [InlineData("Content-Type", "text/javascript")] [InlineData("Content-Type", "application/pdf")] [InlineData("Content-Type", "application/xml")] [InlineData("Content-Type", "application/zip")] [InlineData("Content-Type", "application/grpc")] [InlineData("Content-Type", "application/json")] + [InlineData("Content-Type", "text/event-stream")] [InlineData("Content-Type", "multipart/form-data")] [InlineData("Content-Type", "application/javascript")] + [InlineData("Content-Type", "text/html;charset=utf-8")] + [InlineData("Content-Type", "text/html;charset=UTF-8")] [InlineData("Content-Type", "application/octet-stream")] [InlineData("Content-Type", "text/html; charset=utf-8")] [InlineData("Content-Type", "text/html; charset=UTF-8")] + [InlineData("Content-Type", "text/plain;charset=utf-8")] + [InlineData("Content-Type", "text/plain;charset=UTF-8")] [InlineData("Content-Type", "text/plain; charset=utf-8")] + [InlineData("Content-Type", "text/plain; charset=UTF-8")] + [InlineData("Content-Type", "text/html; charset=ISO-8859-1")] + [InlineData("Content-Type", "text/html; charset=iso-8859-1")] + [InlineData("Content-Type", "text/javascript; charset=utf-8")] + [InlineData("Content-Type", "text/javascript; charset=UTF-8")] [InlineData("Content-Type", "application/json; charset=utf-8")] [InlineData("Content-Type", "application/x-www-form-urlencoded")] [InlineData("Expect", "100-continue")] @@ -207,8 +223,6 @@ public void TryGetKnownHeader_Unknown_NotFound(string name) [InlineData("Upgrade-Insecure-Requests", "1")] [InlineData("Vary", "*")] [InlineData("X-Content-Type-Options", "nosniff")] - [InlineData("X-Frame-Options", "DENY")] - [InlineData("X-Frame-Options", "SAMEORIGIN")] [InlineData("X-XSS-Protection", "0")] [InlineData("X-XSS-Protection", "1")] [InlineData("X-XSS-Protection", "1; mode=block")]