From a8e29efdecff39ccd8418722540748f00ba5528c Mon Sep 17 00:00:00 2001 From: Sean McArthur Date: Fri, 12 Jun 2015 15:20:58 -0700 Subject: [PATCH] docs(header): greatly expand on implementing custom headers --- src/header/mod.rs | 74 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) diff --git a/src/header/mod.rs b/src/header/mod.rs index 087ff1e6..d19d48e2 100644 --- a/src/header/mod.rs +++ b/src/header/mod.rs @@ -4,6 +4,80 @@ //! why we're using Rust in the first place. To set or get any header, an object //! must implement the `Header` trait from this module. Several common headers //! are already provided, such as `Host`, `ContentType`, `UserAgent`, and others. +//! +//! # Why Typed? +//! +//! Or, why not stringly-typed? Types give the following advantages: +//! +//! - More difficult to typo, since typos in types should be caught by the compiler +//! - Parsing to a proper type by default\ +//! +//! # Defining Custom Headers +//! +//! Hyper provides a large amount of the most common headers used in HTTP. If +//! you need to define a custom header, it's easy to do while still taking +//! advantage of the type system. Hyper includes a `header!` macro for defining +//! many wrapper-style headers. +//! +//! ``` +//! #[macro_use] extern crate hyper; +//! use hyper::header::Headers; +//! header! { (XRequestGuid, "X-Request-Guid") => [String] } +//! +//! fn main () { +//! let mut headers = Headers::new(); +//! +//! headers.set(XRequestGuid("a proper guid".to_owned())) +//! } +//! ``` +//! +//! This works well for simiple "string" headers. But the header system +//! actually invovles 2 parts: parsing, and formatting. If you need to +//! customize either part, you can do so. +//! +//! ## `Header` and `HeaderFormat` +//! +//! Consider a Do Not Track header. It can be true or false, but it represents +//! that via the numerals `1` and `0`. +//! +//! ``` +//! use std::fmt; +//! use hyper::header::{Header, HeaderFormat}; +//! +//! #[derive(Debug, Clone, Copy)] +//! struct Dnt(bool); +//! +//! impl Header for Dnt { +//! fn header_name() -> &'static str { +//! "DNT" +//! } +//! +//! fn parse_header(raw: &[Vec]) -> hyper::Result { +//! if raw.len() == 1 { +//! let line = &raw[0]; +//! if line.len() == 1 { +//! let byte = line[0]; +//! match byte { +//! b'0' => return Ok(Dnt(true)), +//! b'1' => return Ok(Dnt(false)), +//! _ => () +//! } +//! } +//! } +//! Err(hyper::Error::Header) +//! } +//! } +//! +//! impl HeaderFormat for Dnt { +//! fn fmt_header(&self, f: &mut fmt::Formatter) -> fmt::Result { +//! if self.0 { +//! f.write_str("1") +//! } else { +//! f.write_str("0") +//! } +//! } +//! } +//! ``` use std::any::Any; use std::borrow::{Cow, ToOwned}; use std::collections::HashMap;