From f1859dfd7abfc124dd986edc413f754f76c76e8b Mon Sep 17 00:00:00 2001 From: Alexander Mielczarek Date: Mon, 24 Apr 2017 12:21:06 -0500 Subject: [PATCH] feat(headers): add `TE` header struct (#1150) The `TE` header is used by a client to specify which transfer encodings other than `chunked` it will accept. It also specifies whether HTTP trailers are acceptable. This commit also adds a `Trailers` variant to the `hyper::header::shared::Encoding` enum. Closes #1109 BREAKING CHANGE: The `Encoding` enum has an additional variant, `Trailers`. --- src/header/common/te.rs | 67 +++++++++++++++++++++++++++++++++++ src/header/shared/encoding.rs | 6 +++- 2 files changed, 72 insertions(+), 1 deletion(-) create mode 100644 src/header/common/te.rs diff --git a/src/header/common/te.rs b/src/header/common/te.rs new file mode 100644 index 0000000000..11b7bd6711 --- /dev/null +++ b/src/header/common/te.rs @@ -0,0 +1,67 @@ +use header::{Encoding, QualityItem}; + +header! { + /// `TE` header, defined in + /// [RFC7230](http://tools.ietf.org/html/rfc7230#section-4.3) + /// + /// As RFC7230 states, "The "TE" header field in a request indicates what transfer codings, + /// besides chunked, the client is willing to accept in response, and + /// whether or not the client is willing to accept trailer fields in a + /// chunked transfer coding." + /// + /// For HTTP/1.1 compliant clients `chunked` transfer codings are assumed to be acceptable and + /// so should never appear in this header. + /// + /// # ABNF + /// ```plain + /// TE = "TE" ":" #( t-codings ) + /// t-codings = "trailers" | ( transfer-extension [ accept-params ] ) + /// ``` + /// + /// # Example values + /// * `trailers` + /// * `trailers, deflate;q=0.5` + /// * `` + /// + /// # Examples + /// ``` + /// use hyper::header::{Headers, TE, Encoding, qitem}; + /// + /// let mut headers = Headers::new(); + /// headers.set( + /// TE(vec![qitem(Encoding::Trailers)]) + /// ); + /// ``` + /// ``` + /// use hyper::header::{Headers, TE, Encoding, qitem}; + /// + /// let mut headers = Headers::new(); + /// headers.set( + /// TE(vec![ + /// qitem(Encoding::Trailers), + /// qitem(Encoding::Gzip), + /// qitem(Encoding::Deflate), + /// ]) + /// ); + /// ``` + /// ``` + /// use hyper::header::{Headers, TE, Encoding, QualityItem, Quality, qitem}; + /// + /// let mut headers = Headers::new(); + /// headers.set( + /// TE(vec![ + /// qitem(Encoding::Trailers), + /// QualityItem::new(Encoding::Gzip, Quality(600)), + /// QualityItem::new(Encoding::EncodingExt("*".to_owned()), Quality(0)), + /// ]) + /// ); + /// ``` + (TE, "TE") => (QualityItem)* + + test_te { + // From the RFC + test_header!(test1, vec![b"trailers"]); + test_header!(test2, vec![b"trailers, deflate;q=0.5"]); + test_header!(test3, vec![b""]); + } +} diff --git a/src/header/shared/encoding.rs b/src/header/shared/encoding.rs index 32087c0409..fc972dd3c7 100644 --- a/src/header/shared/encoding.rs +++ b/src/header/shared/encoding.rs @@ -1,7 +1,7 @@ use std::fmt; use std::str; -pub use self::Encoding::{Chunked, Brotli, Gzip, Deflate, Compress, Identity, EncodingExt}; +pub use self::Encoding::{Chunked, Brotli, Gzip, Deflate, Compress, Identity, EncodingExt, Trailers}; /// A value to represent an encoding used in `Transfer-Encoding` /// or `Accept-Encoding` header. @@ -19,6 +19,8 @@ pub enum Encoding { Compress, /// The `identity` encoding. Identity, + /// The `trailers` encoding. + Trailers, /// Some other encoding that is less common, can be any String. EncodingExt(String) } @@ -32,6 +34,7 @@ impl fmt::Display for Encoding { Deflate => "deflate", Compress => "compress", Identity => "identity", + Trailers => "trailers", EncodingExt(ref s) => s.as_ref() }) } @@ -47,6 +50,7 @@ impl str::FromStr for Encoding { "gzip" => Ok(Gzip), "compress" => Ok(Compress), "identity" => Ok(Identity), + "trailers" => Ok(Trailers), _ => Ok(EncodingExt(s.to_owned())) } }