use super::{HeaderName, HeaderNameInner};
use std::{
fmt::{self, Debug, Display, Formatter},
hash::Hash,
str::FromStr,
};
impl Display for KnownHeaderName {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
f.write_str(self.as_ref())
}
}
impl From<KnownHeaderName> for HeaderName<'_> {
fn from(khn: KnownHeaderName) -> Self {
Self(HeaderNameInner::KnownHeader(khn))
}
}
impl PartialEq<HeaderName<'_>> for KnownHeaderName {
fn eq(&self, other: &HeaderName) -> bool {
matches!(&other.0, HeaderNameInner::KnownHeader(k) if self == k)
}
}
impl AsRef<str> for KnownHeaderName {
fn as_ref(&self) -> &str {
self.as_str()
}
}
macro_rules! known_headers {
(
$(
($capitalized:literal, $variant:tt)
),+
) => {
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)]
#[non_exhaustive]
#[repr(u8)]
pub enum KnownHeaderName {
$(
#[doc = concat!("The [", $capitalized, "](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/", $capitalized, ") header.")]
$variant,
)+
}
impl KnownHeaderName {
pub fn as_str(&self) -> &'static str {
match self {
$( Self::$variant => $capitalized, )+
}
}
}
impl FromStr for KnownHeaderName {
type Err = ();
fn from_str(s: &str) -> Result<Self, Self::Err> {
if !s.is_ascii() { return Err(()); }
let len = s.len();
$( if len == $capitalized.len() && s.eq_ignore_ascii_case($capitalized) { return Ok(Self::$variant); } )+
Err(())
}
}
#[cfg(test)]
mod known_header_name_tests {
use super::*;
#[test]
fn roundtrip_all_variants() {
$(
let parsed: KnownHeaderName = $capitalized.parse()
.unwrap_or_else(|_| panic!("failed to parse {:?}", $capitalized));
assert_eq!(
parsed,
KnownHeaderName::$variant,
"parse({:?}) returned wrong variant",
$capitalized,
);
assert_eq!(
parsed.as_str(),
$capitalized,
"as_str() mismatch for {:?}",
stringify!($variant),
);
)+
}
#[test]
fn case_insensitive_roundtrip() {
$(
let lower: KnownHeaderName = $capitalized.to_lowercase().parse()
.unwrap_or_else(|_| panic!("failed to parse lowercase {:?}", $capitalized));
assert_eq!(lower, KnownHeaderName::$variant);
let upper: KnownHeaderName = $capitalized.to_uppercase().parse()
.unwrap_or_else(|_| panic!("failed to parse uppercase {:?}", $capitalized));
assert_eq!(upper, KnownHeaderName::$variant);
)+
}
#[test]
fn unknown_headers_return_err() {
assert!("X-Unknown-Custom-Header".parse::<KnownHeaderName>().is_err());
assert!("".parse::<KnownHeaderName>().is_err());
assert!("Hostt".parse::<KnownHeaderName>().is_err());
assert!("Hos".parse::<KnownHeaderName>().is_err());
}
}
}
}
known_headers! {
("Host", Host),
("Date", Date),
("Accept", Accept),
("Accept-CH", AcceptCh),
("Accept-CH-Lifetime", AcceptChLifetime),
("Accept-Charset", AcceptCharset),
("Accept-Encoding", AcceptEncoding),
("Accept-Language", AcceptLanguage),
("Accept-Push-Policy", AcceptPushPolicy),
("Accept-Ranges", AcceptRanges),
("Accept-Signature", AcceptSignature),
("Access-Control-Allow-Credentials", AccessControlAllowCredentials),
("Access-Control-Allow-Headers", AccessControlAllowHeaders),
("Access-Control-Allow-Methods", AccessControlAllowMethods),
("Access-Control-Allow-Origin", AccessControlAllowOrigin),
("Access-Control-Expose-Headers", AccessControlExposeHeaders),
("Access-Control-Max-Age", AccessControlMaxAge),
("Access-Control-Request-Headers", AccessControlRequestHeaders),
("Access-Control-Request-Method", AccessControlRequestMethod),
("Age", Age),
("Allow", Allow),
("Alt-Svc", AltSvc),
("Alt-Used", AltUsed),
("Authorization", Authorization),
("Cache-Control", CacheControl),
("Clear-Site-Data", ClearSiteData),
("Connection", Connection),
("Content-DPR", ContentDpr),
("Content-Digest", ContentDigest),
("Content-Disposition", ContentDisposition),
("Content-Encoding", ContentEncoding),
("Content-Language", ContentLanguage),
("Content-Length", ContentLength),
("Content-Location", ContentLocation),
("Content-Range", ContentRange),
("Content-Security-Policy", ContentSecurityPolicy),
("Content-Security-Policy-Report-Only", ContentSecurityPolicyReportOnly),
("Content-Type", ContentType),
("Cookie", Cookie),
("Cookie2", Cookie2),
("Cross-Origin-Embedder-Policy", CrossOriginEmbedderPolicy),
("Cross-Origin-Opener-Policy", CrossOriginOpenerPolicy),
("Cross-Origin-Resource-Policy", CrossOriginResourcePolicy),
("DNT", Dnt),
("DPR", Dpr),
("DPoP", Dpop),
("Deprecation", Deprecation),
("Device-Memory", DeviceMemory),
("Digest", Digest),
("Downlink", Downlink),
("ECT", Ect),
("ETag", Etag),
("Early-Data", EarlyData),
("Expect", Expect),
("Expect-CT", ExpectCt),
("Expires", Expires),
("Feature-Policy", FeaturePolicy),
("Forwarded", Forwarded),
("From", From),
("If-Match", IfMatch),
("If-Modified-Since", IfModifiedSince),
("If-None-Match", IfNoneMatch),
("If-Range", IfRange),
("If-Unmodified-Since", IfUnmodifiedSince),
("Keep-Alive", KeepAlive),
("Large-Allocation", LargeAllocation),
("Last-Event-ID", LastEventId),
("Last-Modified", LastModified),
("Link", Link),
("Location", Location),
("Max-Forwards", MaxForwards),
("NEL", Nel),
("Origin", Origin),
("Origin-Isolation", OriginIsolation),
("Permissions-Policy", PermissionsPolicy),
("Ping-From", PingFrom),
("Ping-To", PingTo),
("Pragma", Pragma),
("Priority", Priority),
("Proxy-Authenticate", ProxyAuthenticate),
("Proxy-Authorization", ProxyAuthorization),
("Proxy-Connection", ProxyConnection),
("Proxy-Status", ProxyStatus),
("Public-Key-Pins", PublicKeyPins),
("Public-Key-Pins-Report-Only", PublicKeyPinsReportOnly),
("Purpose", Purpose),
("Push-Policy", PushPolicy),
("RTT", Rtt),
("Range", Range),
("RateLimit-Reset", RatelimitReset),
("Ratelimit-Limit", RatelimitLimit),
("Ratelimit-Remaining", RatelimitRemaining),
("Referer", Referer),
("Referrer-Policy", ReferrerPolicy),
("Refresh-Cache", RefreshCache),
("Report-To", ReportTo),
("Repr-Digest", ReprDigest),
("Retry-After", RetryAfter),
("Save-Data", SaveData),
("Sec-CH-UA", SecChUa),
("Sec-CH-UA-Mobile", SecChUAMobile),
("Sec-CH-UA-Platform", SecChUAPlatform),
("Sec-Fetch-Dest", SecFetchDest),
("Sec-Fetch-Mode", SecFetchMode),
("Sec-Fetch-Site", SecFetchSite),
("Sec-Fetch-User", SecFetchUser),
("Sec-GPC", SecGpc),
("Sec-WebSocket-Accept", SecWebsocketAccept),
("Sec-WebSocket-Extensions", SecWebsocketExtensions),
("Sec-WebSocket-Key", SecWebsocketKey),
("Sec-WebSocket-Protocol", SecWebsocketProtocol),
("Sec-WebSocket-Version", SecWebsocketVersion),
("Server", Server),
("Server-Timing", ServerTiming),
("Service-Worker-Allowed", ServiceWorkerAllowed),
("Set-Cookie", SetCookie),
("Set-Cookie2", SetCookie2),
("Signature", Signature),
("Signed-Headers", SignedHeaders),
("SourceMap", Sourcemap),
("Strict-Transport-Security", StrictTransportSecurity),
("TE", Te),
("Timing-Allow-Origin", TimingAllowOrigin),
("Traceparent", Traceparent),
("Tracestate", Tracestate),
("Trailer", Trailer),
("Transfer-Encoding", TransferEncoding),
("Upgrade", Upgrade),
("Upgrade-Insecure-Requests", UpgradeInsecureRequests),
("User-Agent", UserAgent),
("Vary", Vary),
("Via", Via),
("Viewport-Width", ViewportWidth),
("WWW-Authenticate", WwwAuthenticate),
("Want-Content-Digest", WantContentDigest),
("Want-Digest", WantDigest),
("Want-Repr-Digest", WantReprDigest),
("Warning", Warning),
("Width", Width),
("X-B3-Traceid", Xb3Traceid),
("X-Cache", Xcache),
("X-Content-Type-Options", XcontentTypeOptions),
("X-Correlation-ID", XcorrelationId),
("X-DNS-Prefetch-Control", XdnsPrefetchControl),
("X-Download-Options", XdownloadOptions),
("X-Firefox-Spdy", XfirefoxSpdy),
("X-Forwarded-By", XforwardedBy),
("X-Forwarded-For", XforwardedFor),
("X-Forwarded-Host", XforwardedHost),
("X-Forwarded-Proto", XforwardedProto),
("X-Forwarded-SSL", XforwardedSsl),
("X-Frame-Options", XframeOptions),
("X-Permitted-Cross-Domain-Policies", XpermittedCrossDomainPolicies),
("X-Pingback", Xpingback),
("X-Powered-By", XpoweredBy),
("X-Real-IP", XrealIp),
("X-Request-Id", XrequestId),
("X-Requested-With", XrequestedWith),
("X-Robots-Tag", XrobotsTag),
("X-Runtime", Xruntime),
("X-Served-By", XservedBy),
("X-UA-Compatible", XuaCompatible),
("X-XSS-Protection", XxssProtection)
}