hyperx/header/common/
mod.rs

1//! A Collection of Header implementations for common HTTP Headers.
2//!
3//! ## Mime
4//!
5//! Several header fields use MIME values for their contents. Keeping with the
6//! strongly-typed theme, the [mime](https://docs.rs/mime) crate
7//! is used, such as `ContentType(pub Mime)`.
8
9pub use self::accept_charset::AcceptCharset;
10pub use self::accept_encoding::AcceptEncoding;
11pub use self::accept_language::AcceptLanguage;
12pub use self::accept_ranges::{AcceptRanges, RangeUnit};
13pub use self::accept::Accept;
14pub use self::access_control_allow_credentials::AccessControlAllowCredentials;
15pub use self::access_control_allow_headers::AccessControlAllowHeaders;
16pub use self::access_control_allow_methods::AccessControlAllowMethods;
17pub use self::access_control_allow_origin::AccessControlAllowOrigin;
18pub use self::access_control_expose_headers::AccessControlExposeHeaders;
19pub use self::access_control_max_age::AccessControlMaxAge;
20pub use self::access_control_request_headers::AccessControlRequestHeaders;
21pub use self::access_control_request_method::AccessControlRequestMethod;
22pub use self::allow::Allow;
23pub use self::authorization::{Authorization, Scheme, Basic, Bearer};
24pub use self::cache_control::{CacheControl, CacheDirective};
25pub use self::connection::{Connection, ConnectionOption};
26pub use self::content_disposition::{ContentDisposition, DispositionType, DispositionParam};
27pub use self::content_encoding::ContentEncoding;
28pub use self::content_language::ContentLanguage;
29pub use self::content_length::ContentLength;
30pub use self::content_location::ContentLocation;
31pub use self::content_range::{ContentRange, ContentRangeSpec};
32pub use self::content_type::ContentType;
33pub use self::cookie::{Cookie, CookieIter};
34pub use self::date::Date;
35pub use self::etag::ETag;
36pub use self::expect::Expect;
37pub use self::expires::Expires;
38pub use self::from::From;
39pub use self::host::Host;
40pub use self::if_match::IfMatch;
41pub use self::if_modified_since::IfModifiedSince;
42pub use self::if_none_match::IfNoneMatch;
43pub use self::if_range::IfRange;
44pub use self::if_unmodified_since::IfUnmodifiedSince;
45pub use self::last_event_id::LastEventId;
46pub use self::last_modified::LastModified;
47pub use self::link::{Link, LinkValue, RelationType, MediaDesc};
48pub use self::location::Location;
49pub use self::origin::Origin;
50pub use self::pragma::Pragma;
51pub use self::prefer::{Prefer, Preference};
52pub use self::preference_applied::PreferenceApplied;
53pub use self::proxy_authorization::ProxyAuthorization;
54pub use self::range::{Range, ByteRangeSpec};
55pub use self::referer::Referer;
56pub use self::referrer_policy::ReferrerPolicy;
57pub use self::retry_after::RetryAfter;
58pub use self::server::Server;
59pub use self::set_cookie::SetCookie;
60pub use self::strict_transport_security::StrictTransportSecurity;
61pub use self::te::Te;
62pub use self::transfer_encoding::TransferEncoding;
63pub use self::upgrade::{Upgrade, Protocol, ProtocolName};
64pub use self::user_agent::UserAgent;
65pub use self::vary::Vary;
66pub use self::warning::Warning;
67
68#[doc(hidden)]
69#[macro_export]
70macro_rules! bench_header(
71    ($name:ident, $ty:ty, $value:expr) => {
72        #[cfg(test)]
73        #[cfg(feature = "nightly")]
74        mod $name {
75            use test::Bencher;
76            use super::*;
77
78            use header::{Header, Raw};
79
80            #[bench]
81            fn bench_parse(b: &mut Bencher) {
82                let val: Raw = $value.into();
83                b.iter(|| {
84                    let _: $ty = Header::parse_header(&val).unwrap();
85                });
86            }
87
88            #[bench]
89            fn bench_format(b: &mut Bencher) {
90                let raw: Raw = $value.into();
91                let val: $ty = Header::parse_header(&raw).unwrap();
92                b.iter(|| {
93                    format!("{}", val);
94                });
95            }
96        }
97    }
98);
99
100#[doc(hidden)]
101#[macro_export]
102macro_rules! __hyper__deref {
103    ($from:ty => $to:ty) => {
104        impl ::std::ops::Deref for $from {
105            type Target = $to;
106
107            #[inline]
108            fn deref(&self) -> &$to {
109                &self.0
110            }
111        }
112
113        impl ::std::ops::DerefMut for $from {
114            #[inline]
115            fn deref_mut(&mut self) -> &mut $to {
116                &mut self.0
117            }
118        }
119    }
120}
121
122#[doc(hidden)]
123#[macro_export]
124macro_rules! __hyper__tm {
125    ($id:ident, $tm:ident{$($tf:item)*}) => {
126        #[allow(unused_imports)]
127        #[cfg(test)]
128        mod $tm{
129            use std::str;
130            use $crate::header::*;
131            use $crate::mime::*;
132            use $crate::method::Method;
133            use super::$id as HeaderField;
134            $($tf)*
135        }
136
137    }
138}
139
140#[doc(hidden)]
141#[macro_export]
142macro_rules! test_header {
143    ($id:ident, $raw:expr) => {
144        #[test]
145        fn $id() {
146            let raw = $raw;
147            let a: Vec<Vec<u8>> = raw.iter().map(|x| x.to_vec()).collect();
148            let a: Raw = a.into();
149            let value = HeaderField::parse_header(&a);
150            let result = format!("{}", value.unwrap());
151            let expected = String::from_utf8(raw[0].to_vec()).unwrap();
152            let result_cmp: Vec<String> = result
153                .to_ascii_lowercase()
154                .split(' ')
155                .map(|x| x.to_owned())
156                .collect();
157            let expected_cmp: Vec<String> = expected
158                .to_ascii_lowercase()
159                .split(' ')
160                .map(|x| x.to_owned())
161                .collect();
162            assert_eq!(result_cmp.concat(), expected_cmp.concat());
163        }
164    };
165    ($id:ident, $raw:expr, $typed:expr) => {
166        #[test]
167        fn $id() {
168
169            let a: Vec<Vec<u8>> = $raw.iter().map(|x| x.to_vec()).collect();
170            let a: Raw = a.into();
171            let val = HeaderField::parse_header(&a);
172            let typed: Option<HeaderField> = $typed;
173            // Test parsing
174            assert_eq!(val.ok(), typed);
175            // Test formatting
176            if typed.is_some() {
177                let raw = &($raw)[..];
178                let mut iter = raw.iter().map(|b|str::from_utf8(&b[..]).unwrap());
179                let mut joined = String::new();
180                joined.push_str(iter.next().unwrap());
181                for s in iter {
182                    joined.push_str(", ");
183                    joined.push_str(s);
184                }
185                assert_eq!(format!("{}", typed.unwrap()), joined);
186            }
187        }
188    }
189}
190
191/// Create a custom header type.
192#[macro_export]
193macro_rules! header {
194    // $a:meta: Attributes associated with the header item (usually docs)
195    // $id:ident: Identifier of the header
196    // $n:expr: Lowercase name of the header
197    // $nn:expr: Nice name of the header
198
199    // List header, zero or more items
200    ($(#[$a:meta])*($id:ident, $n:expr) => ($item:ty)*) => {
201        $(#[$a])*
202        #[derive(Clone, Debug, PartialEq)]
203        pub struct $id(pub Vec<$item>);
204        __hyper__deref!($id => Vec<$item>);
205        impl $crate::header::Header for $id {
206            fn header_name() -> &'static str {
207                static NAME: &'static str = $n;
208                NAME
209            }
210            #[inline]
211            fn parse_header<'a, T>(raw: &'a T) -> $crate::Result<Self>
212            where T: $crate::header::RawLike<'a>
213            {
214                $crate::header::parsing::from_comma_delimited(raw).map($id)
215            }
216            #[inline]
217            fn fmt_header(&self, f: &mut $crate::header::Formatter) -> ::std::fmt::Result {
218                f.fmt_line(self)
219            }
220        }
221        impl ::std::fmt::Display for $id {
222            #[inline]
223            fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
224                $crate::header::parsing::fmt_comma_delimited(f, &self.0[..])
225            }
226        }
227    };
228    // List header, one or more items
229    ($(#[$a:meta])*($id:ident, $n:expr) => ($item:ty)+) => {
230        $(#[$a])*
231        #[derive(Clone, Debug, PartialEq)]
232        pub struct $id(pub Vec<$item>);
233        __hyper__deref!($id => Vec<$item>);
234        impl $crate::header::Header for $id {
235            #[inline]
236            fn header_name() -> &'static str {
237                static NAME: &'static str = $n;
238                NAME
239            }
240            #[inline]
241            fn parse_header<'a, T>(raw: &'a T) -> $crate::Result<Self>
242            where T: $crate::header::RawLike<'a>
243            {
244                $crate::header::parsing::from_comma_delimited(raw).map($id)
245            }
246            #[inline]
247            fn fmt_header(&self, f: &mut $crate::header::Formatter) -> ::std::fmt::Result {
248                f.fmt_line(self)
249            }
250        }
251        impl ::std::fmt::Display for $id {
252            #[inline]
253            fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
254                $crate::header::parsing::fmt_comma_delimited(f, &self.0[..])
255            }
256        }
257    };
258    // Single value header
259    ($(#[$a:meta])*($id:ident, $n:expr) => [$value:ty]) => {
260        $(#[$a])*
261        #[derive(Clone, Debug, PartialEq)]
262        pub struct $id(pub $value);
263        __hyper__deref!($id => $value);
264        impl $crate::header::Header for $id {
265            #[inline]
266            fn header_name() -> &'static str {
267                static NAME: &'static str = $n;
268                NAME
269            }
270            #[inline]
271            fn parse_header<'a, T>(raw: &'a T) -> $crate::Result<Self>
272            where T: $crate::header::RawLike<'a>
273            {
274                $crate::header::parsing::from_one_raw_str(raw).map($id)
275            }
276            #[inline]
277            fn fmt_header(&self, f: &mut $crate::header::Formatter) -> ::std::fmt::Result {
278                f.fmt_line(self)
279            }
280        }
281        impl ::std::fmt::Display for $id {
282            #[inline]
283            fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
284                ::std::fmt::Display::fmt(&self.0, f)
285            }
286        }
287    };
288    // Single value header (internal)
289    ($(#[$a:meta])*($id:ident, $n:expr) => danger [$value:ty]) => {
290        $(#[$a])*
291        #[derive(Clone, Debug, PartialEq)]
292        pub struct $id(pub $value);
293        __hyper__deref!($id => $value);
294        impl $crate::header::Header for $id {
295            #[inline]
296            fn header_name() -> &'static str {
297                static NAME: &'static str = $n;
298                NAME
299            }
300            #[inline]
301            fn parse_header<'a, T>(raw: &'a T) -> $crate::Result<Self>
302            where T: $crate::header::RawLike<'a>
303            {
304                $crate::header::parsing::from_one_raw_str(raw).map($id)
305            }
306            #[inline]
307            fn fmt_header(&self, f: &mut $crate::header::Formatter) -> ::std::fmt::Result {
308                f.danger_fmt_line_without_newline_replacer(self)
309            }
310        }
311        impl ::std::fmt::Display for $id {
312            #[inline]
313            fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
314                ::std::fmt::Display::fmt(&self.0, f)
315            }
316        }
317    };
318    // Single value cow header
319    ($(#[$a:meta])*($id:ident, $n:expr) => Cow[$value:ty]) => {
320        $(#[$a])*
321        #[derive(Clone, Debug, PartialEq)]
322        pub struct $id(::std::borrow::Cow<'static,$value>);
323        impl $id {
324            /// Creates a new $id
325            pub fn new<I: Into<::std::borrow::Cow<'static,$value>>>(value: I) -> Self {
326                $id(value.into())
327            }
328        }
329        impl ::std::ops::Deref for $id {
330            type Target = $value;
331            #[inline]
332            fn deref(&self) -> &Self::Target {
333                &(self.0)
334            }
335        }
336        impl $crate::header::Header for $id {
337            #[inline]
338            fn header_name() -> &'static str {
339                static NAME: &'static str = $n;
340                NAME
341            }
342            #[inline]
343            fn parse_header<'a, T>(raw: &'a T) -> $crate::Result<Self>
344            where T: $crate::header::RawLike<'a>
345            {
346                $crate::header::parsing::from_one_raw_str::<_, <$value as ::std::borrow::ToOwned>::Owned>(raw).map($id::new)
347            }
348            #[inline]
349            fn fmt_header(&self, f: &mut $crate::header::Formatter) -> ::std::fmt::Result {
350                f.fmt_line(self)
351            }
352        }
353        impl ::std::fmt::Display for $id {
354            #[inline]
355            fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
356                ::std::fmt::Display::fmt(&self.0, f)
357            }
358        }
359    };
360    // List header, one or more items with "*" option
361    ($(#[$a:meta])*($id:ident, $n:expr) => {Any / ($item:ty)+}) => {
362        $(#[$a])*
363        #[derive(Clone, Debug, PartialEq)]
364        pub enum $id {
365            /// Any value is a match
366            Any,
367            /// Only the listed items are a match
368            Items(Vec<$item>),
369        }
370        impl $crate::header::Header for $id {
371            #[inline]
372            fn header_name() -> &'static str {
373                static NAME: &'static str = $n;
374                NAME
375            }
376            #[inline]
377            fn parse_header<'a, T>(raw: &'a T) -> $crate::Result<Self>
378            where T: $crate::header::RawLike<'a>
379            {
380                // FIXME: Return None if no item is in $id::Only
381                if let Some(l) = raw.one() {
382                    if l == b"*" {
383                        return Ok($id::Any)
384                    }
385                }
386                $crate::header::parsing::from_comma_delimited(raw).map($id::Items)
387            }
388            #[inline]
389            fn fmt_header(&self, f: &mut $crate::header::Formatter) -> ::std::fmt::Result {
390                f.fmt_line(self)
391            }
392        }
393        impl ::std::fmt::Display for $id {
394            #[inline]
395            fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
396                match *self {
397                    $id::Any => f.write_str("*"),
398                    $id::Items(ref fields) => $crate::header::parsing::fmt_comma_delimited(
399                        f, &fields[..])
400                }
401            }
402        }
403    };
404
405    // optional test module
406    ($(#[$a:meta])*($id:ident, $n:expr) => ($item:ty)* $tm:ident{$($tf:item)*}) => {
407        header! {
408            $(#[$a])*
409            ($id, $n) => ($item)*
410        }
411
412        __hyper__tm! { $id, $tm { $($tf)* }}
413    };
414    ($(#[$a:meta])*($id:ident, $n:expr) => ($item:ty)+ $tm:ident{$($tf:item)*}) => {
415        header! {
416            $(#[$a])*
417            ($id, $n) => ($item)+
418        }
419
420        __hyper__tm! { $id, $tm { $($tf)* }}
421    };
422    ($(#[$a:meta])*($id:ident, $n:expr) => [$item:ty] $tm:ident{$($tf:item)*}) => {
423        header! {
424            $(#[$a])*
425            ($id, $n) => [$item]
426        }
427
428        __hyper__tm! { $id, $tm { $($tf)* }}
429    };
430    ($(#[$a:meta])*($id:ident, $n:expr) => danger [$item:ty] $tm:ident{$($tf:item)*}) => {
431        header! {
432            $(#[$a])*
433            ($id, $n) => danger [$item]
434        }
435
436        __hyper__tm! { $id, $tm { $($tf)* }}
437    };
438    ($(#[$a:meta])*($id:ident, $n:expr) => Cow[$item:ty] $tm:ident{$($tf:item)*}) => {
439        header! {
440            $(#[$a])*
441            ($id, $n) => Cow[$item]
442        }
443
444        __hyper__tm! { $id, $tm { $($tf)* }}
445    };
446    ($(#[$a:meta])*($id:ident, $n:expr) => {Any / ($item:ty)+} $tm:ident{$($tf:item)*}) => {
447        header! {
448            $(#[$a])*
449            ($id, $n) => {Any / ($item)+}
450        }
451
452        __hyper__tm! { $id, $tm { $($tf)* }}
453    };
454}
455
456#[doc(hidden)]
457#[macro_export]
458macro_rules! standard_header {
459    ($local:ident, $hname:ident) => {
460        impl $crate::header::StandardHeader for $local {
461            #[inline]
462            fn http_header_name() -> ::http::header::HeaderName {
463                ::http::header::$hname
464            }
465        }
466    }
467}
468
469mod accept_charset;
470mod accept_encoding;
471mod accept_language;
472mod accept_ranges;
473mod accept;
474mod access_control_allow_credentials;
475mod access_control_allow_headers;
476mod access_control_allow_methods;
477mod access_control_allow_origin;
478mod access_control_expose_headers;
479mod access_control_max_age;
480mod access_control_request_headers;
481mod access_control_request_method;
482mod allow;
483mod authorization;
484mod cache_control;
485mod connection;
486mod content_disposition;
487mod content_encoding;
488mod content_language;
489mod content_length;
490mod content_location;
491mod content_range;
492mod content_type;
493mod cookie;
494mod date;
495mod etag;
496mod expect;
497mod expires;
498mod from;
499mod host;
500mod if_match;
501mod if_modified_since;
502mod if_none_match;
503mod if_range;
504mod if_unmodified_since;
505mod last_event_id;
506mod last_modified;
507mod link;
508mod location;
509mod origin;
510mod pragma;
511mod prefer;
512mod preference_applied;
513mod proxy_authorization;
514mod range;
515mod referer;
516mod referrer_policy;
517mod retry_after;
518mod server;
519mod set_cookie;
520mod strict_transport_security;
521mod te;
522mod transfer_encoding;
523mod upgrade;
524mod user_agent;
525mod vary;
526mod warning;