hyper_sync/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;
79
80            #[bench]
81            fn bench_parse(b: &mut Bencher) {
82                let val = $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 = $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            #[allow(unused, deprecated)]
147            use std::ascii::AsciiExt;
148            let raw = $raw;
149            let a: Vec<Vec<u8>> = raw.iter().map(|x| x.to_vec()).collect();
150            let a = a.into();
151            let value = HeaderField::parse_header(&a);
152            let result = format!("{}", value.unwrap());
153            let expected = String::from_utf8(raw[0].to_vec()).unwrap();
154            let result_cmp: Vec<String> = result
155                .to_ascii_lowercase()
156                .split(' ')
157                .map(|x| x.to_owned())
158                .collect();
159            let expected_cmp: Vec<String> = expected
160                .to_ascii_lowercase()
161                .split(' ')
162                .map(|x| x.to_owned())
163                .collect();
164            assert_eq!(result_cmp.concat(), expected_cmp.concat());
165        }
166    };
167    ($id:ident, $raw:expr, $typed:expr) => {
168        #[test]
169        fn $id() {
170            let a: Vec<Vec<u8>> = $raw.iter().map(|x| x.to_vec()).collect();
171            let a = a.into();
172            let val = HeaderField::parse_header(&a);
173            let typed: Option<HeaderField> = $typed;
174            // Test parsing
175            assert_eq!(val.ok(), typed);
176            // Test formatting
177            if typed.is_some() {
178                let raw = &($raw)[..];
179                let mut iter = raw.iter().map(|b|str::from_utf8(&b[..]).unwrap());
180                let mut joined = String::new();
181                joined.push_str(iter.next().unwrap());
182                for s in iter {
183                    joined.push_str(", ");
184                    joined.push_str(s);
185                }
186                assert_eq!(format!("{}", typed.unwrap()), joined);
187            }
188        }
189    }
190}
191
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(raw: &$crate::header::Raw) -> $crate::Result<Self> {
212                $crate::header::parsing::from_comma_delimited(raw).map($id)
213            }
214            #[inline]
215            fn fmt_header(&self, f: &mut $crate::header::Formatter) -> ::std::fmt::Result {
216                f.fmt_line(self)
217            }
218        }
219        impl ::std::fmt::Display for $id {
220            #[inline]
221            fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
222                $crate::header::parsing::fmt_comma_delimited(f, &self.0[..])
223            }
224        }
225    };
226    // List header, one or more items
227    ($(#[$a:meta])*($id:ident, $n:expr) => ($item:ty)+) => {
228        $(#[$a])*
229        #[derive(Clone, Debug, PartialEq)]
230        pub struct $id(pub Vec<$item>);
231        __hyper__deref!($id => Vec<$item>);
232        impl $crate::header::Header for $id {
233            #[inline]
234            fn header_name() -> &'static str {
235                static NAME: &'static str = $n;
236                NAME
237            }
238            #[inline]
239            fn parse_header(raw: &$crate::header::Raw) -> $crate::Result<Self> {
240                $crate::header::parsing::from_comma_delimited(raw).map($id)
241            }
242            #[inline]
243            fn fmt_header(&self, f: &mut $crate::header::Formatter) -> ::std::fmt::Result {
244                f.fmt_line(self)
245            }
246        }
247        impl ::std::fmt::Display for $id {
248            #[inline]
249            fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
250                $crate::header::parsing::fmt_comma_delimited(f, &self.0[..])
251            }
252        }
253    };
254    // Single value header
255    ($(#[$a:meta])*($id:ident, $n:expr) => [$value:ty]) => {
256        $(#[$a])*
257        #[derive(Clone, Debug, PartialEq)]
258        pub struct $id(pub $value);
259        __hyper__deref!($id => $value);
260        impl $crate::header::Header for $id {
261            #[inline]
262            fn header_name() -> &'static str {
263                static NAME: &'static str = $n;
264                NAME
265            }
266            #[inline]
267            fn parse_header(raw: &$crate::header::Raw) -> $crate::Result<Self> {
268                $crate::header::parsing::from_one_raw_str(raw).map($id)
269            }
270            #[inline]
271            fn fmt_header(&self, f: &mut $crate::header::Formatter) -> ::std::fmt::Result {
272                f.fmt_line(self)
273            }
274        }
275        impl ::std::fmt::Display for $id {
276            #[inline]
277            fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
278                ::std::fmt::Display::fmt(&self.0, f)
279            }
280        }
281    };
282    // Single value header (internal)
283    ($(#[$a:meta])*($id:ident, $n:expr) => danger [$value:ty]) => {
284        $(#[$a])*
285        #[derive(Clone, Debug, PartialEq)]
286        pub struct $id(pub $value);
287        __hyper__deref!($id => $value);
288        impl $crate::header::Header for $id {
289            #[inline]
290            fn header_name() -> &'static str {
291                static NAME: &'static str = $n;
292                NAME
293            }
294            #[inline]
295            fn parse_header(raw: &$crate::header::Raw) -> $crate::Result<Self> {
296                $crate::header::parsing::from_one_raw_str(raw).map($id)
297            }
298            #[inline]
299            fn fmt_header(&self, f: &mut $crate::header::Formatter) -> ::std::fmt::Result {
300                f.danger_fmt_line_without_newline_replacer(self)
301            }
302        }
303        impl ::std::fmt::Display for $id {
304            #[inline]
305            fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
306                ::std::fmt::Display::fmt(&self.0, f)
307            }
308        }
309    };
310    // Single value cow header
311    ($(#[$a:meta])*($id:ident, $n:expr) => Cow[$value:ty]) => {
312        $(#[$a])*
313        #[derive(Clone, Debug, PartialEq)]
314        pub struct $id(::std::borrow::Cow<'static,$value>);
315        impl $id {
316            /// Creates a new $id
317            pub fn new<I: Into<::std::borrow::Cow<'static,$value>>>(value: I) -> Self {
318                $id(value.into())
319            }
320        }
321        impl ::std::ops::Deref for $id {
322            type Target = $value;
323            #[inline]
324            fn deref(&self) -> &Self::Target {
325                &(self.0)
326            }
327        }
328        impl $crate::header::Header for $id {
329            #[inline]
330            fn header_name() -> &'static str {
331                static NAME: &'static str = $n;
332                NAME
333            }
334            #[inline]
335            fn parse_header(raw: &$crate::header::Raw) -> $crate::Result<Self> {
336                $crate::header::parsing::from_one_raw_str::<<$value as ::std::borrow::ToOwned>::Owned>(raw).map($id::new)
337            }
338            #[inline]
339            fn fmt_header(&self, f: &mut $crate::header::Formatter) -> ::std::fmt::Result {
340                f.fmt_line(self)
341            }
342        }
343        impl ::std::fmt::Display for $id {
344            #[inline]
345            fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
346                ::std::fmt::Display::fmt(&self.0, f)
347            }
348        }
349    };
350    // List header, one or more items with "*" option
351    ($(#[$a:meta])*($id:ident, $n:expr) => {Any / ($item:ty)+}) => {
352        $(#[$a])*
353        #[derive(Clone, Debug, PartialEq)]
354        pub enum $id {
355            /// Any value is a match
356            Any,
357            /// Only the listed items are a match
358            Items(Vec<$item>),
359        }
360        impl $crate::header::Header for $id {
361            #[inline]
362            fn header_name() -> &'static str {
363                static NAME: &'static str = $n;
364                NAME
365            }
366            #[inline]
367            fn parse_header(raw: &$crate::header::Raw) -> $crate::Result<Self> {
368                // FIXME: Return None if no item is in $id::Only
369                if raw.len() == 1 {
370                    if &raw[0] == b"*" {
371                        return Ok($id::Any)
372                    }
373                }
374                $crate::header::parsing::from_comma_delimited(raw).map($id::Items)
375            }
376            #[inline]
377            fn fmt_header(&self, f: &mut $crate::header::Formatter) -> ::std::fmt::Result {
378                f.fmt_line(self)
379            }
380        }
381        impl ::std::fmt::Display for $id {
382            #[inline]
383            fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
384                match *self {
385                    $id::Any => f.write_str("*"),
386                    $id::Items(ref fields) => $crate::header::parsing::fmt_comma_delimited(
387                        f, &fields[..])
388                }
389            }
390        }
391    };
392
393    // optional test module
394    ($(#[$a:meta])*($id:ident, $n:expr) => ($item:ty)* $tm:ident{$($tf:item)*}) => {
395        header! {
396            $(#[$a])*
397            ($id, $n) => ($item)*
398        }
399
400        __hyper__tm! { $id, $tm { $($tf)* }}
401    };
402    ($(#[$a:meta])*($id:ident, $n:expr) => ($item:ty)+ $tm:ident{$($tf:item)*}) => {
403        header! {
404            $(#[$a])*
405            ($id, $n) => ($item)+
406        }
407
408        __hyper__tm! { $id, $tm { $($tf)* }}
409    };
410    ($(#[$a:meta])*($id:ident, $n:expr) => [$item:ty] $tm:ident{$($tf:item)*}) => {
411        header! {
412            $(#[$a])*
413            ($id, $n) => [$item]
414        }
415
416        __hyper__tm! { $id, $tm { $($tf)* }}
417    };
418    ($(#[$a:meta])*($id:ident, $n:expr) => danger [$item:ty] $tm:ident{$($tf:item)*}) => {
419        header! {
420            $(#[$a])*
421            ($id, $n) => danger [$item]
422        }
423
424        __hyper__tm! { $id, $tm { $($tf)* }}
425    };
426    ($(#[$a:meta])*($id:ident, $n:expr) => Cow[$item:ty] $tm:ident{$($tf:item)*}) => {
427        header! {
428            $(#[$a])*
429            ($id, $n) => Cow[$item]
430        }
431
432        __hyper__tm! { $id, $tm { $($tf)* }}
433    };
434    ($(#[$a:meta])*($id:ident, $n:expr) => {Any / ($item:ty)+} $tm:ident{$($tf:item)*}) => {
435        header! {
436            $(#[$a])*
437            ($id, $n) => {Any / ($item)+}
438        }
439
440        __hyper__tm! { $id, $tm { $($tf)* }}
441    };
442}
443
444
445mod accept_charset;
446mod accept_encoding;
447mod accept_language;
448mod accept_ranges;
449mod accept;
450mod access_control_allow_credentials;
451mod access_control_allow_headers;
452mod access_control_allow_methods;
453mod access_control_allow_origin;
454mod access_control_expose_headers;
455mod access_control_max_age;
456mod access_control_request_headers;
457mod access_control_request_method;
458mod allow;
459mod authorization;
460mod cache_control;
461mod connection;
462mod content_disposition;
463mod content_encoding;
464mod content_language;
465mod content_length;
466mod content_location;
467mod content_range;
468mod content_type;
469mod cookie;
470mod date;
471mod etag;
472mod expect;
473mod expires;
474mod from;
475mod host;
476mod if_match;
477mod if_modified_since;
478mod if_none_match;
479mod if_range;
480mod if_unmodified_since;
481mod last_event_id;
482mod last_modified;
483mod link;
484mod location;
485mod origin;
486mod pragma;
487mod prefer;
488mod preference_applied;
489mod proxy_authorization;
490mod range;
491mod referer;
492mod referrer_policy;
493mod retry_after;
494mod server;
495mod set_cookie;
496mod strict_transport_security;
497mod te;
498mod transfer_encoding;
499mod upgrade;
500mod user_agent;
501mod vary;
502mod warning;