Skip to main content

min_http11_core/
request.rs

1use crate::error::{Error, Result};
2use crate::util::AsciiLowercaseTestExt;
3use std::convert::{TryFrom, TryInto};
4use std::fmt::{Display, Formatter};
5
6mod minimal {
7    #[cfg(feature = "_minimal")]
8    use crate::error::{Error, Result};
9    #[cfg(feature = "_minimal")]
10    use crate::hash::hash;
11
12    pub const CONTENT_LENGTH: &[u8] = b"content-length";
13    pub const HOST: &[u8] = b"host";
14    pub const TRANSFER_ENCODING: &[u8] = b"transfer-encoding";
15    pub const IF_MATCH: &[u8] = b"if-match";
16    pub const IF_NONE_MATCH: &[u8] = b"if-none-match";
17    pub const X_HUB_SIGNATURE_256: &[u8] = b"x-hub-signature-256";
18
19    pub const CONTENT_LENGTH_HASH: u32 = 314322716;
20    pub const HOST_HASH: u32 = 3475444733;
21    pub const TRANSFER_ENCODING_HASH: u32 = 1470906230;
22    pub const IF_MATCH_HASH: u32 = 1168849366;
23    pub const IF_NONE_MATCH_HASH: u32 = 1529156225;
24    pub const X_HUB_SIGNATURE_256_HASH: u32 = 1932839174;
25
26    #[cfg(feature = "_minimal")]
27    #[derive(Default)]
28    pub struct KnownHeaders<'a> {
29        pub content_length: Option<&'a [u8]>,
30        pub host: Option<&'a [u8]>,
31        pub transfer_encoding: Option<&'a [u8]>,
32        pub if_match: Option<&'a [u8]>,
33        pub if_none_match: Option<&'a [u8]>,
34        pub x_hub_signature_256_hash: Option<&'a [u8]>,
35    }
36
37    #[cfg(feature = "_minimal")]
38    #[derive(Debug, Clone, Ord, PartialOrd, Eq, PartialEq)]
39    pub enum HeaderName {
40        ContentLength,
41        Host,
42        TransferEncoding,
43        IfMatch,
44        IfNoneMatch,
45        XHubSignature256,
46
47        Other(&'static [u8]),
48        Unknown(Vec<u8>),
49    }
50
51    #[cfg(feature = "_minimal")]
52    pub(crate) fn _try_from_lowercase(value: &[u8], lowercase: &[u8]) -> Result<HeaderName> {
53        match hash(lowercase) {
54            CONTENT_LENGTH_HASH if lowercase == CONTENT_LENGTH => Ok(HeaderName::ContentLength),
55            HOST_HASH if lowercase == HOST => Ok(HeaderName::Host),
56            TRANSFER_ENCODING_HASH if lowercase == TRANSFER_ENCODING => {
57                Ok(HeaderName::TransferEncoding)
58            }
59            IF_MATCH_HASH if lowercase == IF_MATCH => Ok(HeaderName::IfMatch),
60            IF_NONE_MATCH_HASH if lowercase == IF_NONE_MATCH => Ok(HeaderName::IfNoneMatch),
61            X_HUB_SIGNATURE_256_HASH if lowercase == X_HUB_SIGNATURE_256 => {
62                Ok(HeaderName::XHubSignature256)
63            }
64            _ => Err(Error::UnknownHeaderName(value.escape_ascii().to_string())),
65        }
66    }
67
68    #[cfg(feature = "_minimal")]
69    impl TryFrom<&HeaderName> for &'static [u8] {
70        type Error = Error;
71
72        fn try_from(value: &HeaderName) -> Result<Self> {
73            match value {
74                HeaderName::ContentLength => Ok(CONTENT_LENGTH),
75                HeaderName::Host => Ok(HOST),
76                HeaderName::TransferEncoding => Ok(TRANSFER_ENCODING),
77                HeaderName::IfMatch => Ok(IF_MATCH),
78                HeaderName::IfNoneMatch => Ok(IF_NONE_MATCH),
79                HeaderName::XHubSignature256 => Ok(X_HUB_SIGNATURE_256),
80                HeaderName::Other(value) => Ok(value),
81                HeaderName::Unknown(value) => {
82                    Err(Error::UnknownHeaderName(value.escape_ascii().to_string()))
83                }
84            }
85        }
86    }
87}
88
89#[cfg(not(feature = "_minimal"))]
90mod others {
91    use super::minimal::*;
92    use crate::error::{Error, Result};
93    use crate::hash::hash;
94    use crate::request::{
95        CONTENT_LENGTH_HASH, HOST_HASH, IF_MATCH_HASH, IF_NONE_MATCH_HASH, X_HUB_SIGNATURE_256_HASH,
96    };
97
98    pub const ACCEPT: &[u8] = b"accept";
99    pub const ACCEPT_ENCODING: &[u8] = b"accept-encoding";
100    pub const ACCEPT_LANGUAGE: &[u8] = b"accept-language";
101    pub const ACCESS_CONTROL_REQUEST_HEADERS: &[u8] = b"access-control-request-headers";
102    pub const ACCESS_CONTROL_REQUEST_METHOD: &[u8] = b"access-control-request-method";
103    pub const AUTHORIZATION: &[u8] = b"authorization";
104    pub const CONNECTION: &[u8] = b"connection";
105    pub const CONTENT_ENCODING: &[u8] = b"content-encoding";
106    pub const CONTENT_TYPE: &[u8] = b"content-type";
107    pub const COOKIE: &[u8] = b"cookie";
108    pub const EXPECT: &[u8] = b"expect";
109    pub const IF_MODIFIED_SINCE: &[u8] = b"if-modified-since";
110    pub const IF_RANGE: &[u8] = b"if-range";
111    pub const IF_UNMODIFIED_SINCE: &[u8] = b"if-unmodified-since";
112    pub const ORIGIN: &[u8] = b"origin";
113    pub const RANGE: &[u8] = b"range";
114    pub const REFERER: &[u8] = b"referer";
115    pub const SEC_CH_UA: &[u8] = b"sec-ch-ua";
116    pub const SEC_CH_UA_MOBILE: &[u8] = b"sec-ch-ua-mobile";
117    pub const SEC_CH_UA_PLATFORM: &[u8] = b"sec-ch-ua-platform";
118    pub const SEC_FETCH_DEST: &[u8] = b"sec-fetch-dest";
119    pub const SEC_FETCH_MODE: &[u8] = b"sec-fetch-mode";
120    pub const SEC_FETCH_SITE: &[u8] = b"sec-fetch-site";
121    pub const SEC_FETCH_USER: &[u8] = b"sec-fetch-user";
122    pub const USER_AGENT: &[u8] = b"user-agent";
123    pub const X_CSRF_TOKEN: &[u8] = b"x-csrf-token";
124    pub const X_FORWARDED_FOR: &[u8] = b"x-forwarded-for";
125    pub const X_FORWARDED_HOST: &[u8] = b"x-forwarded-host";
126    pub const X_REAL_IP: &[u8] = b"x-real-ip";
127
128    pub const ACCEPT_HASH: u32 = 3005279540;
129    pub const ACCEPT_ENCODING_HASH: u32 = 2687938133;
130    pub const ACCEPT_LANGUAGE_HASH: u32 = 480585391;
131    pub const ACCESS_CONTROL_REQUEST_HEADERS_HASH: u32 = 3862518975;
132    pub const ACCESS_CONTROL_REQUEST_METHOD_HASH: u32 = 1698782395;
133    pub const AUTHORIZATION_HASH: u32 = 2053999599;
134    pub const CONNECTION_HASH: u32 = 704082790;
135    pub const CONTENT_ENCODING_HASH: u32 = 3836410099;
136    pub const CONTENT_TYPE_HASH: u32 = 3266185539;
137    pub const COOKIE_HASH: u32 = 2329983590;
138    pub const EXPECT_HASH: u32 = 482521170;
139    pub const IF_MODIFIED_SINCE_HASH: u32 = 1848278858;
140    pub const IF_RANGE_HASH: u32 = 2893522586;
141    pub const IF_UNMODIFIED_SINCE_HASH: u32 = 462614015;
142    pub const ORIGIN_HASH: u32 = 3740358174;
143    pub const RANGE_HASH: u32 = 2475121225;
144    pub const REFERER_HASH: u32 = 1440495237;
145    pub const SEC_CH_UA_HASH: u32 = 3458784846;
146    pub const SEC_CH_UA_MOBILE_HASH: u32 = 3851717610;
147    pub const SEC_CH_UA_PLATFORM_HASH: u32 = 464571004;
148    pub const SEC_FETCH_DEST_HASH: u32 = 1781535743;
149    pub const SEC_FETCH_MODE_HASH: u32 = 1973190087;
150    pub const SEC_FETCH_SITE_HASH: u32 = 2333422472;
151    pub const SEC_FETCH_USER_HASH: u32 = 1875242021;
152    pub const USER_AGENT_HASH: u32 = 2191772431;
153    pub const X_CSRF_TOKEN_HASH: u32 = 3276872746;
154    pub const X_FORWARDED_FOR_HASH: u32 = 2397052407;
155    pub const X_FORWARDED_HOST_HASH: u32 = 1610193784;
156    pub const X_REAL_IP_HASH: u32 = 3988930344;
157
158    #[derive(Default)]
159    pub struct KnownHeaders<'a> {
160        pub accept: Option<&'a [u8]>,
161        pub accept_encoding: Option<&'a [u8]>,
162        pub accept_language: Option<&'a [u8]>,
163        pub access_control_request_headers: Option<&'a [u8]>,
164        pub access_control_request_method: Option<&'a [u8]>,
165        pub authorization: Option<&'a [u8]>,
166        pub connection: Option<&'a [u8]>,
167        pub content_encoding: Option<&'a [u8]>,
168        pub content_length: Option<&'a [u8]>,
169        pub content_type: Option<&'a [u8]>,
170        pub cookie: Option<&'a [u8]>,
171        pub expect: Option<&'a [u8]>,
172        pub host: Option<&'a [u8]>,
173        pub if_match: Option<&'a [u8]>,
174        pub if_modified_since: Option<&'a [u8]>,
175        pub if_none_match: Option<&'a [u8]>,
176        pub if_range: Option<&'a [u8]>,
177        pub if_unmodified_since: Option<&'a [u8]>,
178        pub origin: Option<&'a [u8]>,
179        pub range: Option<&'a [u8]>,
180        pub referer: Option<&'a [u8]>,
181        pub sec_ch_ua: Option<&'a [u8]>,
182        pub sec_ch_ua_mobile: Option<&'a [u8]>,
183        pub sec_ch_ua_platform: Option<&'a [u8]>,
184        pub sec_fetch_dest: Option<&'a [u8]>,
185        pub sec_fetch_mode: Option<&'a [u8]>,
186        pub sec_fetch_site: Option<&'a [u8]>,
187        pub sec_fetch_user: Option<&'a [u8]>,
188        pub transfer_encoding: Option<&'a [u8]>,
189        pub user_agent: Option<&'a [u8]>,
190        pub x_csrf_token: Option<&'a [u8]>,
191        pub x_forwarded_for: Option<&'a [u8]>,
192        pub x_forwarded_host: Option<&'a [u8]>,
193        pub x_real_ip: Option<&'a [u8]>,
194        pub x_hub_signature_256_hash: Option<&'a [u8]>,
195    }
196
197    #[derive(Debug, Clone, Ord, PartialOrd, Eq, PartialEq)]
198    pub enum HeaderName {
199        Accept,
200        AcceptEncoding,
201        AcceptLanguage,
202        AccessControlRequestHeaders,
203        AccessControlRequestMethod,
204        Authorization,
205        Connection,
206        ContentEncoding,
207        ContentLength,
208        ContentType,
209        Cookie,
210        Expect,
211        Host,
212        IfMatch,
213        IfModifiedSince,
214        IfNoneMatch,
215        IfRange,
216        IfUnmodifiedSince,
217        Origin,
218        Range,
219        Referer,
220        SecChUa,
221        SecChUaMobile,
222        SecChUaPlatform,
223        SecFetchDest,
224        SecFetchMode,
225        SecFetchSite,
226        SecFetchUser,
227        TransferEncoding,
228        UserAgent,
229        XCSRFToken,
230        XForwardedFor,
231        XForwardedHost,
232        XRealIp,
233        XHubSignature256,
234
235        Other(&'static [u8]),
236        Unknown(Vec<u8>),
237    }
238
239    pub(crate) fn _try_from_lowercase(value: &[u8], lowercase: &[u8]) -> Result<HeaderName> {
240        match hash(lowercase) {
241            ACCEPT_HASH if lowercase == ACCEPT => Ok(HeaderName::Accept),
242            ACCEPT_ENCODING_HASH if lowercase == ACCEPT_ENCODING => Ok(HeaderName::AcceptEncoding),
243            ACCEPT_LANGUAGE_HASH if lowercase == ACCEPT_LANGUAGE => Ok(HeaderName::AcceptLanguage),
244            ACCESS_CONTROL_REQUEST_HEADERS_HASH if lowercase == ACCESS_CONTROL_REQUEST_HEADERS => {
245                Ok(HeaderName::AccessControlRequestHeaders)
246            }
247            ACCESS_CONTROL_REQUEST_METHOD_HASH if lowercase == ACCESS_CONTROL_REQUEST_METHOD => {
248                Ok(HeaderName::AccessControlRequestMethod)
249            }
250            AUTHORIZATION_HASH if lowercase == AUTHORIZATION => Ok(HeaderName::Authorization),
251            CONNECTION_HASH if lowercase == CONNECTION => Ok(HeaderName::Connection),
252            CONTENT_ENCODING_HASH if lowercase == CONTENT_ENCODING => {
253                Ok(HeaderName::ContentEncoding)
254            }
255            CONTENT_LENGTH_HASH if lowercase == CONTENT_LENGTH => Ok(HeaderName::ContentLength),
256            CONTENT_TYPE_HASH if lowercase == CONTENT_TYPE => Ok(HeaderName::ContentType),
257            COOKIE_HASH if lowercase == COOKIE => Ok(HeaderName::Cookie),
258            EXPECT_HASH if lowercase == EXPECT => Ok(HeaderName::Expect),
259            HOST_HASH if lowercase == HOST => Ok(HeaderName::Host),
260            IF_MATCH_HASH if lowercase == IF_MATCH => Ok(HeaderName::IfMatch),
261            IF_MODIFIED_SINCE_HASH if lowercase == IF_MODIFIED_SINCE => {
262                Ok(HeaderName::IfModifiedSince)
263            }
264            IF_NONE_MATCH_HASH if lowercase == IF_NONE_MATCH => Ok(HeaderName::IfNoneMatch),
265            IF_RANGE_HASH if lowercase == IF_RANGE => Ok(HeaderName::IfRange),
266            IF_UNMODIFIED_SINCE_HASH if lowercase == IF_UNMODIFIED_SINCE => {
267                Ok(HeaderName::IfUnmodifiedSince)
268            }
269            ORIGIN_HASH if lowercase == ORIGIN => Ok(HeaderName::Origin),
270            RANGE_HASH if lowercase == RANGE => Ok(HeaderName::Range),
271            REFERER_HASH if lowercase == REFERER => Ok(HeaderName::Referer),
272            SEC_CH_UA_HASH if lowercase == SEC_CH_UA => Ok(HeaderName::SecChUa),
273            SEC_CH_UA_MOBILE_HASH if lowercase == SEC_CH_UA_MOBILE => Ok(HeaderName::SecChUaMobile),
274            SEC_CH_UA_PLATFORM_HASH if lowercase == SEC_CH_UA_PLATFORM => {
275                Ok(HeaderName::SecChUaPlatform)
276            }
277            SEC_FETCH_DEST_HASH if lowercase == SEC_FETCH_DEST => Ok(HeaderName::SecFetchDest),
278            SEC_FETCH_MODE_HASH if lowercase == SEC_FETCH_MODE => Ok(HeaderName::SecFetchMode),
279            SEC_FETCH_SITE_HASH if lowercase == SEC_FETCH_SITE => Ok(HeaderName::SecFetchSite),
280            SEC_FETCH_USER_HASH if lowercase == SEC_FETCH_USER => Ok(HeaderName::SecFetchUser),
281            TRANSFER_ENCODING_HASH if lowercase == TRANSFER_ENCODING => {
282                Ok(HeaderName::TransferEncoding)
283            }
284            USER_AGENT_HASH if lowercase == USER_AGENT => Ok(HeaderName::UserAgent),
285            X_CSRF_TOKEN_HASH if lowercase == X_CSRF_TOKEN => Ok(HeaderName::XCSRFToken),
286            X_FORWARDED_FOR_HASH if lowercase == X_FORWARDED_FOR => Ok(HeaderName::XForwardedFor),
287            X_FORWARDED_HOST_HASH if lowercase == X_FORWARDED_HOST => {
288                Ok(HeaderName::XForwardedHost)
289            }
290            X_HUB_SIGNATURE_256_HASH if lowercase == X_HUB_SIGNATURE_256 => {
291                Ok(HeaderName::XHubSignature256)
292            }
293            X_REAL_IP_HASH if lowercase == X_REAL_IP => Ok(HeaderName::XRealIp),
294            _ => Err(Error::UnknownHeaderName(value.escape_ascii().to_string())),
295        }
296    }
297
298    impl TryFrom<&HeaderName> for &'static [u8] {
299        type Error = Error;
300
301        fn try_from(value: &HeaderName) -> Result<Self> {
302            match value {
303                HeaderName::Accept => Ok(ACCEPT),
304                HeaderName::AcceptEncoding => Ok(ACCEPT_ENCODING),
305                HeaderName::AcceptLanguage => Ok(ACCEPT_LANGUAGE),
306                HeaderName::AccessControlRequestHeaders => Ok(ACCESS_CONTROL_REQUEST_HEADERS),
307                HeaderName::AccessControlRequestMethod => Ok(ACCESS_CONTROL_REQUEST_METHOD),
308                HeaderName::Authorization => Ok(AUTHORIZATION),
309                HeaderName::Connection => Ok(CONNECTION),
310                HeaderName::ContentEncoding => Ok(CONTENT_ENCODING),
311                HeaderName::ContentLength => Ok(CONTENT_LENGTH),
312                HeaderName::ContentType => Ok(CONTENT_TYPE),
313                HeaderName::Cookie => Ok(COOKIE),
314                HeaderName::Expect => Ok(EXPECT),
315                HeaderName::Host => Ok(HOST),
316                HeaderName::IfMatch => Ok(IF_MATCH),
317                HeaderName::IfModifiedSince => Ok(IF_MODIFIED_SINCE),
318                HeaderName::IfNoneMatch => Ok(IF_NONE_MATCH),
319                HeaderName::IfRange => Ok(IF_RANGE),
320                HeaderName::IfUnmodifiedSince => Ok(IF_UNMODIFIED_SINCE),
321                HeaderName::Origin => Ok(ORIGIN),
322                HeaderName::Range => Ok(RANGE),
323                HeaderName::Referer => Ok(REFERER),
324                HeaderName::SecChUa => Ok(SEC_CH_UA),
325                HeaderName::SecChUaMobile => Ok(SEC_CH_UA_MOBILE),
326                HeaderName::SecChUaPlatform => Ok(SEC_CH_UA_PLATFORM),
327                HeaderName::SecFetchDest => Ok(SEC_FETCH_DEST),
328                HeaderName::SecFetchMode => Ok(SEC_FETCH_MODE),
329                HeaderName::SecFetchSite => Ok(SEC_FETCH_SITE),
330                HeaderName::SecFetchUser => Ok(SEC_FETCH_USER),
331                HeaderName::TransferEncoding => Ok(TRANSFER_ENCODING),
332                HeaderName::UserAgent => Ok(USER_AGENT),
333                HeaderName::XCSRFToken => Ok(X_CSRF_TOKEN),
334                HeaderName::XForwardedFor => Ok(X_FORWARDED_FOR),
335                HeaderName::XForwardedHost => Ok(X_FORWARDED_HOST),
336                HeaderName::XRealIp => Ok(X_REAL_IP),
337                HeaderName::XHubSignature256 => Ok(X_HUB_SIGNATURE_256),
338                HeaderName::Other(value) => Ok(value),
339                HeaderName::Unknown(value) => {
340                    Err(Error::UnknownHeaderName(value.escape_ascii().to_string()))
341                }
342            }
343        }
344    }
345}
346
347pub use minimal::*;
348#[cfg(not(feature = "_minimal"))]
349pub use others::*;
350
351impl HeaderName {
352    pub fn as_slice(&self) -> &[u8] {
353        match self {
354            HeaderName::Unknown(vec) => vec.as_slice(),
355            _ => self.try_into().unwrap(),
356        }
357    }
358    pub fn try_from_static(value: &'static [u8]) -> Result<Self> {
359        value.try_into().or_else(|_| {
360            if value.is_ascii_lowercase() {
361                Ok(HeaderName::Other(value))
362            } else {
363                Err(Error::CustomHeaderNameNotLowercase(
364                    String::from_utf8_lossy(value).to_string(),
365                ))
366            }
367        })
368    }
369    pub fn owned(value: &[u8]) -> Result<Self> {
370        match value.try_into() {
371            Err(_) => {
372                let lowercase = value.to_ascii_lowercase();
373                if lowercase.is_ascii_lowercase() {
374                    Ok(HeaderName::Unknown(value.to_ascii_lowercase()))
375                } else {
376                    Err(Error::InvalidHeaderName(value.escape_ascii().to_string()))
377                }
378            }
379            it => it,
380        }
381    }
382}
383
384impl Display for HeaderName {
385    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
386        write!(f, "{}", self.as_slice().escape_ascii())
387    }
388}
389
390impl<'a, const N: usize> TryFrom<&'a [u8; N]> for HeaderName {
391    type Error = Error;
392
393    fn try_from(value: &'a [u8; N]) -> Result<Self> {
394        value.as_slice().try_into()
395    }
396}
397
398impl<'a> TryFrom<&'a [u8]> for HeaderName {
399    type Error = Error;
400
401    fn try_from(value: &'a [u8]) -> Result<Self> {
402        if value.is_ascii_lowercase() {
403            _try_from_lowercase(value, value)
404        } else {
405            _try_from_lowercase(value, value.to_ascii_lowercase().as_slice())
406        }
407    }
408}
409
410impl AsRef<[u8]> for HeaderName {
411    fn as_ref(&self) -> &[u8] {
412        self.as_slice()
413    }
414}
415
416impl TryFrom<&str> for HeaderName {
417    type Error = Error;
418
419    fn try_from(value: &str) -> Result<Self> {
420        let value = value.as_bytes();
421        if value.is_ascii_lowercase() {
422            value.try_into()
423        } else {
424            value.to_ascii_lowercase().as_slice().try_into()
425        }
426    }
427}
428
429#[cfg(test)]
430#[cfg(not(feature = "_minimal"))]
431mod test {
432    use super::*;
433
434    #[test]
435    fn from_bytes() {
436        assert_eq!(ACCEPT.try_into(), Ok(HeaderName::Accept));
437        assert_eq!(ACCEPT_ENCODING.try_into(), Ok(HeaderName::AcceptEncoding));
438        assert_eq!(ACCEPT_LANGUAGE.try_into(), Ok(HeaderName::AcceptLanguage));
439        assert_eq!(
440            ACCESS_CONTROL_REQUEST_HEADERS.try_into(),
441            Ok(HeaderName::AccessControlRequestHeaders)
442        );
443        assert_eq!(
444            ACCESS_CONTROL_REQUEST_METHOD.try_into(),
445            Ok(HeaderName::AccessControlRequestMethod)
446        );
447        assert_eq!(AUTHORIZATION.try_into(), Ok(HeaderName::Authorization));
448        assert_eq!(CONNECTION.try_into(), Ok(HeaderName::Connection));
449        assert_eq!(CONTENT_ENCODING.try_into(), Ok(HeaderName::ContentEncoding));
450        assert_eq!(CONTENT_LENGTH.try_into(), Ok(HeaderName::ContentLength));
451        assert_eq!(CONTENT_TYPE.try_into(), Ok(HeaderName::ContentType));
452        assert_eq!(COOKIE.try_into(), Ok(HeaderName::Cookie));
453        assert_eq!(EXPECT.try_into(), Ok(HeaderName::Expect));
454        assert_eq!(HOST.try_into(), Ok(HeaderName::Host));
455        assert_eq!(IF_MATCH.try_into(), Ok(HeaderName::IfMatch));
456        assert_eq!(
457            IF_MODIFIED_SINCE.try_into(),
458            Ok(HeaderName::IfModifiedSince)
459        );
460        assert_eq!(IF_NONE_MATCH.try_into(), Ok(HeaderName::IfNoneMatch));
461        assert_eq!(IF_RANGE.try_into(), Ok(HeaderName::IfRange));
462        assert_eq!(
463            IF_UNMODIFIED_SINCE.try_into(),
464            Ok(HeaderName::IfUnmodifiedSince)
465        );
466        assert_eq!(ORIGIN.try_into(), Ok(HeaderName::Origin));
467        assert_eq!(RANGE.try_into(), Ok(HeaderName::Range));
468        assert_eq!(REFERER.try_into(), Ok(HeaderName::Referer));
469        assert_eq!(SEC_CH_UA.try_into(), Ok(HeaderName::SecChUa));
470        assert_eq!(SEC_CH_UA_MOBILE.try_into(), Ok(HeaderName::SecChUaMobile));
471        assert_eq!(
472            SEC_CH_UA_PLATFORM.try_into(),
473            Ok(HeaderName::SecChUaPlatform)
474        );
475        assert_eq!(SEC_FETCH_DEST.try_into(), Ok(HeaderName::SecFetchDest));
476        assert_eq!(SEC_FETCH_MODE.try_into(), Ok(HeaderName::SecFetchMode));
477        assert_eq!(SEC_FETCH_SITE.try_into(), Ok(HeaderName::SecFetchSite));
478        assert_eq!(SEC_FETCH_USER.try_into(), Ok(HeaderName::SecFetchUser));
479        assert_eq!(
480            TRANSFER_ENCODING.try_into(),
481            Ok(HeaderName::TransferEncoding)
482        );
483        assert_eq!(USER_AGENT.try_into(), Ok(HeaderName::UserAgent));
484        assert_eq!(X_CSRF_TOKEN.try_into(), Ok(HeaderName::XCSRFToken));
485        assert_eq!(X_FORWARDED_FOR.try_into(), Ok(HeaderName::XForwardedFor));
486        assert_eq!(X_FORWARDED_HOST.try_into(), Ok(HeaderName::XForwardedHost));
487        assert_eq!(X_REAL_IP.try_into(), Ok(HeaderName::XRealIp));
488        assert_eq!(
489            X_HUB_SIGNATURE_256.try_into(),
490            Ok(HeaderName::XHubSignature256)
491        );
492        let unknown: Result<HeaderName> = b"UNKNOWN".try_into();
493        assert!(unknown.is_err());
494        let unknown: Result<HeaderName> = HeaderName::try_from_static(b"Unknown");
495        assert!(unknown.is_err());
496        assert_eq!(HeaderName::try_from_static(b"Host"), Ok(HeaderName::Host));
497        assert_eq!(
498            HeaderName::try_from_static(b"origin"),
499            Ok(HeaderName::Origin)
500        );
501        assert_eq!(
502            HeaderName::try_from_static(b"unknown"),
503            Ok(HeaderName::Other(b"unknown"))
504        );
505        assert_eq!(
506            HeaderName::owned(b"HOST").unwrap().try_into(),
507            Ok(HeaderName::Host)
508        );
509        assert_eq!(
510            HeaderName::owned(b"accept").unwrap().try_into(),
511            Ok(HeaderName::Accept)
512        );
513        assert_eq!(
514            HeaderName::owned(b"Unknown").unwrap().try_into(),
515            Ok(HeaderName::Unknown(b"unknown".to_vec()))
516        );
517        assert_eq!(
518            HeaderName::owned(b"unknown").unwrap().try_into(),
519            Ok(HeaderName::Unknown(b"unknown".to_vec()))
520        );
521    }
522
523    #[test]
524    fn from_str() {
525        assert_eq!("Accept".try_into(), Ok(HeaderName::Accept));
526        assert_eq!("accept".try_into(), Ok(HeaderName::Accept));
527        assert_eq!("ACCEPT".try_into(), Ok(HeaderName::Accept));
528        assert_eq!("Accept-Encoding".try_into(), Ok(HeaderName::AcceptEncoding));
529        assert_eq!("accept-encoding".try_into(), Ok(HeaderName::AcceptEncoding));
530        assert_eq!("ACCEPT-ENCODING".try_into(), Ok(HeaderName::AcceptEncoding));
531        assert_eq!("Accept-Language".try_into(), Ok(HeaderName::AcceptLanguage));
532        assert_eq!("accept-language".try_into(), Ok(HeaderName::AcceptLanguage));
533        assert_eq!("ACCEPT-LANGUAGE".try_into(), Ok(HeaderName::AcceptLanguage));
534        assert_eq!(
535            "Access-Control-Request-Headers".try_into(),
536            Ok(HeaderName::AccessControlRequestHeaders)
537        );
538        assert_eq!(
539            "access-control-request-headers".try_into(),
540            Ok(HeaderName::AccessControlRequestHeaders)
541        );
542        assert_eq!(
543            "ACCESS-CONTROL-REQUEST-HEADERS".try_into(),
544            Ok(HeaderName::AccessControlRequestHeaders)
545        );
546        assert_eq!(
547            "Access-Control-Request-Method".try_into(),
548            Ok(HeaderName::AccessControlRequestMethod)
549        );
550        assert_eq!(
551            "access-control-request-method".try_into(),
552            Ok(HeaderName::AccessControlRequestMethod)
553        );
554        assert_eq!(
555            "ACCESS-CONTROL-REQUEST-METHOD".try_into(),
556            Ok(HeaderName::AccessControlRequestMethod)
557        );
558        assert_eq!("Authorization".try_into(), Ok(HeaderName::Authorization));
559        assert_eq!("authorization".try_into(), Ok(HeaderName::Authorization));
560        assert_eq!("AUTHORIZATION".try_into(), Ok(HeaderName::Authorization));
561        assert_eq!("Connection".try_into(), Ok(HeaderName::Connection));
562        assert_eq!("connection".try_into(), Ok(HeaderName::Connection));
563        assert_eq!("CONNECTION".try_into(), Ok(HeaderName::Connection));
564        assert_eq!(
565            "Content-Encoding".try_into(),
566            Ok(HeaderName::ContentEncoding)
567        );
568        assert_eq!(
569            "content-encoding".try_into(),
570            Ok(HeaderName::ContentEncoding)
571        );
572        assert_eq!(
573            "CONTENT-ENCODING".try_into(),
574            Ok(HeaderName::ContentEncoding)
575        );
576        assert_eq!("Content-Length".try_into(), Ok(HeaderName::ContentLength));
577        assert_eq!("content-length".try_into(), Ok(HeaderName::ContentLength));
578        assert_eq!("CONTENT-LENGTH".try_into(), Ok(HeaderName::ContentLength));
579        assert_eq!("Content-Type".try_into(), Ok(HeaderName::ContentType));
580        assert_eq!("content-type".try_into(), Ok(HeaderName::ContentType));
581        assert_eq!("CONTENT-TYPE".try_into(), Ok(HeaderName::ContentType));
582        assert_eq!("Cookie".try_into(), Ok(HeaderName::Cookie));
583        assert_eq!("cookie".try_into(), Ok(HeaderName::Cookie));
584        assert_eq!("COOKIE".try_into(), Ok(HeaderName::Cookie));
585        assert_eq!("Expect".try_into(), Ok(HeaderName::Expect));
586        assert_eq!("expect".try_into(), Ok(HeaderName::Expect));
587        assert_eq!("EXPECT".try_into(), Ok(HeaderName::Expect));
588        assert_eq!("Host".try_into(), Ok(HeaderName::Host));
589        assert_eq!("host".try_into(), Ok(HeaderName::Host));
590        assert_eq!("HOST".try_into(), Ok(HeaderName::Host));
591        assert_eq!("If-Match".try_into(), Ok(HeaderName::IfMatch));
592        assert_eq!("if-match".try_into(), Ok(HeaderName::IfMatch));
593        assert_eq!("IF-MATCH".try_into(), Ok(HeaderName::IfMatch));
594        assert_eq!(
595            "If-Modified-Since".try_into(),
596            Ok(HeaderName::IfModifiedSince)
597        );
598        assert_eq!(
599            "if-modified-since".try_into(),
600            Ok(HeaderName::IfModifiedSince)
601        );
602        assert_eq!(
603            "IF-MODIFIED-SINCE".try_into(),
604            Ok(HeaderName::IfModifiedSince)
605        );
606        assert_eq!("If-None-Match".try_into(), Ok(HeaderName::IfNoneMatch));
607        assert_eq!("if-none-match".try_into(), Ok(HeaderName::IfNoneMatch));
608        assert_eq!("IF-NONE-MATCH".try_into(), Ok(HeaderName::IfNoneMatch));
609        assert_eq!("If-Range".try_into(), Ok(HeaderName::IfRange));
610        assert_eq!("if-range".try_into(), Ok(HeaderName::IfRange));
611        assert_eq!("IF-RANGE".try_into(), Ok(HeaderName::IfRange));
612        assert_eq!(
613            "If-Unmodified-Since".try_into(),
614            Ok(HeaderName::IfUnmodifiedSince)
615        );
616        assert_eq!(
617            "if-unmodified-since".try_into(),
618            Ok(HeaderName::IfUnmodifiedSince)
619        );
620        assert_eq!(
621            "IF-UNMODIFIED-SINCE".try_into(),
622            Ok(HeaderName::IfUnmodifiedSince)
623        );
624        assert_eq!("Origin".try_into(), Ok(HeaderName::Origin));
625        assert_eq!("origin".try_into(), Ok(HeaderName::Origin));
626        assert_eq!("ORIGIN".try_into(), Ok(HeaderName::Origin));
627        assert_eq!("Range".try_into(), Ok(HeaderName::Range));
628        assert_eq!("range".try_into(), Ok(HeaderName::Range));
629        assert_eq!("RANGE".try_into(), Ok(HeaderName::Range));
630        assert_eq!("Referer".try_into(), Ok(HeaderName::Referer));
631        assert_eq!("referer".try_into(), Ok(HeaderName::Referer));
632        assert_eq!("REFERER".try_into(), Ok(HeaderName::Referer));
633        assert_eq!("Sec-Ch-Ua".try_into(), Ok(HeaderName::SecChUa));
634        assert_eq!("sec-ch-ua".try_into(), Ok(HeaderName::SecChUa));
635        assert_eq!("SEC-CH-UA".try_into(), Ok(HeaderName::SecChUa));
636        assert_eq!("Sec-Ch-Ua-Mobile".try_into(), Ok(HeaderName::SecChUaMobile));
637        assert_eq!("sec-ch-ua-mobile".try_into(), Ok(HeaderName::SecChUaMobile));
638        assert_eq!("SEC-CH-UA-MOBILE".try_into(), Ok(HeaderName::SecChUaMobile));
639        assert_eq!(
640            "Sec-Ch-Ua-Platform".try_into(),
641            Ok(HeaderName::SecChUaPlatform)
642        );
643        assert_eq!(
644            "sec-ch-ua-platform".try_into(),
645            Ok(HeaderName::SecChUaPlatform)
646        );
647        assert_eq!(
648            "SEC-CH-UA-PLATFORM".try_into(),
649            Ok(HeaderName::SecChUaPlatform)
650        );
651        assert_eq!("sec-fetch-dest".try_into(), Ok(HeaderName::SecFetchDest));
652        assert_eq!("Sec-Fetch-Dest".try_into(), Ok(HeaderName::SecFetchDest));
653        assert_eq!("SEC-FETCH-DEST".try_into(), Ok(HeaderName::SecFetchDest));
654        assert_eq!("sec-fetch-mode".try_into(), Ok(HeaderName::SecFetchMode));
655        assert_eq!("Sec-Fetch-Mode".try_into(), Ok(HeaderName::SecFetchMode));
656        assert_eq!("SEC-FETCH-MODE".try_into(), Ok(HeaderName::SecFetchMode));
657        assert_eq!("sec-fetch-site".try_into(), Ok(HeaderName::SecFetchSite));
658        assert_eq!("Sec-Fetch-Site".try_into(), Ok(HeaderName::SecFetchSite));
659        assert_eq!("SEC-FETCH-SITE".try_into(), Ok(HeaderName::SecFetchSite));
660        assert_eq!("sec-fetch-user".try_into(), Ok(HeaderName::SecFetchUser));
661        assert_eq!("Sec-Fetch-User".try_into(), Ok(HeaderName::SecFetchUser));
662        assert_eq!("SEC-FETCH-USER".try_into(), Ok(HeaderName::SecFetchUser));
663        assert_eq!(
664            "Transfer-Encoding".try_into(),
665            Ok(HeaderName::TransferEncoding)
666        );
667        assert_eq!(
668            "transfer-encoding".try_into(),
669            Ok(HeaderName::TransferEncoding)
670        );
671        assert_eq!(
672            "TRANSFER-ENCODING".try_into(),
673            Ok(HeaderName::TransferEncoding)
674        );
675        assert_eq!("User-Agent".try_into(), Ok(HeaderName::UserAgent));
676        assert_eq!("user-agent".try_into(), Ok(HeaderName::UserAgent));
677        assert_eq!("USER-AGENT".try_into(), Ok(HeaderName::UserAgent));
678        assert_eq!("X-CSRF-Token".try_into(), Ok(HeaderName::XCSRFToken));
679        assert_eq!("x-csrf-token".try_into(), Ok(HeaderName::XCSRFToken));
680        assert_eq!("X-CSRF-TOKEN".try_into(), Ok(HeaderName::XCSRFToken));
681        assert_eq!("X-Forwarded-For".try_into(), Ok(HeaderName::XForwardedFor));
682        assert_eq!("x-forwarded-for".try_into(), Ok(HeaderName::XForwardedFor));
683        assert_eq!("X-FORWARDED-FOR".try_into(), Ok(HeaderName::XForwardedFor));
684        assert_eq!(
685            "X-Forwarded-Host".try_into(),
686            Ok(HeaderName::XForwardedHost)
687        );
688        assert_eq!(
689            "x-forwarded-host".try_into(),
690            Ok(HeaderName::XForwardedHost)
691        );
692        assert_eq!(
693            "X-FORWARDED-HOST".try_into(),
694            Ok(HeaderName::XForwardedHost)
695        );
696        assert_eq!("X-Real-Ip".try_into(), Ok(HeaderName::XRealIp));
697        assert_eq!("x-real-ip".try_into(), Ok(HeaderName::XRealIp));
698        assert_eq!("X-REAL-IP".try_into(), Ok(HeaderName::XRealIp));
699        assert_eq!(
700            "X-Hub-Signature-256".try_into(),
701            Ok(HeaderName::XHubSignature256)
702        );
703        assert_eq!(
704            "x-hub-signature-256".try_into(),
705            Ok(HeaderName::XHubSignature256)
706        );
707        assert_eq!(
708            "X-HUB-SIGNATURE-256".try_into(),
709            Ok(HeaderName::XHubSignature256)
710        );
711        let unknown: Result<HeaderName> = "UNKNOWN".try_into();
712        assert!(unknown.is_err());
713    }
714
715    #[test]
716    fn as_ref() {
717        assert_eq!(HeaderName::Accept.as_ref(), ACCEPT);
718        assert_eq!(HeaderName::AcceptEncoding.as_ref(), ACCEPT_ENCODING);
719        assert_eq!(HeaderName::AcceptLanguage.as_ref(), ACCEPT_LANGUAGE);
720        assert_eq!(
721            HeaderName::AccessControlRequestHeaders.as_ref(),
722            ACCESS_CONTROL_REQUEST_HEADERS
723        );
724        assert_eq!(
725            HeaderName::AccessControlRequestMethod.as_ref(),
726            ACCESS_CONTROL_REQUEST_METHOD
727        );
728        assert_eq!(HeaderName::Authorization.as_ref(), AUTHORIZATION);
729        assert_eq!(HeaderName::Connection.as_ref(), CONNECTION);
730        assert_eq!(HeaderName::ContentEncoding.as_ref(), CONTENT_ENCODING);
731        assert_eq!(HeaderName::ContentLength.as_ref(), CONTENT_LENGTH);
732        assert_eq!(HeaderName::ContentType.as_ref(), CONTENT_TYPE);
733        assert_eq!(HeaderName::Cookie.as_ref(), COOKIE);
734        assert_eq!(HeaderName::Expect.as_ref(), EXPECT);
735        assert_eq!(HeaderName::Host.as_ref(), HOST);
736        assert_eq!(HeaderName::IfMatch.as_ref(), IF_MATCH);
737        assert_eq!(HeaderName::IfModifiedSince.as_ref(), IF_MODIFIED_SINCE);
738        assert_eq!(HeaderName::IfNoneMatch.as_ref(), IF_NONE_MATCH);
739        assert_eq!(HeaderName::IfRange.as_ref(), IF_RANGE);
740        assert_eq!(HeaderName::IfUnmodifiedSince.as_ref(), IF_UNMODIFIED_SINCE);
741        assert_eq!(HeaderName::Origin.as_ref(), ORIGIN);
742        assert_eq!(HeaderName::Range.as_ref(), RANGE);
743        assert_eq!(HeaderName::TransferEncoding.as_ref(), TRANSFER_ENCODING);
744        assert_eq!(HeaderName::UserAgent.as_ref(), USER_AGENT);
745        assert_eq!(HeaderName::XCSRFToken.as_ref(), X_CSRF_TOKEN);
746        assert_eq!(HeaderName::XForwardedFor.as_ref(), X_FORWARDED_FOR);
747        assert_eq!(HeaderName::XForwardedHost.as_ref(), X_FORWARDED_HOST);
748        assert_eq!(HeaderName::XRealIp.as_ref(), X_REAL_IP);
749        assert_eq!(HeaderName::XHubSignature256.as_ref(), X_HUB_SIGNATURE_256);
750        assert_eq!(
751            HeaderName::try_from_static(b"unknown").unwrap().as_ref(),
752            b"unknown"
753        );
754        assert_eq!(
755            &HeaderName::try_from_static(b"unknown").unwrap().as_ref(),
756            b"unknown"
757        );
758    }
759}