1pub use crate::HeaderMap;
3#[doc(hidden)]
4pub use crate::map::{AsName, Either, GetAll, Iter, Value};
5pub use crate::value::{HeaderValue, InvalidHeaderValue, ToStrError};
6
7pub use http::header::{
8 ACCEPT, ACCEPT_CHARSET, ACCEPT_ENCODING, ACCEPT_LANGUAGE, ACCEPT_RANGES,
9 ACCESS_CONTROL_ALLOW_CREDENTIALS, ACCESS_CONTROL_ALLOW_HEADERS, ACCESS_CONTROL_ALLOW_METHODS,
10 ACCESS_CONTROL_ALLOW_ORIGIN, ACCESS_CONTROL_EXPOSE_HEADERS, ACCESS_CONTROL_MAX_AGE,
11 ACCESS_CONTROL_REQUEST_HEADERS, ACCESS_CONTROL_REQUEST_METHOD, AGE, ALLOW, ALT_SVC,
12 AUTHORIZATION, CACHE_CONTROL, CONNECTION, CONTENT_DISPOSITION, CONTENT_ENCODING,
13 CONTENT_LANGUAGE, CONTENT_LENGTH, CONTENT_LOCATION, CONTENT_RANGE, CONTENT_SECURITY_POLICY,
14 CONTENT_SECURITY_POLICY_REPORT_ONLY, CONTENT_TYPE, COOKIE, DATE, DNT, ETAG, EXPECT, EXPIRES,
15 FORWARDED, FROM, HOST, IF_MATCH, IF_MODIFIED_SINCE, IF_NONE_MATCH, IF_RANGE,
16 IF_UNMODIFIED_SINCE, LAST_MODIFIED, LINK, LOCATION, MAX_FORWARDS, ORIGIN, PRAGMA,
17 PROXY_AUTHENTICATE, PROXY_AUTHORIZATION, PUBLIC_KEY_PINS, PUBLIC_KEY_PINS_REPORT_ONLY, RANGE,
18 REFERER, REFERRER_POLICY, REFRESH, RETRY_AFTER, SEC_WEBSOCKET_ACCEPT, SEC_WEBSOCKET_EXTENSIONS,
19 SEC_WEBSOCKET_KEY, SEC_WEBSOCKET_PROTOCOL, SEC_WEBSOCKET_VERSION, SERVER, SET_COOKIE,
20 STRICT_TRANSPORT_SECURITY, TE, TRAILER, TRANSFER_ENCODING, UPGRADE, UPGRADE_INSECURE_REQUESTS,
21 USER_AGENT, VARY, VIA, WARNING, WWW_AUTHENTICATE, X_CONTENT_TYPE_OPTIONS,
22 X_DNS_PREFETCH_CONTROL, X_FRAME_OPTIONS, X_XSS_PROTECTION,
23};
24pub use http::header::{HeaderName, InvalidHeaderName};
25
26pub use crate::error::InvalidContentEncoding;
27
28#[derive(Copy, Clone, PartialEq, Eq, Debug)]
30pub enum ContentEncoding {
31 Auto,
33 Br,
35 Deflate,
37 Gzip,
39 Zstd,
41 Identity,
43}
44
45impl ContentEncoding {
46 #[inline]
47 pub fn is_compressed(self) -> bool {
49 !matches!(self, ContentEncoding::Identity | ContentEncoding::Auto)
50 }
51
52 #[inline]
53 pub fn as_str(self) -> &'static str {
55 match self {
56 ContentEncoding::Br => "br",
57 ContentEncoding::Gzip => "gzip",
58 ContentEncoding::Deflate => "deflate",
59 ContentEncoding::Zstd => "zstd",
60 ContentEncoding::Identity | ContentEncoding::Auto => "identity",
61 }
62 }
63
64 #[inline]
65 pub fn quality(self) -> f64 {
67 match self {
68 ContentEncoding::Br => 1.1,
69 ContentEncoding::Zstd => 1.05,
70 ContentEncoding::Gzip => 1.0,
71 ContentEncoding::Deflate => 0.9,
72 ContentEncoding::Identity | ContentEncoding::Auto => 0.1,
73 }
74 }
75}
76
77impl std::str::FromStr for ContentEncoding {
78 type Err = InvalidContentEncoding;
79
80 fn from_str(s: &str) -> Result<ContentEncoding, InvalidContentEncoding> {
87 let s = s.trim();
88
89 if s.eq_ignore_ascii_case("br") {
90 Ok(ContentEncoding::Br)
91 } else if s.eq_ignore_ascii_case("gzip") || s.eq_ignore_ascii_case("x-gzip") {
92 Ok(ContentEncoding::Gzip)
93 } else if s.eq_ignore_ascii_case("deflate") {
94 Ok(ContentEncoding::Deflate)
95 } else if s.eq_ignore_ascii_case("zstd") {
96 Ok(ContentEncoding::Zstd)
97 } else if s.eq_ignore_ascii_case("identity") {
98 Ok(ContentEncoding::Identity)
99 } else {
100 Err(InvalidContentEncoding::new())
101 }
102 }
103}
104
105#[cfg(test)]
106mod tests {
107 use super::*;
108
109 #[test]
115 fn encoding() {
116 assert!(ContentEncoding::Br.is_compressed());
117 assert!(!ContentEncoding::Identity.is_compressed());
118 assert!(!ContentEncoding::Auto.is_compressed());
119 assert_eq!(format!("{:?}", ContentEncoding::Identity), "Identity");
120
121 assert!(ContentEncoding::Zstd.is_compressed());
122 assert_eq!(ContentEncoding::Zstd.as_str(), "zstd");
123 assert!(ContentEncoding::Br.quality() > ContentEncoding::Zstd.quality());
124 assert!(ContentEncoding::Zstd.quality() > ContentEncoding::Gzip.quality());
125 }
126
127 #[test]
135 fn parse() {
136 for (s, enc) in [
137 ("br", ContentEncoding::Br),
138 ("gzip", ContentEncoding::Gzip),
139 ("X-Gzip", ContentEncoding::Gzip),
140 ("Deflate", ContentEncoding::Deflate),
141 (" ZStd ", ContentEncoding::Zstd),
142 ("identity", ContentEncoding::Identity),
143 ("IDENTITY", ContentEncoding::Identity),
144 ] {
145 assert_eq!(s.parse::<ContentEncoding>(), Ok(enc), "{s:?}");
146 }
147
148 for s in ["gizp", "x-zstd", "compress", "auto", "gzip, br", "", " "] {
149 let err = s.parse::<ContentEncoding>().unwrap_err();
150 assert_eq!(err.to_string(), "Unsupported content encoding");
151 assert!(
152 crate::Error::from(err).is::<InvalidContentEncoding>(),
153 "{s:?}"
154 );
155 }
156 }
157}