hyper_old_types/header/
mod.rs

1//! Headers container, and common header fields.
2//!
3//! hyper has the opinion that Headers should be strongly-typed, because that's
4//! why we're using Rust in the first place. To set or get any header, an object
5//! must implement the `Header` trait from this module. Several common headers
6//! are already provided, such as `Host`, `ContentType`, `UserAgent`, and others.
7//!
8//! # Why Typed?
9//!
10//! Or, why not stringly-typed? Types give the following advantages:
11//!
12//! - More difficult to typo, since typos in types should be caught by the compiler
13//! - Parsing to a proper type by default
14//!
15//! # Defining Custom Headers
16//!
17//! Hyper provides many of the most commonly used headers in HTTP. If
18//! you need to define a custom header, it's easy to do while still taking
19//! advantage of the type system. Hyper includes a `header!` macro for defining
20//! many wrapper-style headers.
21//!
22//! ```
23//! #[macro_use] extern crate hyper;
24//! use hyper::header::Headers;
25//! header! { (XRequestGuid, "X-Request-Guid") => [String] }
26//!
27//! fn main () {
28//!     let mut headers = Headers::new();
29//!
30//!     headers.set(XRequestGuid("a proper guid".to_owned()))
31//! }
32//! ```
33//!
34//! This works well for simple "string" headers.  If you need more control,
35//! you can implement the trait directly.
36//!
37//! ## Implementing the `Header` trait
38//!
39//! Consider a Do Not Track header. It can be true or false, but it represents
40//! that via the numerals `1` and `0`.
41//!
42//! ```
43//! use std::fmt;
44//! use hyper::header::{self, Header, Raw};
45//!
46//! #[derive(Debug, Clone, Copy)]
47//! struct Dnt(bool);
48//!
49//! impl Header for Dnt {
50//!     fn header_name() -> &'static str {
51//!         "DNT"
52//!     }
53//!
54//!     fn parse_header(raw: &Raw) -> hyper::Result<Dnt> {
55//!         if raw.len() == 1 {
56//!             let line = &raw[0];
57//!             if line.len() == 1 {
58//!                 let byte = line[0];
59//!                 match byte {
60//!                     b'0' => return Ok(Dnt(true)),
61//!                     b'1' => return Ok(Dnt(false)),
62//!                     _ => ()
63//!                 }
64//!             }
65//!         }
66//!         Err(hyper::Error::Header)
67//!     }
68//!
69//!     fn fmt_header(&self, f: &mut header::Formatter) -> fmt::Result {
70//!         let value = if self.0 {
71//!             "1"
72//!         } else {
73//!             "0"
74//!         };
75//!         f.fmt_line(&value)
76//!     }
77//! }
78//! ```
79use std::borrow::{Cow, ToOwned};
80#[cfg(feature = "compat")]
81use std::convert::From;
82use std::iter::{FromIterator, IntoIterator};
83use std::{mem, fmt};
84
85#[cfg(feature = "compat")]
86use http;
87
88use unicase::Ascii;
89
90use self::internals::{Item, VecMap, Entry};
91use self::sealed::HeaderClone;
92
93pub use self::shared::*;
94pub use self::common::*;
95pub use self::raw::Raw;
96use bytes::Bytes;
97
98mod common;
99mod internals;
100mod raw;
101mod shared;
102pub mod parsing;
103
104
105/// A trait for any object that will represent a header field and value.
106///
107/// This trait represents the construction and identification of headers,
108/// and contains trait-object unsafe methods.
109pub trait Header: 'static + HeaderClone + Send + Sync {
110    /// Returns the name of the header field this belongs to.
111    ///
112    /// This will become an associated constant once available.
113    fn header_name() -> &'static str where Self: Sized;
114    /// Parse a header from a raw stream of bytes.
115    ///
116    /// It's possible that a request can include a header field more than once,
117    /// and in that case, the slice will have a length greater than 1. However,
118    /// it's not necessarily the case that a Header is *allowed* to have more
119    /// than one field value. If that's the case, you **should** return `None`
120    /// if `raw.len() > 1`.
121    fn parse_header(raw: &Raw) -> ::Result<Self> where Self: Sized;
122    /// Format a header to outgoing stream.
123    ///
124    /// Most headers should be formatted on one line, and so a common pattern
125    /// would be to implement `std::fmt::Display` for this type as well, and
126    /// then just call `f.fmt_line(self)`.
127    ///
128    /// ## Note
129    ///
130    /// This has the ability to format a header over multiple lines.
131    ///
132    /// The main example here is `Set-Cookie`, which requires that every
133    /// cookie being set be specified in a separate line. Almost every other
134    /// case should only format as 1 single line.
135    #[inline]
136    fn fmt_header(&self, f: &mut Formatter) -> fmt::Result;
137}
138
139mod sealed {
140    use super::Header;
141
142    #[doc(hidden)]
143    pub trait HeaderClone {
144        fn clone_box(&self) -> Box<Header + Send + Sync>;
145    }
146
147    impl<T: Header + Clone> HeaderClone for T {
148        #[inline]
149        fn clone_box(&self) -> Box<Header + Send + Sync> {
150            Box::new(self.clone())
151        }
152    }
153}
154
155
156/// A formatter used to serialize headers to an output stream.
157#[allow(missing_debug_implementations)]
158pub struct Formatter<'a, 'b: 'a>(Multi<'a, 'b>);
159
160enum Multi<'a, 'b: 'a> {
161    Line(&'a str, &'a mut fmt::Formatter<'b>),
162    Join(bool, &'a mut fmt::Formatter<'b>),
163    Raw(&'a mut Raw),
164}
165
166impl<'a, 'b> Formatter<'a, 'b> {
167
168    /// Format one 'line' of a header.
169    ///
170    /// This writes the header name plus the `Display` value as a single line.
171    ///
172    /// ## Note
173    ///
174    /// This has the ability to format a header over multiple lines.
175    ///
176    /// The main example here is `Set-Cookie`, which requires that every
177    /// cookie being set be specified in a separate line. Almost every other
178    /// case should only format as 1 single line.
179    pub fn fmt_line(&mut self, line: &fmt::Display) -> fmt::Result {
180        use std::fmt::Write;
181        match self.0 {
182            Multi::Line(name, ref mut f) => {
183                try!(f.write_str(name));
184                try!(f.write_str(": "));
185                try!(write!(NewlineReplacer(*f), "{}", line));
186                f.write_str("\r\n")
187            },
188            Multi::Join(ref mut first, ref mut f) => {
189                if !*first {
190                    try!(f.write_str(", "));
191                } else {
192                    *first = false;
193                }
194                write!(NewlineReplacer(*f), "{}", line)
195            }
196            Multi::Raw(ref mut raw) => {
197                let mut s = String::new();
198                try!(write!(NewlineReplacer(&mut s), "{}", line));
199                raw.push(s);
200                Ok(())
201            }
202        }
203    }
204
205    fn danger_fmt_line_without_newline_replacer<T: fmt::Display>(&mut self, line: &T) -> fmt::Result {
206        use std::fmt::Write;
207        match self.0 {
208            Multi::Line(name, ref mut f) => {
209                try!(f.write_str(name));
210                try!(f.write_str(": "));
211                try!(fmt::Display::fmt(line, f));
212                f.write_str("\r\n")
213            },
214            Multi::Join(ref mut first, ref mut f) => {
215                if !*first {
216                    try!(f.write_str(", "));
217                } else {
218                    *first = false;
219                }
220                fmt::Display::fmt(line, f)
221            }
222            Multi::Raw(ref mut raw) => {
223                let mut s = String::new();
224                try!(write!(s, "{}", line));
225                raw.push(s);
226                Ok(())
227            }
228        }
229    }
230}
231
232struct ValueString<'a>(&'a Item);
233
234impl<'a> fmt::Debug for ValueString<'a> {
235    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
236        try!(f.write_str("\""));
237        try!(self.0.write_h1(&mut Formatter(Multi::Join(true, f))));
238        f.write_str("\"")
239    }
240}
241
242impl<'a> fmt::Display for ValueString<'a> {
243    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
244        self.0.write_h1(&mut Formatter(Multi::Join(true, f)))
245    }
246}
247
248struct NewlineReplacer<'a, F: fmt::Write + 'a>(&'a mut F);
249
250impl<'a, F: fmt::Write + 'a> fmt::Write for NewlineReplacer<'a, F> {
251    #[inline]
252    fn write_str(&mut self, s: &str) -> fmt::Result {
253        let mut since = 0;
254        for (i, &byte) in s.as_bytes().iter().enumerate() {
255            if byte == b'\r' || byte == b'\n' {
256                try!(self.0.write_str(&s[since..i]));
257                try!(self.0.write_str(" "));
258                since = i + 1;
259            }
260        }
261        if since < s.len() {
262            self.0.write_str(&s[since..])
263        } else {
264            Ok(())
265        }
266    }
267
268    #[inline]
269    fn write_fmt(&mut self, args: fmt::Arguments) -> fmt::Result {
270        fmt::write(self, args)
271    }
272}
273
274
275impl Header + Send + Sync {
276    // A trait object looks like this:
277    //
278    // TraitObject { data: *mut (), vtable: *mut () }
279    //
280    // So, we transmute &Trait into a (*mut (), *mut ()). This depends on the
281    // order the compiler has chosen to represent a TraitObject.
282    //
283    // It has been assured that this order will be stable.
284    #[inline]
285    unsafe fn downcast_ref_unchecked<T: 'static>(&self) -> &T {
286        &*(mem::transmute::<*const _, (*const (), *const ())>(self).0 as *const T)
287    }
288
289    #[inline]
290    unsafe fn downcast_mut_unchecked<T: 'static>(&mut self) -> &mut T {
291        &mut *(mem::transmute::<*mut _, (*mut (), *mut ())>(self).0 as *mut T)
292    }
293
294    #[inline]
295    unsafe fn downcast_unchecked<T: 'static>(self: Box<Self>) -> T {
296        *Box::from_raw(mem::transmute::<*mut _, (*mut (), *mut ())>(Box::into_raw(self)).0 as *mut T)
297    }
298}
299
300impl Clone for Box<Header + Send + Sync> {
301    #[inline]
302    fn clone(&self) -> Box<Header + Send + Sync> {
303        self.clone_box()
304    }
305}
306
307#[inline]
308fn header_name<T: Header>() -> &'static str {
309    <T as Header>::header_name()
310}
311
312/// A map of header fields on requests and responses.
313#[derive(Clone)]
314pub struct Headers {
315    data: VecMap<HeaderName, Item>,
316}
317
318impl Default for Headers {
319    fn default() -> Headers {
320        Headers::new()
321    }
322}
323
324macro_rules! literals {
325    ($($len:expr => $($header:path),+;)+) => (
326        fn maybe_literal(s: &str) -> Cow<'static, str> {
327            match s.len() {
328                $($len => {
329                    $(
330                    if Ascii::new(<$header>::header_name()) == Ascii::new(s) {
331                        return Cow::Borrowed(<$header>::header_name());
332                    }
333                    )+
334                })+
335
336                _ => ()
337            }
338
339            trace!("maybe_literal not found, copying {:?}", s);
340            Cow::Owned(s.to_owned())
341        }
342
343        #[test]
344        fn test_literal_lens() {
345            $(
346            $({
347                let s = <$header>::header_name();
348                assert!(s.len() == $len, "{:?} has len of {}, listed as {}", s, s.len(), $len);
349            })+
350            )+
351        }
352    );
353}
354
355literals! {
356    4  => Host, Date, ETag;
357    5  => Allow, Range;
358    6  => Accept, Cookie, Server, Expect;
359    7  => Upgrade, Referer, Expires;
360    8  => Location, IfMatch, IfRange;
361    10 => UserAgent, Connection, SetCookie;
362    12 => ContentType;
363    13 => Authorization<String>, CacheControl, LastModified, IfNoneMatch, AcceptRanges, ContentRange;
364    14 => ContentLength, AcceptCharset;
365    15 => AcceptEncoding, AcceptLanguage;
366    17 => TransferEncoding;
367    25 => StrictTransportSecurity;
368    27 => AccessControlAllowOrigin;
369}
370
371impl Headers {
372
373    /// Creates a new, empty headers map.
374    #[inline]
375    pub fn new() -> Headers {
376        Headers::with_capacity(0)
377    }
378
379    /// Creates a new `Headers` struct with space reserved for `len` headers.
380    #[inline]
381    pub fn with_capacity(len: usize) -> Headers {
382        Headers {
383            data: VecMap::with_capacity(len)
384        }
385    }
386
387    /// Set a header field to the corresponding value.
388    ///
389    /// The field is determined by the type of the value being set.
390    pub fn set<H: Header>(&mut self, value: H) {
391        self.data.insert(HeaderName(Ascii::new(Cow::Borrowed(header_name::<H>()))),
392                         Item::new_typed(value));
393    }
394
395    #[doc(hidden)]
396    pub fn __internal_set_pos<H: Header>(&mut self, pos: usize, value: H) {
397        self.data.insert_pos(
398            HeaderName(Ascii::new(Cow::Borrowed(header_name::<H>()))),
399            Item::new_typed(value),
400            pos,
401        );
402    }
403
404    /// Get a reference to the header field's value, if it exists.
405    pub fn get<H: Header>(&self) -> Option<&H> {
406        self.data.get(&HeaderName(Ascii::new(Cow::Borrowed(header_name::<H>()))))
407        .and_then(Item::typed::<H>)
408    }
409
410    /// Get a mutable reference to the header field's value, if it exists.
411    pub fn get_mut<H: Header>(&mut self) -> Option<&mut H> {
412        self.data.get_mut(&HeaderName(Ascii::new(Cow::Borrowed(header_name::<H>()))))
413        .and_then(Item::typed_mut::<H>)
414    }
415
416    /// Returns a boolean of whether a certain header is in the map.
417    ///
418    /// Example:
419    ///
420    /// ```
421    /// # use hyper::header::Headers;
422    /// # use hyper::header::ContentType;
423    /// # let mut headers = Headers::new();
424    /// headers.set(ContentType::json());
425    /// assert!(headers.has::<ContentType>());
426    /// ```
427    pub fn has<H: Header>(&self) -> bool {
428        self.data.contains_key(&HeaderName(Ascii::new(Cow::Borrowed(header_name::<H>()))))
429    }
430
431    /// Removes a header from the map, if one existed.
432    /// Returns the header, if one has been removed and could be parsed.
433    ///
434    /// Note that this function may return `None` even though a header was removed. If you want to
435    /// know whether a header exists, rather rely on `has`.
436    pub fn remove<H: Header>(&mut self) -> Option<H> {
437        self.data.remove(&HeaderName(Ascii::new(Cow::Borrowed(header_name::<H>()))))
438            .and_then(Item::into_typed::<H>)
439    }
440
441    /// Returns an iterator over the header fields.
442    pub fn iter(&self) -> HeadersItems {
443        HeadersItems {
444            inner: self.data.iter()
445        }
446    }
447
448    /// Returns the number of headers in the map.
449    pub fn len(&self) -> usize {
450        self.data.len()
451    }
452
453    /// Remove all headers from the map.
454    pub fn clear(&mut self) {
455        self.data.clear()
456    }
457
458    /// Access the raw value of a header.
459    ///
460    /// Prefer to use the typed getters instead.
461    ///
462    /// Example:
463    ///
464    /// ```
465    /// # use hyper::header::Headers;
466    /// # let mut headers = Headers::new();
467    /// # headers.set_raw("content-type", "text/plain");
468    /// let raw = headers.get_raw("content-type").unwrap();
469    /// assert_eq!(raw, "text/plain");
470    /// ```
471    pub fn get_raw(&self, name: &str) -> Option<&Raw> {
472        self.data
473            .get(name)
474            .map(Item::raw)
475    }
476
477    /// Set the raw value of a header, bypassing any typed headers.
478    ///
479    /// Example:
480    ///
481    /// ```
482    /// # use hyper::header::Headers;
483    /// # let mut headers = Headers::new();
484    /// headers.set_raw("content-length", b"1".as_ref());
485    /// headers.set_raw("content-length", "2");
486    /// headers.set_raw("content-length", "3".to_string());
487    /// headers.set_raw("content-length", vec![vec![b'4']]);
488    /// ```
489    pub fn set_raw<K: Into<Cow<'static, str>>, V: Into<Raw>>(&mut self, name: K, value: V) {
490        let name = name.into();
491        let value = value.into();
492        self.data.insert(HeaderName(Ascii::new(name)), Item::new_raw(value));
493    }
494
495    /// Append a value to raw value of this header.
496    ///
497    /// If a header already contains a value, this will add another line to it.
498    ///
499    /// If a header does not exist for this name, a new one will be created with
500    /// the value.
501    ///
502    /// Example:
503    ///
504    /// ```
505    /// # use hyper::header::Headers;
506    /// # let mut headers = Headers::new();
507    /// headers.append_raw("x-foo", b"bar".to_vec());
508    /// headers.append_raw("x-foo", b"quux".to_vec());
509    /// ```
510    pub fn append_raw<K: Into<Cow<'static, str>>, V: Into<Raw>>(&mut self, name: K, value: V) {
511        let name = name.into();
512        let value = value.into();
513        let name = HeaderName(Ascii::new(name));
514        if let Some(item) = self.data.get_mut(&name) {
515            item.raw_mut().push(value);
516            return;
517        }
518        self.data.insert(name, Item::new_raw(value));
519    }
520
521    /// Remove a header by name.
522    pub fn remove_raw(&mut self, name: &str) {
523        self.data.remove(name);
524    }
525
526}
527
528impl PartialEq for Headers {
529    fn eq(&self, other: &Headers) -> bool {
530        if self.len() != other.len() {
531            return false;
532        }
533
534        for header in self.iter() {
535            match other.get_raw(header.name()) {
536                Some(val) if val == self.get_raw(header.name()).unwrap() => {},
537                _ => { return false; }
538            }
539        }
540        true
541    }
542}
543
544impl fmt::Display for Headers {
545    #[inline]
546    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
547        for header in self.iter() {
548            try!(fmt::Display::fmt(&header, f));
549        }
550        Ok(())
551    }
552}
553
554impl fmt::Debug for Headers {
555    #[inline]
556    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
557        f.debug_map()
558            .entries(self.iter().map(|view| (view.0.as_ref(), ValueString(view.1))))
559            .finish()
560    }
561}
562
563#[cfg(feature = "compat")]
564impl From<http::HeaderMap> for Headers {
565    fn from(mut header_map: http::HeaderMap) -> Headers {
566        let mut headers = Headers::new();
567        for (name, mut value_drain) in header_map.drain() {
568            if let Some(first_value) = value_drain.next() {
569                let mut raw: Raw = first_value.as_bytes().into();
570                for value in value_drain {
571                    raw.push(value.as_bytes());
572                }
573                headers.append_raw(name.as_str().to_string(), raw);        
574            }
575        }
576        headers
577    }
578}
579
580#[cfg(feature = "compat")]
581impl From<Headers> for http::HeaderMap {
582    fn from(headers: Headers) -> http::HeaderMap {
583        let mut header_map = http::HeaderMap::new();
584        for header in headers.iter() {
585            let entry = header_map.entry(header.name())
586                .expect("attempted to convert invalid header name");
587            let mut value_iter = header.raw().iter().map(|line| {
588                http::header::HeaderValue::from_bytes(line)
589                    .expect("attempted to convert invalid header value")
590            });
591            match entry {
592                http::header::Entry::Occupied(mut  occupied) => {
593                    for value in value_iter {
594                        occupied.append(value);
595                    }
596                },
597                http::header::Entry::Vacant(vacant) => {
598                    if let Some(first_value) = value_iter.next() {
599                        let mut occupied = vacant.insert_entry(first_value);
600                        for value in value_iter {
601                            occupied.append(value);
602                        }
603                    }
604                }
605            }
606        }
607        header_map
608    }
609}
610
611/// An `Iterator` over the fields in a `Headers` map.
612#[allow(missing_debug_implementations)]
613pub struct HeadersItems<'a> {
614    inner: ::std::slice::Iter<'a, (HeaderName, Item)>
615}
616
617impl<'a> Iterator for HeadersItems<'a> {
618    type Item = HeaderView<'a>;
619
620    fn next(&mut self) -> Option<HeaderView<'a>> {
621        self.inner.next().map(|&(ref k, ref v)| HeaderView(k, v))
622    }
623}
624
625/// Returned with the `HeadersItems` iterator.
626pub struct HeaderView<'a>(&'a HeaderName, &'a Item);
627
628impl<'a> HeaderView<'a> {
629    /// Check if a HeaderView is a certain Header.
630    #[inline]
631    pub fn is<H: Header>(&self) -> bool {
632        HeaderName(Ascii::new(Cow::Borrowed(header_name::<H>()))) == *self.0
633    }
634
635    /// Get the Header name as a slice.
636    #[inline]
637    pub fn name(&self) -> &'a str {
638        self.0.as_ref()
639    }
640
641    /// Cast the value to a certain Header type.
642    #[inline]
643    pub fn value<H: Header>(&self) -> Option<&'a H> {
644        self.1.typed::<H>()
645    }
646
647    /// Get just the header value as a String.
648    ///
649    /// This will join multiple values of this header with a `, `.
650    ///
651    /// **Warning:** This may not be the format that should be used to send
652    /// a Request or Response.
653    #[inline]
654    pub fn value_string(&self) -> String {
655        ValueString(self.1).to_string()
656    }
657
658    /// Access the raw value of the header.
659    #[inline]
660    pub fn raw(&self) -> &Raw {
661        self.1.raw()
662    }
663}
664
665impl<'a> fmt::Display for HeaderView<'a> {
666    #[inline]
667    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
668        self.1.write_h1(&mut Formatter(Multi::Line(self.0.as_ref(), f)))
669    }
670}
671
672impl<'a> fmt::Debug for HeaderView<'a> {
673    #[inline]
674    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
675        fmt::Display::fmt(self, f)
676    }
677}
678
679impl<'a> Extend<HeaderView<'a>> for Headers {
680    fn extend<I: IntoIterator<Item=HeaderView<'a>>>(&mut self, iter: I) {
681        for header in iter {
682            self.data.insert((*header.0).clone(), (*header.1).clone());
683        }
684    }
685}
686
687impl<'a> Extend<(&'a str, Bytes)> for Headers {
688    fn extend<I: IntoIterator<Item=(&'a str, Bytes)>>(&mut self, iter: I) {
689        for (name, value) in iter {
690            let name = HeaderName(Ascii::new(maybe_literal(name)));
691            //let trim = header.value.iter().rev().take_while(|&&x| x == b' ').count();
692
693            match self.data.entry(name) {
694                Entry::Vacant(entry) => {
695                    entry.insert(Item::new_raw(self::raw::parsed(value)));
696                }
697                Entry::Occupied(entry) => {
698                    self::raw::push(entry.into_mut().raw_mut(), value);
699                }
700            };
701        }
702    }
703}
704
705impl<'a> FromIterator<HeaderView<'a>> for Headers {
706    fn from_iter<I: IntoIterator<Item=HeaderView<'a>>>(iter: I) -> Headers {
707        let mut headers = Headers::new();
708        headers.extend(iter);
709        headers
710    }
711}
712
713#[derive(Clone, Debug)]
714struct HeaderName(Ascii<Cow<'static, str>>);
715
716impl fmt::Display for HeaderName {
717    #[inline]
718    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
719        fmt::Display::fmt(self.0.as_ref(), f)
720    }
721}
722
723impl AsRef<str> for HeaderName {
724    fn as_ref(&self) -> &str {
725        self.0.as_ref()
726    }
727}
728
729impl PartialEq for HeaderName {
730    #[inline]
731    fn eq(&self, other: &HeaderName) -> bool {
732        let s = self.as_ref();
733        let k = other.as_ref();
734        if s.as_ptr() == k.as_ptr() && s.len() == k.len() {
735            true
736        } else {
737            self.0 == other.0
738        }
739    }
740}
741
742impl PartialEq<HeaderName> for str {
743    fn eq(&self, other: &HeaderName) -> bool {
744        let k = other.as_ref();
745        if self.as_ptr() == k.as_ptr() && self.len() == k.len() {
746            true
747        } else {
748            other.0 == self
749        }
750    }
751}
752
753#[cfg(test)]
754mod tests {
755    use std::fmt;
756    use super::{Headers, Header, Raw, ContentLength, ContentType, Host, SetCookie};
757
758    #[cfg(feature = "nightly")]
759    use test::Bencher;
760
761    macro_rules! make_header {
762        ($name:expr, $value:expr) => ({
763            let mut headers = Headers::new();
764            headers.set_raw(String::from_utf8($name.to_vec()).unwrap(), $value.to_vec());
765            headers
766        });
767        ($text:expr) => ({
768            let bytes = $text;
769            let colon = bytes.iter().position(|&x| x == b':').unwrap();
770            make_header!(&bytes[..colon], &bytes[colon + 2..])
771        })
772    }
773    #[test]
774    fn test_from_raw() {
775        let headers = make_header!(b"Content-Length", b"10");
776        assert_eq!(headers.get(), Some(&ContentLength(10)));
777    }
778
779    #[derive(Clone, PartialEq, Debug)]
780    struct CrazyLength(Option<bool>, usize);
781
782    impl Header for CrazyLength {
783        fn header_name() -> &'static str {
784            "content-length"
785        }
786        fn parse_header(raw: &Raw) -> ::Result<CrazyLength> {
787            use std::str::from_utf8;
788            use std::str::FromStr;
789
790            if let Some(line) = raw.one() {
791                let s = try!(from_utf8(line).map(|s| FromStr::from_str(s).map_err(|_| ::Error::Header)));
792                s.map(|u| CrazyLength(Some(false), u))
793            } else {
794                Err(::Error::Header)
795            }
796        }
797
798        fn fmt_header(&self, f: &mut super::Formatter) -> fmt::Result {
799            f.fmt_line(self)
800        }
801    }
802
803    impl fmt::Display for CrazyLength {
804        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
805            let CrazyLength(ref opt, ref value) = *self;
806            write!(f, "{:?}, {:?}", opt, value)
807        }
808    }
809
810    #[test]
811    fn test_different_structs_for_same_header() {
812        let headers = make_header!(b"Content-Length: 10");
813        assert_eq!(headers.get::<ContentLength>(), Some(&ContentLength(10)));
814        assert_eq!(headers.get::<CrazyLength>(), Some(&CrazyLength(Some(false), 10)));
815    }
816
817    #[test]
818    fn test_trailing_whitespace() {
819        let headers = make_header!(b"Content-Length: 10   ");
820        assert_eq!(headers.get::<ContentLength>(), Some(&ContentLength(10)));
821    }
822
823    #[test]
824    fn test_multiple_reads() {
825        let headers = make_header!(b"Content-Length: 10");
826        let ContentLength(one) = *headers.get::<ContentLength>().unwrap();
827        let ContentLength(two) = *headers.get::<ContentLength>().unwrap();
828        assert_eq!(one, two);
829    }
830
831    #[test]
832    fn test_different_reads() {
833        let mut headers = Headers::new();
834        headers.set_raw("Content-Length", "10");
835        headers.set_raw("Content-Type", "text/plain");
836        let ContentLength(_) = *headers.get::<ContentLength>().unwrap();
837        let ContentType(_) = *headers.get::<ContentType>().unwrap();
838    }
839
840    #[test]
841    fn test_typed_get_raw() {
842        let mut headers = Headers::new();
843        headers.set(ContentLength(15));
844        assert_eq!(headers.get_raw("content-length").unwrap(), "15");
845
846        headers.set(SetCookie(vec![
847            "foo=bar".to_string(),
848            "baz=quux; Path=/path".to_string()
849        ]));
850        assert_eq!(headers.get_raw("set-cookie").unwrap(), &["foo=bar", "baz=quux; Path=/path"][..]);
851    }
852
853    #[test]
854    fn test_get_mutable() {
855        let mut headers = make_header!(b"Content-Length: 10");
856        *headers.get_mut::<ContentLength>().unwrap() = ContentLength(20);
857        assert_eq!(headers.get_raw("content-length").unwrap(), &[b"20".to_vec()][..]);
858        assert_eq!(*headers.get::<ContentLength>().unwrap(), ContentLength(20));
859    }
860
861    #[test]
862    fn test_headers_to_string() {
863        let mut headers = Headers::new();
864        headers.set(ContentLength(15));
865        headers.set(Host::new("foo.bar", None));
866
867        let s = headers.to_string();
868        assert!(s.contains("Host: foo.bar\r\n"));
869        assert!(s.contains("Content-Length: 15\r\n"));
870    }
871
872    #[test]
873    fn test_headers_to_string_raw() {
874        let mut headers = make_header!(b"Content-Length: 10");
875        headers.set_raw("x-foo", vec![b"foo".to_vec(), b"bar".to_vec()]);
876        let s = headers.to_string();
877        assert_eq!(s, "Content-Length: 10\r\nx-foo: foo\r\nx-foo: bar\r\n");
878    }
879
880    #[test]
881    fn test_set_raw() {
882        let mut headers = Headers::new();
883        headers.set(ContentLength(10));
884        headers.set_raw("content-LENGTH", vec![b"20".to_vec()]);
885        assert_eq!(headers.get_raw("Content-length").unwrap(), &[b"20".to_vec()][..]);
886        assert_eq!(headers.get(), Some(&ContentLength(20)));
887    }
888
889    #[test]
890    fn test_append_raw() {
891        let mut headers = Headers::new();
892        headers.set(ContentLength(10));
893        headers.append_raw("content-LENGTH", b"20".to_vec());
894        assert_eq!(headers.get_raw("Content-length").unwrap(), &[b"10".to_vec(), b"20".to_vec()][..]);
895        headers.append_raw("x-foo", "bar");
896        assert_eq!(headers.get_raw("x-foo").unwrap(), &[b"bar".to_vec()][..]);
897    }
898
899    #[test]
900    fn test_remove_raw() {
901        let mut headers = Headers::new();
902        headers.set_raw("content-LENGTH", vec![b"20".to_vec()]);
903        headers.remove_raw("content-LENGTH");
904        assert_eq!(headers.get_raw("Content-length"), None);
905    }
906
907    #[test]
908    fn test_remove() {
909        let mut headers = Headers::new();
910        headers.set(ContentLength(10));
911        assert_eq!(headers.remove(), Some(ContentLength(10)));
912        assert_eq!(headers.len(), 0);
913
914        headers.set(ContentLength(9));
915        assert_eq!(headers.len(), 1);
916        assert!(headers.remove::<CrazyLength>().is_none());
917        assert_eq!(headers.len(), 0);
918    }
919
920    #[test]
921    fn test_len() {
922        let mut headers = Headers::new();
923        headers.set(ContentLength(10));
924        assert_eq!(headers.len(), 1);
925        headers.set(ContentType::json());
926        assert_eq!(headers.len(), 2);
927        // Redundant, should not increase count.
928        headers.set(ContentLength(20));
929        assert_eq!(headers.len(), 2);
930    }
931
932    #[test]
933    fn test_clear() {
934        let mut headers = Headers::new();
935        headers.set(ContentLength(10));
936        headers.set(ContentType::json());
937        assert_eq!(headers.len(), 2);
938        headers.clear();
939        assert_eq!(headers.len(), 0);
940    }
941
942    #[test]
943    fn test_iter() {
944        let mut headers = Headers::new();
945        headers.set(ContentLength(11));
946        for header in headers.iter() {
947            assert!(header.is::<ContentLength>());
948            assert_eq!(header.name(), <ContentLength as Header>::header_name());
949            assert_eq!(header.value(), Some(&ContentLength(11)));
950            assert_eq!(header.value_string(), "11".to_owned());
951        }
952    }
953
954    #[test]
955    fn test_header_view_value_string() {
956        let mut headers = Headers::new();
957        headers.set_raw("foo", vec![b"one".to_vec(), b"two".to_vec()]);
958        for header in headers.iter() {
959            assert_eq!(header.name(), "foo");
960            assert_eq!(header.value_string(), "one, two");
961        }
962    }
963
964    #[test]
965    fn test_header_view_raw() {
966        let mut headers = Headers::new();
967        headers.set_raw("foo", vec![b"one".to_vec(), b"two".to_vec()]);
968        for header in headers.iter() {
969            assert_eq!(header.name(), "foo");
970            let values: Vec<&[u8]> = header.raw().iter().collect();
971            assert_eq!(values, vec![b"one", b"two"]);
972        }
973    }
974
975    #[test]
976    fn test_eq() {
977        let mut headers1 = Headers::new();
978        let mut headers2 = Headers::new();
979
980        assert_eq!(headers1, headers2);
981
982        headers1.set(ContentLength(11));
983        headers2.set(Host::new("foo.bar", None));
984        assert_ne!(headers1, headers2);
985
986        headers1 = Headers::new();
987        headers2 = Headers::new();
988
989        headers1.set(ContentLength(11));
990        headers2.set(ContentLength(11));
991        assert_eq!(headers1, headers2);
992
993        headers1.set(ContentLength(10));
994        assert_ne!(headers1, headers2);
995
996        headers1 = Headers::new();
997        headers2 = Headers::new();
998
999        headers1.set(Host::new("foo.bar", None));
1000        headers1.set(ContentLength(11));
1001        headers2.set(ContentLength(11));
1002        assert_ne!(headers1, headers2);
1003    }
1004
1005    #[test]
1006    #[cfg(feature = "compat")]
1007    fn test_compat() {
1008        use http;
1009
1010        let mut orig_hyper_headers = Headers::new();
1011        orig_hyper_headers.set(ContentLength(11));
1012        orig_hyper_headers.set(Host::new("foo.bar", None));
1013        orig_hyper_headers.append_raw("x-foo", b"bar".to_vec());
1014        orig_hyper_headers.append_raw("x-foo", b"quux".to_vec());
1015
1016        let mut orig_http_headers = http::HeaderMap::new();
1017        orig_http_headers.insert(http::header::CONTENT_LENGTH, "11".parse().unwrap());
1018        orig_http_headers.insert(http::header::HOST, "foo.bar".parse().unwrap());
1019        orig_http_headers.append("x-foo", "bar".parse().unwrap());
1020        orig_http_headers.append("x-foo", "quux".parse().unwrap());
1021
1022        let conv_hyper_headers: Headers = orig_http_headers.clone().into();
1023        let conv_http_headers: http::HeaderMap = orig_hyper_headers.clone().into();
1024        assert_eq!(orig_hyper_headers, conv_hyper_headers);
1025        assert_eq!(orig_http_headers, conv_http_headers);
1026    }
1027
1028    #[cfg(feature = "nightly")]
1029    #[bench]
1030    fn bench_headers_new(b: &mut Bencher) {
1031        b.iter(|| {
1032            let mut h = Headers::new();
1033            h.set(ContentLength(11));
1034            h
1035        })
1036    }
1037
1038    #[cfg(feature = "nightly")]
1039    #[bench]
1040    fn bench_headers_get(b: &mut Bencher) {
1041        let mut headers = Headers::new();
1042        headers.set(ContentLength(11));
1043        b.iter(|| assert_eq!(headers.get::<ContentLength>(), Some(&ContentLength(11))))
1044    }
1045
1046    #[cfg(feature = "nightly")]
1047    #[bench]
1048    fn bench_headers_get_miss(b: &mut Bencher) {
1049        let headers = Headers::new();
1050        b.iter(|| assert!(headers.get::<ContentLength>().is_none()))
1051    }
1052
1053    #[cfg(feature = "nightly")]
1054    #[bench]
1055    fn bench_headers_get_miss_previous_10(b: &mut Bencher) {
1056        let mut headers = Headers::new();
1057        for i in 0..10 {
1058            headers.set_raw(format!("non-standard-{}", i), "hi");
1059        }
1060        b.iter(|| assert!(headers.get::<ContentLength>().is_none()))
1061    }
1062
1063    #[cfg(feature = "nightly")]
1064    #[bench]
1065    fn bench_headers_set(b: &mut Bencher) {
1066        let mut headers = Headers::new();
1067        b.iter(|| headers.set(ContentLength(12)))
1068    }
1069
1070    #[cfg(feature = "nightly")]
1071    #[bench]
1072    fn bench_headers_set_previous_10(b: &mut Bencher) {
1073        let mut headers = Headers::new();
1074        for i in 0..10 {
1075            headers.set_raw(format!("non-standard-{}", i), "hi");
1076        }
1077        b.iter(|| headers.set(ContentLength(12)))
1078    }
1079
1080    #[cfg(feature = "nightly")]
1081    #[bench]
1082    fn bench_headers_set_raw(b: &mut Bencher) {
1083        let mut headers = Headers::new();
1084        b.iter(|| headers.set_raw("non-standard", "hello"))
1085    }
1086
1087    #[cfg(feature = "nightly")]
1088    #[bench]
1089    fn bench_headers_set_raw_previous_10(b: &mut Bencher) {
1090        let mut headers = Headers::new();
1091        for i in 0..10 {
1092            headers.set_raw(format!("non-standard-{}", i), "hi");
1093        }
1094        b.iter(|| headers.set_raw("non-standard", "hello"))
1095    }
1096
1097    #[cfg(feature = "nightly")]
1098    #[bench]
1099    fn bench_headers_has(b: &mut Bencher) {
1100        let mut headers = Headers::new();
1101        headers.set(ContentLength(11));
1102        b.iter(|| assert!(headers.has::<ContentLength>()))
1103    }
1104
1105    #[cfg(feature = "nightly")]
1106    #[bench]
1107    fn bench_headers_view_is(b: &mut Bencher) {
1108        let mut headers = Headers::new();
1109        headers.set(ContentLength(11));
1110        let mut iter = headers.iter();
1111        let view = iter.next().unwrap();
1112        b.iter(|| assert!(view.is::<ContentLength>()))
1113    }
1114
1115    #[cfg(feature = "nightly")]
1116    #[bench]
1117    fn bench_headers_fmt(b: &mut Bencher) {
1118        use std::fmt::Write;
1119        let mut buf = String::with_capacity(64);
1120        let mut headers = Headers::new();
1121        headers.set(ContentLength(11));
1122        headers.set(ContentType::json());
1123        b.bytes = headers.to_string().len() as u64;
1124        b.iter(|| {
1125            let _ = write!(buf, "{}", headers);
1126            ::test::black_box(&buf);
1127            unsafe { buf.as_mut_vec().set_len(0); }
1128        })
1129    }
1130}