diff --git a/src/header/common/accept.rs b/src/header/common/accept.rs index 14ed97b45d..02522deaf0 100644 --- a/src/header/common/accept.rs +++ b/src/header/common/accept.rs @@ -2,39 +2,39 @@ use mime::Mime; use header::QualityItem; -/// The `Accept` header. -/// -/// The `Accept` header is used to tell a server which content-types the client -/// is capable of using. It can be a comma-separated list of `Mime`s, and the -/// priority can be indicated with a `q` parameter. -/// -/// Example: -/// -/// ``` -/// # use hyper::header::Headers; -/// # use hyper::header::Accept; -/// # use hyper::header::qitem; -/// use hyper::mime::Mime; -/// use hyper::mime::TopLevel::Text; -/// use hyper::mime::SubLevel::{Html, Xml}; -/// # let mut headers = Headers::new(); -/// headers.set(Accept(vec![ -/// qitem(Mime(Text, Html, vec![])), -/// qitem(Mime(Text, Xml, vec![])) ])); -/// ``` -#[derive(Clone, PartialEq, Debug)] -pub struct Accept(pub Vec>); - -impl_list_header!(Accept, - "Accept", - Vec>); +header! { + #[doc="`Accept` header, defined in [RFC7231](http://tools.ietf.org/html/rfc7231#section-5.3.2)"] + #[doc=""] + #[doc="The `Accept` header field can be used by user agents to specify"] + #[doc="response media types that are acceptable. Accept header fields can"] + #[doc="be used to indicate that the request is specifically limited to a"] + #[doc="small set of desired types, as in the case of a request for an"] + #[doc="in-line image"] + #[doc=""] + #[doc="# ABNF"] + #[doc="```plain"] + #[doc="Accept = #( media-range [ accept-params ] )"] + #[doc=""] + #[doc="media-range = ( \"*/*\""] + #[doc=" / ( type \"/\" \"*\" )"] + #[doc=" / ( type \"/\" subtype )"] + #[doc=" ) *( OWS \";\" OWS parameter )"] + #[doc="accept-params = weight *( accept-ext )"] + #[doc="accept-ext = OWS \";\" OWS token [ \"=\" ( token / quoted-string ) ]"] + #[doc="```"] + #[doc=""] + #[doc="# Notes"] + #[doc="* Using always Mime types to represent `media-range` differs from the ABNF."] + #[doc="* **FIXME**: `accept-ext` is not supported."] + (Accept, "Accept") => (QualityItem)+ +} #[cfg(test)] mod tests { use mime::*; use header::{Header, Quality, QualityItem, qitem}; - + use super::Accept; #[test] diff --git a/src/header/common/accept_charset.rs b/src/header/common/accept_charset.rs index 59bb3724bd..7b36bd9d18 100644 --- a/src/header/common/accept_charset.rs +++ b/src/header/common/accept_charset.rs @@ -1,15 +1,22 @@ use header::{Charset, QualityItem}; -/// The `Accept-Charset` header -/// -/// The `Accept-Charset` header can be used by clients to indicate what -/// response charsets they accept. -#[derive(Clone, PartialEq, Debug)] -pub struct AcceptCharset(pub Vec>); - -impl_list_header!(AcceptCharset, - "Accept-Charset", - Vec>); +header! { + #[doc="`Accept-Charset` header, defined in"] + #[doc="[RFC7231](http://tools.ietf.org/html/rfc7231#section-5.3.3)"] + #[doc=""] + #[doc="The `Accept-Charset` header field can be sent by a user agent to"] + #[doc="indicate what charsets are acceptable in textual response content."] + #[doc="This field allows user agents capable of understanding more"] + #[doc="comprehensive or special-purpose charsets to signal that capability"] + #[doc="to an origin server that is capable of representing information in"] + #[doc="those charsets."] + #[doc=""] + #[doc="# ABNF"] + #[doc="```plain"] + #[doc="Accept-Charset = 1#( ( charset / \"*\" ) [ weight ] )"] + #[doc="```"] + (AcceptCharset, "Accept-Charset") => (QualityItem)+ +} #[test] diff --git a/src/header/common/accept_encoding.rs b/src/header/common/accept_encoding.rs index 1799156d76..03a254f578 100644 --- a/src/header/common/accept_encoding.rs +++ b/src/header/common/accept_encoding.rs @@ -1,15 +1,22 @@ use header::{Encoding, QualityItem}; -/// The `Accept-Encoding` header -/// -/// The `Accept-Encoding` header can be used by clients to indicate what -/// response encodings they accept. -#[derive(Clone, PartialEq, Debug)] -pub struct AcceptEncoding(pub Vec>); - -impl_list_header!(AcceptEncoding, - "Accept-Encoding", - Vec>); +header! { + #[doc="`Accept-Encoding` header, defined in"] + #[doc="[RFC7231](http://tools.ietf.org/html/rfc7231#section-5.3.4)"] + #[doc=""] + #[doc="The `Accept-Encoding` header field can be used by user agents to"] + #[doc="indicate what response content-codings are"] + #[doc="acceptable in the response. An `identity` token is used as a synonym"] + #[doc="for \"no encoding\" in order to communicate when no encoding is"] + #[doc="preferred."] + #[doc=""] + #[doc="# ABNF"] + #[doc="```plain"] + #[doc="Accept-Encoding = #( codings [ weight ] )"] + #[doc="codings = content-coding / \"identity\" / \"*\""] + #[doc="```"] + (AcceptEncoding, "Accept-Encoding") => (QualityItem)* +} #[cfg(test)] mod tests { diff --git a/src/header/common/accept_language.rs b/src/header/common/accept_language.rs index 838ebbeec5..3cc95c52ba 100644 --- a/src/header/common/accept_language.rs +++ b/src/header/common/accept_language.rs @@ -35,16 +35,21 @@ impl fmt::Display for Language { } } -/// The `Accept-Language` header -/// -/// The `Accept-Language` header can be used by clients to indicate what -/// response languages they accept. -#[derive(Clone, PartialEq, Debug)] -pub struct AcceptLanguage(pub Vec>); - -impl_list_header!(AcceptLanguage, - "Accept-Language", - Vec>); +header! { + #[doc="`Accept-Language` header, defined in"] + #[doc="[RFC7231](http://tools.ietf.org/html/rfc7231#section-5.3.5)"] + #[doc=""] + #[doc="The `Accept-Language` header field can be used by user agents to"] + #[doc="indicate the set of natural languages that are preferred in the"] + #[doc="response."] + #[doc=""] + #[doc="# ABNF"] + #[doc="```plain"] + #[doc="Accept-Language = 1#( language-range [ weight ] )"] + #[doc="language-range = "] + #[doc="```"] + (AcceptLanguage, "Accept-Language") => (QualityItem)+ +} #[cfg(test)] mod tests { diff --git a/src/header/common/allow.rs b/src/header/common/allow.rs index b3026a7b1e..41464388f8 100644 --- a/src/header/common/allow.rs +++ b/src/header/common/allow.rs @@ -1,14 +1,19 @@ use method::Method; -/// The `Allow` header. -/// See also https://tools.ietf.org/html/rfc7231#section-7.4.1 - -#[derive(Clone, PartialEq, Debug)] -pub struct Allow(pub Vec); - -impl_list_header!(Allow, - "Allow", - Vec); +header! { + #[doc="`Allow` header, defined in [RFC7231](http://tools.ietf.org/html/rfc7231#section-7.4.1)"] + #[doc=""] + #[doc="The `Allow` header field lists the set of methods advertised as"] + #[doc="supported by the target resource. The purpose of this field is"] + #[doc="strictly to inform the recipient of valid request methods associated"] + #[doc="with the resource."] + #[doc=""] + #[doc="# ABNF"] + #[doc="```plain"] + #[doc="Allow = #method"] + #[doc="```"] + (Allow, "Allow") => (Method)* +} #[cfg(test)] mod tests { diff --git a/src/header/common/content_encoding.rs b/src/header/common/content_encoding.rs index 6e56c388c1..0d836bb68f 100644 --- a/src/header/common/content_encoding.rs +++ b/src/header/common/content_encoding.rs @@ -1,19 +1,23 @@ use header::Encoding; -/// The `Content-Encoding` header. -/// -/// This header describes the encoding of the message body. It can be -/// comma-separated, including multiple encodings. -/// -/// ```notrust -/// Content-Encoding: gzip -/// ``` -#[derive(Clone, PartialEq, Debug)] -pub struct ContentEncoding(pub Vec); - -impl_list_header!(ContentEncoding, - "Content-Encoding", - Vec); +header! { + #[doc="`Content-Encoding` header, defined in"] + #[doc="[RFC7231](http://tools.ietf.org/html/rfc7231#section-3.1.2.2)"] + #[doc=""] + #[doc="The `Content-Encoding` header field indicates what content codings"] + #[doc="have been applied to the representation, beyond those inherent in the"] + #[doc="media type, and thus what decoding mechanisms have to be applied in"] + #[doc="order to obtain data in the media type referenced by the Content-Type"] + #[doc="header field. Content-Encoding is primarily used to allow a"] + #[doc="representation's data to be compressed without losing the identity of"] + #[doc="its underlying media type."] + #[doc=""] + #[doc="# ABNF"] + #[doc="```plain"] + #[doc="Content-Encoding = 1#content-coding"] + #[doc="```"] + (ContentEncoding, "ContentEncoding") => (Encoding)+ +} bench_header!(single, ContentEncoding, { vec![b"gzip".to_vec()] }); bench_header!(multiple, ContentEncoding, { vec![b"gzip, deflate".to_vec()] }); diff --git a/src/header/common/content_length.rs b/src/header/common/content_length.rs index f65744ab89..ac6308809e 100644 --- a/src/header/common/content_length.rs +++ b/src/header/common/content_length.rs @@ -1,11 +1,21 @@ -/// The `Content-Length` header. -/// -/// Simply a wrapper around a `u64`. -#[derive(Copy, Clone, PartialEq, Debug)] -pub struct ContentLength(pub u64); - -impl_header!(ContentLength, - "Content-Length", - u64); +header! { + #[doc="`Content-Length` header, defined in"] + #[doc="[RFC7230](http://tools.ietf.org/html/rfc7230#section-3.3.2)"] + #[doc=""] + #[doc="When a message does not have a `Transfer-Encoding` header field, a"] + #[doc="Content-Length header field can provide the anticipated size, as a"] + #[doc="decimal number of octets, for a potential payload body. For messages"] + #[doc="that do include a payload body, the Content-Length field-value"] + #[doc="provides the framing information necessary for determining where the"] + #[doc="body (and message) ends. For messages that do not include a payload"] + #[doc="body, the Content-Length indicates the size of the selected"] + #[doc="representation."] + #[doc=""] + #[doc="# ABNF"] + #[doc="```plain"] + #[doc="Content-Length = 1*DIGIT"] + #[doc="```"] + (ContentLength, "Content-Length") => [u64] +} bench_header!(bench, ContentLength, { vec![b"42349984".to_vec()] }); diff --git a/src/header/common/content_type.rs b/src/header/common/content_type.rs index 264ed257b9..427de5eef8 100644 --- a/src/header/common/content_type.rs +++ b/src/header/common/content_type.rs @@ -1,14 +1,22 @@ use mime::Mime; -/// The `Content-Type` header. -/// -/// Used to describe the MIME type of message body. Can be used with both -/// requests and responses. -#[derive(Clone, PartialEq, Debug)] -pub struct ContentType(pub Mime); - -impl_header!(ContentType, - "Content-Type", - Mime); +header! { + #[doc="`Content-Type` header, defined in"] + #[doc="[RFC7231](http://tools.ietf.org/html/rfc7231#section-3.1.1.5)"] + #[doc=""] + #[doc="The `Content-Type` header field indicates the media type of the"] + #[doc="associated representation: either the representation enclosed in the"] + #[doc="message payload or the selected representation, as determined by the"] + #[doc="message semantics. The indicated media type defines both the data"] + #[doc="format and how that data is intended to be processed by a recipient,"] + #[doc="within the scope of the received message semantics, after any content"] + #[doc="codings indicated by Content-Encoding are decoded."] + #[doc=""] + #[doc="# ABNF"] + #[doc="```plain"] + #[doc="Content-Type = media-type"] + #[doc="```"] + (ContentType, "Content-Type") => [Mime] +} bench_header!(bench, ContentType, { vec![b"application/json; charset=utf-8".to_vec()] }); diff --git a/src/header/common/date.rs b/src/header/common/date.rs index 47ca75daa9..70fcb5fed5 100644 --- a/src/header/common/date.rs +++ b/src/header/common/date.rs @@ -1,10 +1,17 @@ use header::HttpDate; -/// The `Date` header field. -#[derive(Copy, PartialEq, Clone, Debug)] -pub struct Date(pub HttpDate); - -impl_header!(Date, "Date", HttpDate); +header! { + #[doc="`Date` header, defined in [RFC7231](http://tools.ietf.org/html/rfc7231#section-7.1.1.2)"] + #[doc=""] + #[doc="The `Date` header field represents the date and time at which the"] + #[doc="message was originated."] + #[doc=""] + #[doc="# ABNF"] + #[doc="```plain"] + #[doc="Date = HTTP-date"] + #[doc="```"] + (Date, "Date") => [HttpDate] +} bench_header!(imf_fixdate, Date, { vec![b"Sun, 07 Nov 1994 08:48:37 GMT".to_vec()] }); bench_header!(rfc_850, Date, { vec![b"Sunday, 06-Nov-94 08:49:37 GMT".to_vec()] }); diff --git a/src/header/common/expires.rs b/src/header/common/expires.rs index 57819180ba..613ef6a0e0 100644 --- a/src/header/common/expires.rs +++ b/src/header/common/expires.rs @@ -1,9 +1,21 @@ use header::HttpDate; -/// The `Expires` header field. -#[derive(Copy, PartialEq, Clone, Debug)] -pub struct Expires(pub HttpDate); -impl_header!(Expires, "Expires", HttpDate); +header! { + #[doc="`Expires` header, defined in [RFC7234](http://tools.ietf.org/html/rfc7234#section-5.3)"] + #[doc=""] + #[doc="The `Expires` header field gives the date/time after which the"] + #[doc="response is considered stale."] + #[doc=""] + #[doc="The presence of an Expires field does not imply that the original"] + #[doc="resource will change or cease to exist at, before, or after that"] + #[doc="time."] + #[doc=""] + #[doc="# ABNF"] + #[doc="```plain"] + #[doc="Expires = HTTP-date"] + #[doc="```"] + (Expires, "Expires") => [HttpDate] +} bench_header!(imf_fixdate, Expires, { vec![b"Sun, 07 Nov 1994 08:48:37 GMT".to_vec()] }); bench_header!(rfc_850, Expires, { vec![b"Sunday, 06-Nov-94 08:49:37 GMT".to_vec()] }); diff --git a/src/header/common/if_modified_since.rs b/src/header/common/if_modified_since.rs index 53dae88a12..b845320393 100644 --- a/src/header/common/if_modified_since.rs +++ b/src/header/common/if_modified_since.rs @@ -1,9 +1,21 @@ use header::HttpDate; -/// The `If-Modified-Since` header field. -#[derive(Copy, PartialEq, Clone, Debug)] -pub struct IfModifiedSince(pub HttpDate); -impl_header!(IfModifiedSince, "If-Modified-Since", HttpDate); +header! { + #[doc="`If-Modified-Since` header, defined in"] + #[doc="[RFC7232](http://tools.ietf.org/html/rfc7232#section-3.3)"] + #[doc=""] + #[doc="The `If-Modified-Since` header field makes a GET or HEAD request"] + #[doc="method conditional on the selected representation's modification date"] + #[doc="being more recent than the date provided in the field-value."] + #[doc="Transfer of the selected representation's data is avoided if that"] + #[doc="data has not changed."] + #[doc=""] + #[doc="# ABNF"] + #[doc="```plain"] + #[doc="If-Unmodified-Since = HTTP-date"] + #[doc="```"] + (IfModifiedSince, "If-Modified-Since") => [HttpDate] +} bench_header!(imf_fixdate, IfModifiedSince, { vec![b"Sun, 07 Nov 1994 08:48:37 GMT".to_vec()] }); bench_header!(rfc_850, IfModifiedSince, { vec![b"Sunday, 06-Nov-94 08:49:37 GMT".to_vec()] }); diff --git a/src/header/common/if_unmodified_since.rs b/src/header/common/if_unmodified_since.rs index 88d0f48146..200d030d5a 100644 --- a/src/header/common/if_unmodified_since.rs +++ b/src/header/common/if_unmodified_since.rs @@ -1,10 +1,21 @@ use header::HttpDate; -/// The `If-Unmodified-Since` header field. -#[derive(Copy, PartialEq, Clone, Debug)] -pub struct IfUnmodifiedSince(pub HttpDate); - -impl_header!(IfUnmodifiedSince, "If-Unmodified-Since", HttpDate); +header! { + #[doc="`If-Unmodified-Since` header, defined in"] + #[doc="[RFC7232](http://tools.ietf.org/html/rfc7232#section-3.4)"] + #[doc=""] + #[doc="The `If-Unmodified-Since` header field makes the request method"] + #[doc="conditional on the selected representation's last modification date"] + #[doc="being earlier than or equal to the date provided in the field-value."] + #[doc="This field accomplishes the same purpose as If-Match for cases where"] + #[doc="the user agent does not have an entity-tag for the representation."] + #[doc=""] + #[doc="# ABNF"] + #[doc="```plain"] + #[doc="If-Unmodified-Since = HTTP-date"] + #[doc="```"] + (IfUnmodifiedSince, "If-Unmodified-Since") => [HttpDate] +} bench_header!(imf_fixdate, IfUnmodifiedSince, { vec![b"Sun, 07 Nov 1994 08:48:37 GMT".to_vec()] }); bench_header!(rfc_850, IfUnmodifiedSince, { vec![b"Sunday, 06-Nov-94 08:49:37 GMT".to_vec()] }); diff --git a/src/header/common/last_modified.rs b/src/header/common/last_modified.rs index 5b90dce6e4..cf3f0cf564 100644 --- a/src/header/common/last_modified.rs +++ b/src/header/common/last_modified.rs @@ -1,10 +1,19 @@ use header::HttpDate; -/// The `LastModified` header field. -#[derive(Copy, PartialEq, Clone, Debug)] -pub struct LastModified(pub HttpDate); - -impl_header!(LastModified, "Last-Modified", HttpDate); +header! { + #[doc="`Last-Modified` header, defined in [RFC7232](http://tools.ietf.org/html/rfc7232#section-2.2)"] + #[doc=""] + #[doc="The `Last-Modified` header field in a response provides a timestamp"] + #[doc="indicating the date and time at which the origin server believes the"] + #[doc="selected representation was last modified, as determined at the"] + #[doc="conclusion of handling the request."] + #[doc=""] + #[doc="# ABNF"] + #[doc="```plain"] + #[doc="Expires = HTTP-date"] + #[doc="```"] + (LastModified, "Last-Modified") => [HttpDate] +} bench_header!(imf_fixdate, LastModified, { vec![b"Sun, 07 Nov 1994 08:48:37 GMT".to_vec()] }); bench_header!(rfc_850, LastModified, { vec![b"Sunday, 06-Nov-94 08:49:37 GMT".to_vec()] }); diff --git a/src/header/common/location.rs b/src/header/common/location.rs index a1232482a2..f5d23023f0 100644 --- a/src/header/common/location.rs +++ b/src/header/common/location.rs @@ -1,19 +1,19 @@ -/// The `Location` header. -/// -/// The Location response-header field is used to redirect the recipient to -/// a location other than the Request-URI for completion of the request or identification -/// of a new resource. For 201 (Created) responses, the Location is that of the new -/// resource which was created by the request. For 3xx responses, the location SHOULD -/// indicate the server's preferred URI for automatic redirection to the resource. -/// The field value consists of a single absolute URI. -/// -/// Currently is just a String, but it should probably become a better type, -/// like url::Url or something. -#[derive(Clone, PartialEq, Debug)] -pub struct Location(pub String); +header! { + #[doc="`Location` header, defined in"] + #[doc="[RFC7231](http://tools.ietf.org/html/rfc7231#section-7.1.2)"] + #[doc=""] + #[doc="The `Location` header field is used in some responses to refer to a"] + #[doc="specific resource in relation to the response. The type of"] + #[doc="relationship is defined by the combination of request method and"] + #[doc="status code semantics."] + #[doc=""] + #[doc="# ABNF"] + #[doc="```plain"] + #[doc="Location = URI-reference"] + #[doc="```"] + // TODO: Use URL + (Location, "Location") => [String] -impl_header!(Location, - "Location", - String); +} bench_header!(bench, Location, { vec![b"http://foo.com/hello:3000".to_vec()] }); diff --git a/src/header/common/mod.rs b/src/header/common/mod.rs index 7a374b8d70..dd57a0a557 100644 --- a/src/header/common/mod.rs +++ b/src/header/common/mod.rs @@ -89,64 +89,91 @@ macro_rules! deref( ); #[macro_export] -macro_rules! impl_list_header( - ($from:ident, $name:expr, $item:ty) => { - deref!($from => $item); - - impl $crate::header::Header for $from { +macro_rules! header { + // $a:meta: Attributes associated with the header item (usually docs) + // $id:ident: Identifier of the header + // $n:expr: Lowercase name of the header + // $nn:expr: Nice name of the header + + // List header, zero or more items + ($(#[$a:meta])*($id:ident, $n:expr) => ($item:ty)*) => { + $(#[$a])* + #[derive(Clone, Debug, PartialEq)] + pub struct $id(pub Vec<$item>); + deref!($id => Vec<$item>); + impl $crate::header::Header for $id { fn header_name() -> &'static str { - $name + $n } - - fn parse_header(raw: &[Vec]) -> Option<$from> { - $crate::header::parsing::from_comma_delimited(raw).map($from) + fn parse_header(raw: &[Vec]) -> Option { + $crate::header::parsing::from_comma_delimited(raw).map($id) } } - - impl $crate::header::HeaderFormat for $from { - fn fmt_header(&self, fmt: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { - $crate::header::parsing::fmt_comma_delimited(fmt, &self[..]) + impl $crate::header::HeaderFormat for $id { + fn fmt_header(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { + $crate::header::parsing::fmt_comma_delimited(f, &self.0[..]) } } - - impl ::std::fmt::Display for $from { + impl ::std::fmt::Display for $id { fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { use $crate::header::HeaderFormat; self.fmt_header(f) } } - } -); -#[macro_export] -macro_rules! impl_header( - ($from:ident, $name:expr, $item:ty) => { - deref!($from => $item); - - impl $crate::header::Header for $from { + }; + // List header, one or more items + ($(#[$a:meta])*($id:ident, $n:expr) => ($item:ty)+) => { + $(#[$a])* + #[derive(Clone, Debug, PartialEq)] + pub struct $id(pub Vec<$item>); + deref!($id => Vec<$item>); + impl $crate::header::Header for $id { fn header_name() -> &'static str { - $name + $n } - - fn parse_header(raw: &[Vec]) -> Option<$from> { - $crate::header::parsing::from_one_raw_str(raw).map($from) + fn parse_header(raw: &[Vec]) -> Option { + $crate::header::parsing::from_comma_delimited(raw).map($id) } } - - impl $crate::header::HeaderFormat for $from { + impl $crate::header::HeaderFormat for $id { fn fmt_header(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { - ::std::fmt::Display::fmt(&**self, f) + $crate::header::parsing::fmt_comma_delimited(f, &self.0[..]) } } - - impl ::std::fmt::Display for $from { + impl ::std::fmt::Display for $id { fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { use $crate::header::HeaderFormat; self.fmt_header(f) } } - } -); + }; + // Single value header + ($(#[$a:meta])*($id:ident, $n:expr) => [$value:ty]) => { + $(#[$a])* + #[derive(Clone, Debug, PartialEq)] + pub struct $id(pub $value); + deref!($id => $value); + impl $crate::header::Header for $id { + fn header_name() -> &'static str { + $n + } + fn parse_header(raw: &[Vec]) -> Option { + $crate::header::parsing::from_one_raw_str(raw).map($id) + } + } + impl $crate::header::HeaderFormat for $id { + fn fmt_header(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { + ::std::fmt::Display::fmt(&**self, f) + } + } + impl ::std::fmt::Display for $id { + fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { + ::std::fmt::Display::fmt(&**self, f) + } + } + }; +} mod access_control; mod accept; diff --git a/src/header/common/referer.rs b/src/header/common/referer.rs index 4839401538..ab720537ea 100644 --- a/src/header/common/referer.rs +++ b/src/header/common/referer.rs @@ -1,16 +1,19 @@ -/// The `Referer` header. -/// -/// The Referer header is used by user agents to inform server about -/// the page URL user has came from. -/// -/// See alse [RFC 1945, section 10.13](http://tools.ietf.org/html/rfc1945#section-10.13). -/// -/// Currently just a string, but maybe better replace it with url::Url or something like it. -#[derive(Clone, PartialEq, Debug)] -pub struct Referer(pub String); - -impl_header!(Referer, - "Referer", - String); +header! { + #[doc="`Referer` header, defined in"] + #[doc="[RFC7231](http://tools.ietf.org/html/rfc7231#section-5.5.2)"] + #[doc=""] + #[doc="The `Referer` [sic] header field allows the user agent to specify a"] + #[doc="URI reference for the resource from which the target URI was obtained"] + #[doc="(i.e., the \"referrer\", though the field name is misspelled). A user"] + #[doc="agent MUST NOT include the fragment and userinfo components of the"] + #[doc="URI reference, if any, when generating the Referer field value."] + #[doc=""] + #[doc="# ABNF"] + #[doc="```plain"] + #[doc="Referer = absolute-URI / partial-URI"] + #[doc="```"] + // TODO: Use URL + (Referer, "Referer") => [String] +} bench_header!(bench, Referer, { vec![b"http://foo.com/hello:3000".to_vec()] }); diff --git a/src/header/common/server.rs b/src/header/common/server.rs index 2b95033e5e..476d4bc083 100644 --- a/src/header/common/server.rs +++ b/src/header/common/server.rs @@ -1,11 +1,20 @@ -/// The `Server` header field. -/// -/// They can contain any value, so it just wraps a `String`. -#[derive(Clone, PartialEq, Debug)] -pub struct Server(pub String); - -impl_header!(Server, - "Server", - String); +header! { + #[doc="`Server` header, defined in [RFC7231](http://tools.ietf.org/html/rfc7231#section-7.4.2)"] + #[doc=""] + #[doc="The `Server` header field contains information about the software"] + #[doc="used by the origin server to handle the request, which is often used"] + #[doc="by clients to help identify the scope of reported interoperability"] + #[doc="problems, to work around or tailor requests to avoid particular"] + #[doc="server limitations, and for analytics regarding server or operating"] + #[doc="system use. An origin server MAY generate a Server field in its"] + #[doc="responses."] + #[doc=""] + #[doc="# ABNF"] + #[doc="```plain"] + #[doc="Server = product *( RWS ( product / comment ) )"] + #[doc="```"] + // TODO: Maybe parse as defined in the spec? + (Server, "Server") => [String] +} bench_header!(bench, Server, { vec![b"Some String".to_vec()] }); diff --git a/src/header/common/transfer_encoding.rs b/src/header/common/transfer_encoding.rs index c031f2f55d..4e8db0e95d 100644 --- a/src/header/common/transfer_encoding.rs +++ b/src/header/common/transfer_encoding.rs @@ -1,24 +1,20 @@ use header::Encoding; -/// The `Transfer-Encoding` header. -/// -/// This header describes the encoding of the message body. It can be -/// comma-separated, including multiple encodings. -/// -/// ```notrust -/// Transfer-Encoding: gzip, chunked -/// ``` -/// -/// According to the spec, if a `Content-Length` header is not included, -/// this header should include `chunked` as the last encoding. -/// -/// The implementation uses a vector of `Encoding` values. -#[derive(Clone, PartialEq, Debug)] -pub struct TransferEncoding(pub Vec); - -impl_list_header!(TransferEncoding, - "Transfer-Encoding", - Vec); +header! { + #[doc="`Transfer-Encoding` header, defined in"] + #[doc="[RFC7230](http://tools.ietf.org/html/rfc7230#section-3.3.1)"] + #[doc=""] + #[doc="The `Transfer-Encoding` header field lists the transfer coding names"] + #[doc="corresponding to the sequence of transfer codings that have been (or"] + #[doc="will be) applied to the payload body in order to form the message"] + #[doc="body."] + #[doc=""] + #[doc="# ABNF"] + #[doc="```plain"] + #[doc="Transfer-Encoding = 1#transfer-coding"] + #[doc="```"] + (TransferEncoding, "Transfer-Encoding") => (Encoding)+ +} bench_header!(normal, TransferEncoding, { vec![b"chunked, gzip".to_vec()] }); bench_header!(ext, TransferEncoding, { vec![b"ext".to_vec()] }); diff --git a/src/header/common/user_agent.rs b/src/header/common/user_agent.rs index 51112d1fba..2a481e9bab 100644 --- a/src/header/common/user_agent.rs +++ b/src/header/common/user_agent.rs @@ -1,14 +1,24 @@ -/// The `User-Agent` header field. -/// -/// They can contain any value, so it just wraps a `String`. -#[derive(Clone, PartialEq, Debug)] -pub struct UserAgent(pub String); - -impl_header!(UserAgent, - "User-Agent", - String); - -bench_header!(bench, UserAgent, { vec![b"cargo bench".to_vec()] }); +header! { + #[doc="`User-Agent` header, defined in"] + #[doc="[RFC7231](http://tools.ietf.org/html/rfc7231#section-5.5.3)"] + #[doc=""] + #[doc="The `User-Agent` header field contains information about the user"] + #[doc="agent originating the request, which is often used by servers to help"] + #[doc="identify the scope of reported interoperability problems, to work"] + #[doc="around or tailor responses to avoid particular user agent"] + #[doc="limitations, and for analytics regarding browser or operating system"] + #[doc="use. A user agent SHOULD send a User-Agent field in each request"] + #[doc="unless specifically configured not to do so."] + #[doc=""] + #[doc="# ABNF"] + #[doc="```plain"] + #[doc="User-Agent = product *( RWS ( product / comment ) )"] + #[doc="product = token [\"/\" product-version]"] + #[doc="product-version = token"] + #[doc="```"] + // TODO: Maybe write parsing according to the spec? (Split the String) + (UserAgent, "User-Agent") => [String] +} #[test] fn test_format() { use std::borrow::ToOwned;