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 //! ```
79 use std::borrow::{Cow, ToOwned};
80 #[cfg(feature = "compat")]
81 use std::convert::From;
82 use std::iter::{FromIterator, IntoIterator};
83 use std::{mem, fmt};
84
85 #[cfg(feature = "compat")]
86 use http;
87
88 use unicase::Ascii;
89
90 use self::internals::{Item, VecMap, Entry};
91 use self::sealed::HeaderClone;
92
93 pub use self::shared::*;
94 pub use self::common::*;
95 pub use self::raw::Raw;
96 use bytes::Bytes;
97
98 mod common;
99 mod internals;
100 mod raw;
101 mod shared;
102 pub 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.
109 pub 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.
header_name() -> &'static str where Self: Sized113 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`.
parse_header(raw: &Raw) -> ::Result<Self> where Self: Sized121 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]
fmt_header(&self, f: &mut Formatter) -> fmt::Result136 fn fmt_header(&self, f: &mut Formatter) -> fmt::Result;
137 }
138
139 mod sealed {
140 use super::Header;
141
142 #[doc(hidden)]
143 pub trait HeaderClone {
clone_box(&self) -> Box<Header + Send + Sync>144 fn clone_box(&self) -> Box<Header + Send + Sync>;
145 }
146
147 impl<T: Header + Clone> HeaderClone for T {
148 #[inline]
clone_box(&self) -> Box<Header + Send + Sync>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)]
158 pub struct Formatter<'a, 'b: 'a>(Multi<'a, 'b>);
159
160 enum 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
166 impl<'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.
fmt_line(&mut self, line: &fmt::Display) -> fmt::Result179 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
danger_fmt_line_without_newline_replacer<T: fmt::Display>(&mut self, line: &T) -> fmt::Result205 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
232 struct ValueString<'a>(&'a Item);
233
234 impl<'a> fmt::Debug for ValueString<'a> {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result235 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
242 impl<'a> fmt::Display for ValueString<'a> {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result243 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
244 self.0.write_h1(&mut Formatter(Multi::Join(true, f)))
245 }
246 }
247
248 struct NewlineReplacer<'a, F: fmt::Write + 'a>(&'a mut F);
249
250 impl<'a, F: fmt::Write + 'a> fmt::Write for NewlineReplacer<'a, F> {
251 #[inline]
write_str(&mut self, s: &str) -> fmt::Result252 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]
write_fmt(&mut self, args: fmt::Arguments) -> fmt::Result269 fn write_fmt(&mut self, args: fmt::Arguments) -> fmt::Result {
270 fmt::write(self, args)
271 }
272 }
273
274
275 impl 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]
downcast_ref_unchecked<T: 'static>(&self) -> &T285 unsafe fn downcast_ref_unchecked<T: 'static>(&self) -> &T {
286 &*(mem::transmute::<*const _, (*const (), *const ())>(self).0 as *const T)
287 }
288
289 #[inline]
downcast_mut_unchecked<T: 'static>(&mut self) -> &mut T290 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]
downcast_unchecked<T: 'static>(self: Box<Self>) -> T295 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
300 impl Clone for Box<Header + Send + Sync> {
301 #[inline]
clone(&self) -> Box<Header + Send + Sync>302 fn clone(&self) -> Box<Header + Send + Sync> {
303 self.clone_box()
304 }
305 }
306
307 #[inline]
header_name<T: Header>() -> &'static str308 fn 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)]
314 pub struct Headers {
315 data: VecMap<HeaderName, Item>,
316 }
317
318 impl Default for Headers {
default() -> Headers319 fn default() -> Headers {
320 Headers::new()
321 }
322 }
323
324 macro_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
355 literals! {
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
371 impl Headers {
372
373 /// Creates a new, empty headers map.
374 #[inline]
new() -> Headers375 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]
with_capacity(len: usize) -> Headers381 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.
set<H: Header>(&mut self, value: H)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
set_pos<H: Header>(&mut self, pos: usize, value: H)395 pub(crate) fn set_pos<H: Header>(&mut self, pos: usize, value: H) {
396 self.data.insert_pos(
397 HeaderName(Ascii::new(Cow::Borrowed(header_name::<H>()))),
398 Item::new_typed(value),
399 pos,
400 );
401 }
402
403 /// Get a reference to the header field's value, if it exists.
get<H: Header>(&self) -> Option<&H>404 pub fn get<H: Header>(&self) -> Option<&H> {
405 self.data.get(&HeaderName(Ascii::new(Cow::Borrowed(header_name::<H>()))))
406 .and_then(Item::typed::<H>)
407 }
408
409 /// Get a mutable reference to the header field's value, if it exists.
get_mut<H: Header>(&mut self) -> Option<&mut H>410 pub fn get_mut<H: Header>(&mut self) -> Option<&mut H> {
411 self.data.get_mut(&HeaderName(Ascii::new(Cow::Borrowed(header_name::<H>()))))
412 .and_then(Item::typed_mut::<H>)
413 }
414
415 /// Returns a boolean of whether a certain header is in the map.
416 ///
417 /// Example:
418 ///
419 /// ```
420 /// # use hyper::header::Headers;
421 /// # use hyper::header::ContentType;
422 /// # let mut headers = Headers::new();
423 /// headers.set(ContentType::json());
424 /// assert!(headers.has::<ContentType>());
425 /// ```
has<H: Header>(&self) -> bool426 pub fn has<H: Header>(&self) -> bool {
427 self.data.contains_key(&HeaderName(Ascii::new(Cow::Borrowed(header_name::<H>()))))
428 }
429
430 /// Removes a header from the map, if one existed.
431 /// Returns the header, if one has been removed and could be parsed.
432 ///
433 /// Note that this function may return `None` even though a header was removed. If you want to
434 /// know whether a header exists, rather rely on `has`.
remove<H: Header>(&mut self) -> Option<H>435 pub fn remove<H: Header>(&mut self) -> Option<H> {
436 self.data.remove(&HeaderName(Ascii::new(Cow::Borrowed(header_name::<H>()))))
437 .and_then(Item::into_typed::<H>)
438 }
439
440 /// Returns an iterator over the header fields.
iter(&self) -> HeadersItems441 pub fn iter(&self) -> HeadersItems {
442 HeadersItems {
443 inner: self.data.iter()
444 }
445 }
446
447 /// Returns the number of headers in the map.
len(&self) -> usize448 pub fn len(&self) -> usize {
449 self.data.len()
450 }
451
452 /// Remove all headers from the map.
clear(&mut self)453 pub fn clear(&mut self) {
454 self.data.clear()
455 }
456
457 /// Access the raw value of a header.
458 ///
459 /// Prefer to use the typed getters instead.
460 ///
461 /// Example:
462 ///
463 /// ```
464 /// # use hyper::header::Headers;
465 /// # let mut headers = Headers::new();
466 /// # headers.set_raw("content-type", "text/plain");
467 /// let raw = headers.get_raw("content-type").unwrap();
468 /// assert_eq!(raw, "text/plain");
469 /// ```
get_raw(&self, name: &str) -> Option<&Raw>470 pub fn get_raw(&self, name: &str) -> Option<&Raw> {
471 self.data
472 .get(name)
473 .map(Item::raw)
474 }
475
476 /// Set the raw value of a header, bypassing any typed headers.
477 ///
478 /// Example:
479 ///
480 /// ```
481 /// # use hyper::header::Headers;
482 /// # let mut headers = Headers::new();
483 /// headers.set_raw("content-length", b"1".as_ref());
484 /// headers.set_raw("content-length", "2");
485 /// headers.set_raw("content-length", "3".to_string());
486 /// headers.set_raw("content-length", vec![vec![b'4']]);
487 /// ```
set_raw<K: Into<Cow<'static, str>>, V: Into<Raw>>(&mut self, name: K, value: V)488 pub fn set_raw<K: Into<Cow<'static, str>>, V: Into<Raw>>(&mut self, name: K, value: V) {
489 let name = name.into();
490 let value = value.into();
491 self.data.insert(HeaderName(Ascii::new(name)), Item::new_raw(value));
492 }
493
494 /// Append a value to raw value of this header.
495 ///
496 /// If a header already contains a value, this will add another line to it.
497 ///
498 /// If a header does not exist for this name, a new one will be created with
499 /// the value.
500 ///
501 /// Example:
502 ///
503 /// ```
504 /// # use hyper::header::Headers;
505 /// # let mut headers = Headers::new();
506 /// headers.append_raw("x-foo", b"bar".to_vec());
507 /// headers.append_raw("x-foo", b"quux".to_vec());
508 /// ```
append_raw<K: Into<Cow<'static, str>>, V: Into<Raw>>(&mut self, name: K, value: V)509 pub fn append_raw<K: Into<Cow<'static, str>>, V: Into<Raw>>(&mut self, name: K, value: V) {
510 let name = name.into();
511 let value = value.into();
512 let name = HeaderName(Ascii::new(name));
513 if let Some(item) = self.data.get_mut(&name) {
514 item.raw_mut().push(value);
515 return;
516 }
517 self.data.insert(name, Item::new_raw(value));
518 }
519
520 /// Remove a header by name.
remove_raw(&mut self, name: &str)521 pub fn remove_raw(&mut self, name: &str) {
522 self.data.remove(name);
523 }
524
525 }
526
527 impl PartialEq for Headers {
eq(&self, other: &Headers) -> bool528 fn eq(&self, other: &Headers) -> bool {
529 if self.len() != other.len() {
530 return false;
531 }
532
533 for header in self.iter() {
534 match other.get_raw(header.name()) {
535 Some(val) if val == self.get_raw(header.name()).unwrap() => {},
536 _ => { return false; }
537 }
538 }
539 true
540 }
541 }
542
543 impl fmt::Display for Headers {
544 #[inline]
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result545 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
546 for header in self.iter() {
547 try!(fmt::Display::fmt(&header, f));
548 }
549 Ok(())
550 }
551 }
552
553 impl fmt::Debug for Headers {
554 #[inline]
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result555 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
556 f.debug_map()
557 .entries(self.iter().map(|view| (view.0.as_ref(), ValueString(view.1))))
558 .finish()
559 }
560 }
561
562 #[cfg(feature = "compat")]
563 impl From<http::HeaderMap> for Headers {
from(mut header_map: http::HeaderMap) -> Headers564 fn from(mut header_map: http::HeaderMap) -> Headers {
565 let mut headers = Headers::new();
566 for (name, mut value_drain) in header_map.drain() {
567 if let Some(first_value) = value_drain.next() {
568 let mut raw: Raw = first_value.as_bytes().into();
569 for value in value_drain {
570 raw.push(value.as_bytes());
571 }
572 headers.append_raw(name.as_str().to_string(), raw);
573 }
574 }
575 headers
576 }
577 }
578
579 #[cfg(feature = "compat")]
580 impl From<Headers> for http::HeaderMap {
from(headers: Headers) -> http::HeaderMap581 fn from(headers: Headers) -> http::HeaderMap {
582 let mut header_map = http::HeaderMap::new();
583 for header in headers.iter() {
584 let entry = header_map.entry(header.name())
585 .expect("attempted to convert invalid header name");
586 let mut value_iter = header.raw().iter().map(|line| {
587 http::header::HeaderValue::from_bytes(line)
588 .expect("attempted to convert invalid header value")
589 });
590 match entry {
591 http::header::Entry::Occupied(mut occupied) => {
592 for value in value_iter {
593 occupied.append(value);
594 }
595 },
596 http::header::Entry::Vacant(vacant) => {
597 if let Some(first_value) = value_iter.next() {
598 let mut occupied = vacant.insert_entry(first_value);
599 for value in value_iter {
600 occupied.append(value);
601 }
602 }
603 }
604 }
605 }
606 header_map
607 }
608 }
609
610 /// An `Iterator` over the fields in a `Headers` map.
611 #[allow(missing_debug_implementations)]
612 pub struct HeadersItems<'a> {
613 inner: ::std::slice::Iter<'a, (HeaderName, Item)>
614 }
615
616 impl<'a> Iterator for HeadersItems<'a> {
617 type Item = HeaderView<'a>;
618
next(&mut self) -> Option<HeaderView<'a>>619 fn next(&mut self) -> Option<HeaderView<'a>> {
620 self.inner.next().map(|&(ref k, ref v)| HeaderView(k, v))
621 }
622 }
623
624 /// Returned with the `HeadersItems` iterator.
625 pub struct HeaderView<'a>(&'a HeaderName, &'a Item);
626
627 impl<'a> HeaderView<'a> {
628 /// Check if a HeaderView is a certain Header.
629 #[inline]
is<H: Header>(&self) -> bool630 pub fn is<H: Header>(&self) -> bool {
631 HeaderName(Ascii::new(Cow::Borrowed(header_name::<H>()))) == *self.0
632 }
633
634 /// Get the Header name as a slice.
635 #[inline]
name(&self) -> &'a str636 pub fn name(&self) -> &'a str {
637 self.0.as_ref()
638 }
639
640 /// Cast the value to a certain Header type.
641 #[inline]
value<H: Header>(&self) -> Option<&'a H>642 pub fn value<H: Header>(&self) -> Option<&'a H> {
643 self.1.typed::<H>()
644 }
645
646 /// Get just the header value as a String.
647 ///
648 /// This will join multiple values of this header with a `, `.
649 ///
650 /// **Warning:** This may not be the format that should be used to send
651 /// a Request or Response.
652 #[inline]
value_string(&self) -> String653 pub fn value_string(&self) -> String {
654 ValueString(self.1).to_string()
655 }
656
657 /// Access the raw value of the header.
658 #[inline]
raw(&self) -> &Raw659 pub fn raw(&self) -> &Raw {
660 self.1.raw()
661 }
662 }
663
664 impl<'a> fmt::Display for HeaderView<'a> {
665 #[inline]
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result666 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
667 self.1.write_h1(&mut Formatter(Multi::Line(self.0.as_ref(), f)))
668 }
669 }
670
671 impl<'a> fmt::Debug for HeaderView<'a> {
672 #[inline]
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result673 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
674 fmt::Display::fmt(self, f)
675 }
676 }
677
678 impl<'a> Extend<HeaderView<'a>> for Headers {
extend<I: IntoIterator<Item=HeaderView<'a>>>(&mut self, iter: I)679 fn extend<I: IntoIterator<Item=HeaderView<'a>>>(&mut self, iter: I) {
680 for header in iter {
681 self.data.insert((*header.0).clone(), (*header.1).clone());
682 }
683 }
684 }
685
686 impl<'a> Extend<(&'a str, Bytes)> for Headers {
extend<I: IntoIterator<Item=(&'a str, Bytes)>>(&mut self, iter: I)687 fn extend<I: IntoIterator<Item=(&'a str, Bytes)>>(&mut self, iter: I) {
688 for (name, value) in iter {
689 let name = HeaderName(Ascii::new(maybe_literal(name)));
690 //let trim = header.value.iter().rev().take_while(|&&x| x == b' ').count();
691
692 match self.data.entry(name) {
693 Entry::Vacant(entry) => {
694 entry.insert(Item::new_raw(self::raw::parsed(value)));
695 }
696 Entry::Occupied(entry) => {
697 self::raw::push(entry.into_mut().raw_mut(), value);
698 }
699 };
700 }
701 }
702 }
703
704 impl<'a> FromIterator<HeaderView<'a>> for Headers {
from_iter<I: IntoIterator<Item=HeaderView<'a>>>(iter: I) -> Headers705 fn from_iter<I: IntoIterator<Item=HeaderView<'a>>>(iter: I) -> Headers {
706 let mut headers = Headers::new();
707 headers.extend(iter);
708 headers
709 }
710 }
711
712 #[derive(Clone, Debug)]
713 struct HeaderName(Ascii<Cow<'static, str>>);
714
715 impl fmt::Display for HeaderName {
716 #[inline]
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result717 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
718 fmt::Display::fmt(self.0.as_ref(), f)
719 }
720 }
721
722 impl AsRef<str> for HeaderName {
as_ref(&self) -> &str723 fn as_ref(&self) -> &str {
724 self.0.as_ref()
725 }
726 }
727
728 impl PartialEq for HeaderName {
729 #[inline]
eq(&self, other: &HeaderName) -> bool730 fn eq(&self, other: &HeaderName) -> bool {
731 let s = self.as_ref();
732 let k = other.as_ref();
733 if s.as_ptr() == k.as_ptr() && s.len() == k.len() {
734 true
735 } else {
736 self.0 == other.0
737 }
738 }
739 }
740
741 impl PartialEq<HeaderName> for str {
eq(&self, other: &HeaderName) -> bool742 fn eq(&self, other: &HeaderName) -> bool {
743 let k = other.as_ref();
744 if self.as_ptr() == k.as_ptr() && self.len() == k.len() {
745 true
746 } else {
747 other.0 == self
748 }
749 }
750 }
751
752 #[cfg(test)]
753 mod tests {
754 use std::fmt;
755 use super::{Headers, Header, Raw, ContentLength, ContentType, Host, SetCookie};
756
757 #[cfg(feature = "nightly")]
758 use test::Bencher;
759
760 macro_rules! make_header {
761 ($name:expr, $value:expr) => ({
762 let mut headers = Headers::new();
763 headers.set_raw(String::from_utf8($name.to_vec()).unwrap(), $value.to_vec());
764 headers
765 });
766 ($text:expr) => ({
767 let bytes = $text;
768 let colon = bytes.iter().position(|&x| x == b':').unwrap();
769 make_header!(&bytes[..colon], &bytes[colon + 2..])
770 })
771 }
772 #[test]
test_from_raw()773 fn test_from_raw() {
774 let headers = make_header!(b"Content-Length", b"10");
775 assert_eq!(headers.get(), Some(&ContentLength(10)));
776 }
777
778 #[derive(Clone, PartialEq, Debug)]
779 struct CrazyLength(Option<bool>, usize);
780
781 impl Header for CrazyLength {
header_name() -> &'static str782 fn header_name() -> &'static str {
783 "content-length"
784 }
parse_header(raw: &Raw) -> ::Result<CrazyLength>785 fn parse_header(raw: &Raw) -> ::Result<CrazyLength> {
786 use std::str::from_utf8;
787 use std::str::FromStr;
788
789 if let Some(line) = raw.one() {
790 let s = try!(from_utf8(line).map(|s| FromStr::from_str(s).map_err(|_| ::Error::Header)));
791 s.map(|u| CrazyLength(Some(false), u))
792 } else {
793 Err(::Error::Header)
794 }
795 }
796
fmt_header(&self, f: &mut super::Formatter) -> fmt::Result797 fn fmt_header(&self, f: &mut super::Formatter) -> fmt::Result {
798 f.fmt_line(self)
799 }
800 }
801
802 impl fmt::Display for CrazyLength {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result803 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
804 let CrazyLength(ref opt, ref value) = *self;
805 write!(f, "{:?}, {:?}", opt, value)
806 }
807 }
808
809 #[test]
test_different_structs_for_same_header()810 fn test_different_structs_for_same_header() {
811 let headers = make_header!(b"Content-Length: 10");
812 assert_eq!(headers.get::<ContentLength>(), Some(&ContentLength(10)));
813 assert_eq!(headers.get::<CrazyLength>(), Some(&CrazyLength(Some(false), 10)));
814 }
815
816 #[test]
test_trailing_whitespace()817 fn test_trailing_whitespace() {
818 let headers = make_header!(b"Content-Length: 10 ");
819 assert_eq!(headers.get::<ContentLength>(), Some(&ContentLength(10)));
820 }
821
822 #[test]
test_multiple_reads()823 fn test_multiple_reads() {
824 let headers = make_header!(b"Content-Length: 10");
825 let ContentLength(one) = *headers.get::<ContentLength>().unwrap();
826 let ContentLength(two) = *headers.get::<ContentLength>().unwrap();
827 assert_eq!(one, two);
828 }
829
830 #[test]
test_different_reads()831 fn test_different_reads() {
832 let mut headers = Headers::new();
833 headers.set_raw("Content-Length", "10");
834 headers.set_raw("Content-Type", "text/plain");
835 let ContentLength(_) = *headers.get::<ContentLength>().unwrap();
836 let ContentType(_) = *headers.get::<ContentType>().unwrap();
837 }
838
839 #[test]
test_typed_get_raw()840 fn test_typed_get_raw() {
841 let mut headers = Headers::new();
842 headers.set(ContentLength(15));
843 assert_eq!(headers.get_raw("content-length").unwrap(), "15");
844
845 headers.set(SetCookie(vec![
846 "foo=bar".to_string(),
847 "baz=quux; Path=/path".to_string()
848 ]));
849 assert_eq!(headers.get_raw("set-cookie").unwrap(), &["foo=bar", "baz=quux; Path=/path"][..]);
850 }
851
852 #[test]
test_get_mutable()853 fn test_get_mutable() {
854 let mut headers = make_header!(b"Content-Length: 10");
855 *headers.get_mut::<ContentLength>().unwrap() = ContentLength(20);
856 assert_eq!(headers.get_raw("content-length").unwrap(), &[b"20".to_vec()][..]);
857 assert_eq!(*headers.get::<ContentLength>().unwrap(), ContentLength(20));
858 }
859
860 #[test]
test_headers_to_string()861 fn test_headers_to_string() {
862 let mut headers = Headers::new();
863 headers.set(ContentLength(15));
864 headers.set(Host::new("foo.bar", None));
865
866 let s = headers.to_string();
867 assert!(s.contains("Host: foo.bar\r\n"));
868 assert!(s.contains("Content-Length: 15\r\n"));
869 }
870
871 #[test]
test_headers_to_string_raw()872 fn test_headers_to_string_raw() {
873 let mut headers = make_header!(b"Content-Length: 10");
874 headers.set_raw("x-foo", vec![b"foo".to_vec(), b"bar".to_vec()]);
875 let s = headers.to_string();
876 assert_eq!(s, "Content-Length: 10\r\nx-foo: foo\r\nx-foo: bar\r\n");
877 }
878
879 #[test]
test_set_raw()880 fn test_set_raw() {
881 let mut headers = Headers::new();
882 headers.set(ContentLength(10));
883 headers.set_raw("content-LENGTH", vec![b"20".to_vec()]);
884 assert_eq!(headers.get_raw("Content-length").unwrap(), &[b"20".to_vec()][..]);
885 assert_eq!(headers.get(), Some(&ContentLength(20)));
886 }
887
888 #[test]
test_append_raw()889 fn test_append_raw() {
890 let mut headers = Headers::new();
891 headers.set(ContentLength(10));
892 headers.append_raw("content-LENGTH", b"20".to_vec());
893 assert_eq!(headers.get_raw("Content-length").unwrap(), &[b"10".to_vec(), b"20".to_vec()][..]);
894 headers.append_raw("x-foo", "bar");
895 assert_eq!(headers.get_raw("x-foo").unwrap(), &[b"bar".to_vec()][..]);
896 }
897
898 #[test]
test_remove_raw()899 fn test_remove_raw() {
900 let mut headers = Headers::new();
901 headers.set_raw("content-LENGTH", vec![b"20".to_vec()]);
902 headers.remove_raw("content-LENGTH");
903 assert_eq!(headers.get_raw("Content-length"), None);
904 }
905
906 #[test]
test_remove()907 fn test_remove() {
908 let mut headers = Headers::new();
909 headers.set(ContentLength(10));
910 assert_eq!(headers.remove(), Some(ContentLength(10)));
911 assert_eq!(headers.len(), 0);
912
913 headers.set(ContentLength(9));
914 assert_eq!(headers.len(), 1);
915 assert!(headers.remove::<CrazyLength>().is_none());
916 assert_eq!(headers.len(), 0);
917 }
918
919 #[test]
test_len()920 fn test_len() {
921 let mut headers = Headers::new();
922 headers.set(ContentLength(10));
923 assert_eq!(headers.len(), 1);
924 headers.set(ContentType::json());
925 assert_eq!(headers.len(), 2);
926 // Redundant, should not increase count.
927 headers.set(ContentLength(20));
928 assert_eq!(headers.len(), 2);
929 }
930
931 #[test]
test_clear()932 fn test_clear() {
933 let mut headers = Headers::new();
934 headers.set(ContentLength(10));
935 headers.set(ContentType::json());
936 assert_eq!(headers.len(), 2);
937 headers.clear();
938 assert_eq!(headers.len(), 0);
939 }
940
941 #[test]
test_iter()942 fn test_iter() {
943 let mut headers = Headers::new();
944 headers.set(ContentLength(11));
945 for header in headers.iter() {
946 assert!(header.is::<ContentLength>());
947 assert_eq!(header.name(), <ContentLength as Header>::header_name());
948 assert_eq!(header.value(), Some(&ContentLength(11)));
949 assert_eq!(header.value_string(), "11".to_owned());
950 }
951 }
952
953 #[test]
test_header_view_value_string()954 fn test_header_view_value_string() {
955 let mut headers = Headers::new();
956 headers.set_raw("foo", vec![b"one".to_vec(), b"two".to_vec()]);
957 for header in headers.iter() {
958 assert_eq!(header.name(), "foo");
959 assert_eq!(header.value_string(), "one, two");
960 }
961 }
962
963 #[test]
test_header_view_raw()964 fn test_header_view_raw() {
965 let mut headers = Headers::new();
966 headers.set_raw("foo", vec![b"one".to_vec(), b"two".to_vec()]);
967 for header in headers.iter() {
968 assert_eq!(header.name(), "foo");
969 let values: Vec<&[u8]> = header.raw().iter().collect();
970 assert_eq!(values, vec![b"one", b"two"]);
971 }
972 }
973
974 #[test]
test_eq()975 fn test_eq() {
976 let mut headers1 = Headers::new();
977 let mut headers2 = Headers::new();
978
979 assert_eq!(headers1, headers2);
980
981 headers1.set(ContentLength(11));
982 headers2.set(Host::new("foo.bar", None));
983 assert_ne!(headers1, headers2);
984
985 headers1 = Headers::new();
986 headers2 = Headers::new();
987
988 headers1.set(ContentLength(11));
989 headers2.set(ContentLength(11));
990 assert_eq!(headers1, headers2);
991
992 headers1.set(ContentLength(10));
993 assert_ne!(headers1, headers2);
994
995 headers1 = Headers::new();
996 headers2 = Headers::new();
997
998 headers1.set(Host::new("foo.bar", None));
999 headers1.set(ContentLength(11));
1000 headers2.set(ContentLength(11));
1001 assert_ne!(headers1, headers2);
1002 }
1003
1004 #[test]
1005 #[cfg(feature = "compat")]
test_compat()1006 fn test_compat() {
1007 use http;
1008
1009 let mut orig_hyper_headers = Headers::new();
1010 orig_hyper_headers.set(ContentLength(11));
1011 orig_hyper_headers.set(Host::new("foo.bar", None));
1012 orig_hyper_headers.append_raw("x-foo", b"bar".to_vec());
1013 orig_hyper_headers.append_raw("x-foo", b"quux".to_vec());
1014
1015 let mut orig_http_headers = http::HeaderMap::new();
1016 orig_http_headers.insert(http::header::CONTENT_LENGTH, "11".parse().unwrap());
1017 orig_http_headers.insert(http::header::HOST, "foo.bar".parse().unwrap());
1018 orig_http_headers.append("x-foo", "bar".parse().unwrap());
1019 orig_http_headers.append("x-foo", "quux".parse().unwrap());
1020
1021 let conv_hyper_headers: Headers = orig_http_headers.clone().into();
1022 let conv_http_headers: http::HeaderMap = orig_hyper_headers.clone().into();
1023 assert_eq!(orig_hyper_headers, conv_hyper_headers);
1024 assert_eq!(orig_http_headers, conv_http_headers);
1025 }
1026
1027 #[cfg(feature = "nightly")]
1028 #[bench]
bench_headers_new(b: &mut Bencher)1029 fn bench_headers_new(b: &mut Bencher) {
1030 b.iter(|| {
1031 let mut h = Headers::new();
1032 h.set(ContentLength(11));
1033 h
1034 })
1035 }
1036
1037 #[cfg(feature = "nightly")]
1038 #[bench]
bench_headers_get(b: &mut Bencher)1039 fn bench_headers_get(b: &mut Bencher) {
1040 let mut headers = Headers::new();
1041 headers.set(ContentLength(11));
1042 b.iter(|| assert_eq!(headers.get::<ContentLength>(), Some(&ContentLength(11))))
1043 }
1044
1045 #[cfg(feature = "nightly")]
1046 #[bench]
bench_headers_get_miss(b: &mut Bencher)1047 fn bench_headers_get_miss(b: &mut Bencher) {
1048 let headers = Headers::new();
1049 b.iter(|| assert!(headers.get::<ContentLength>().is_none()))
1050 }
1051
1052 #[cfg(feature = "nightly")]
1053 #[bench]
bench_headers_get_miss_previous_10(b: &mut Bencher)1054 fn bench_headers_get_miss_previous_10(b: &mut Bencher) {
1055 let mut headers = Headers::new();
1056 for i in 0..10 {
1057 headers.set_raw(format!("non-standard-{}", i), "hi");
1058 }
1059 b.iter(|| assert!(headers.get::<ContentLength>().is_none()))
1060 }
1061
1062 #[cfg(feature = "nightly")]
1063 #[bench]
bench_headers_set(b: &mut Bencher)1064 fn bench_headers_set(b: &mut Bencher) {
1065 let mut headers = Headers::new();
1066 b.iter(|| headers.set(ContentLength(12)))
1067 }
1068
1069 #[cfg(feature = "nightly")]
1070 #[bench]
bench_headers_set_previous_10(b: &mut Bencher)1071 fn bench_headers_set_previous_10(b: &mut Bencher) {
1072 let mut headers = Headers::new();
1073 for i in 0..10 {
1074 headers.set_raw(format!("non-standard-{}", i), "hi");
1075 }
1076 b.iter(|| headers.set(ContentLength(12)))
1077 }
1078
1079 #[cfg(feature = "nightly")]
1080 #[bench]
bench_headers_set_raw(b: &mut Bencher)1081 fn bench_headers_set_raw(b: &mut Bencher) {
1082 let mut headers = Headers::new();
1083 b.iter(|| headers.set_raw("non-standard", "hello"))
1084 }
1085
1086 #[cfg(feature = "nightly")]
1087 #[bench]
bench_headers_set_raw_previous_10(b: &mut Bencher)1088 fn bench_headers_set_raw_previous_10(b: &mut Bencher) {
1089 let mut headers = Headers::new();
1090 for i in 0..10 {
1091 headers.set_raw(format!("non-standard-{}", i), "hi");
1092 }
1093 b.iter(|| headers.set_raw("non-standard", "hello"))
1094 }
1095
1096 #[cfg(feature = "nightly")]
1097 #[bench]
bench_headers_has(b: &mut Bencher)1098 fn bench_headers_has(b: &mut Bencher) {
1099 let mut headers = Headers::new();
1100 headers.set(ContentLength(11));
1101 b.iter(|| assert!(headers.has::<ContentLength>()))
1102 }
1103
1104 #[cfg(feature = "nightly")]
1105 #[bench]
bench_headers_view_is(b: &mut Bencher)1106 fn bench_headers_view_is(b: &mut Bencher) {
1107 let mut headers = Headers::new();
1108 headers.set(ContentLength(11));
1109 let mut iter = headers.iter();
1110 let view = iter.next().unwrap();
1111 b.iter(|| assert!(view.is::<ContentLength>()))
1112 }
1113
1114 #[cfg(feature = "nightly")]
1115 #[bench]
bench_headers_fmt(b: &mut Bencher)1116 fn bench_headers_fmt(b: &mut Bencher) {
1117 use std::fmt::Write;
1118 let mut buf = String::with_capacity(64);
1119 let mut headers = Headers::new();
1120 headers.set(ContentLength(11));
1121 headers.set(ContentType::json());
1122 b.bytes = headers.to_string().len() as u64;
1123 b.iter(|| {
1124 let _ = write!(buf, "{}", headers);
1125 ::test::black_box(&buf);
1126 unsafe { buf.as_mut_vec().set_len(0); }
1127 })
1128 }
1129 }
1130