|
4 | 4 | //! why we're using Rust in the first place. To set or get any header, an object |
5 | 5 | //! must implement the `Header` trait from this module. Several common headers |
6 | 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 a large amount of the most common headers used 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 simiple "string" headers. But the header system |
| 35 | +//! actually invovles 2 parts: parsing, and formatting. If you need to |
| 36 | +//! customize either part, you can do so. |
| 37 | +//! |
| 38 | +//! ## `Header` and `HeaderFormat` |
| 39 | +//! |
| 40 | +//! Consider a Do Not Track header. It can be true or false, but it represents |
| 41 | +//! that via the numerals `1` and `0`. |
| 42 | +//! |
| 43 | +//! ``` |
| 44 | +//! use std::fmt; |
| 45 | +//! use hyper::header::{Header, HeaderFormat}; |
| 46 | +//! |
| 47 | +//! #[derive(Debug, Clone, Copy)] |
| 48 | +//! struct Dnt(bool); |
| 49 | +//! |
| 50 | +//! impl Header for Dnt { |
| 51 | +//! fn header_name() -> &'static str { |
| 52 | +//! "DNT" |
| 53 | +//! } |
| 54 | +//! |
| 55 | +//! fn parse_header(raw: &[Vec<u8>]) -> hyper::Result<Dnt> { |
| 56 | +//! if raw.len() == 1 { |
| 57 | +//! let line = &raw[0]; |
| 58 | +//! if line.len() == 1 { |
| 59 | +//! let byte = line[0]; |
| 60 | +//! match byte { |
| 61 | +//! b'0' => return Ok(Dnt(true)), |
| 62 | +//! b'1' => return Ok(Dnt(false)), |
| 63 | +//! _ => () |
| 64 | +//! } |
| 65 | +//! } |
| 66 | +//! } |
| 67 | +//! Err(hyper::Error::Header) |
| 68 | +//! } |
| 69 | +//! } |
| 70 | +//! |
| 71 | +//! impl HeaderFormat for Dnt { |
| 72 | +//! fn fmt_header(&self, f: &mut fmt::Formatter) -> fmt::Result { |
| 73 | +//! if self.0 { |
| 74 | +//! f.write_str("1") |
| 75 | +//! } else { |
| 76 | +//! f.write_str("0") |
| 77 | +//! } |
| 78 | +//! } |
| 79 | +//! } |
| 80 | +//! ``` |
7 | 81 | use std::any::Any; |
8 | 82 | use std::borrow::{Cow, ToOwned}; |
9 | 83 | use std::collections::HashMap; |
|
0 commit comments