From 8d0e5bc3027a1b0bddbd68b2b7fda9491eaa120a Mon Sep 17 00:00:00 2001 From: Pyfisch Date: Tue, 20 Jan 2015 13:04:42 +0100 Subject: [PATCH] refactor(headers): export all headers and utils directly under header Currently headers are exported at many places. For example you can access `Transfer-Encoding` header at `header`, `header::common` and `header::common::transfer_encoding`. Per discussion on IRC with @seanmonstar and @reem, all contents of headers will be exposed at `header` directly. Parsing utilities will be exposed at `header::parsing`. Header macros can now be used from other crates. This breaks much code using headers. It should use everything it needs directly from `header::`, encodings are exposed at `header::Encoding::`, connection options are exposed at `header::ConnectionOption`. --- examples/server.rs | 2 +- src/client/mod.rs | 4 +- src/client/request.rs | 14 +-- src/client/response.rs | 8 +- src/header/common/accept.rs | 18 +-- src/header/common/accept_encoding.rs | 10 +- .../common/access_control/allow_headers.rs | 17 ++- .../common/access_control/allow_methods.rs | 17 ++- .../common/access_control/allow_origin.rs | 14 ++- src/header/common/access_control/max_age.rs | 14 ++- src/header/common/access_control/mod.rs | 30 ++--- .../common/access_control/request_headers.rs | 16 ++- .../common/access_control/request_method.rs | 14 ++- src/header/common/allow.rs | 2 +- src/header/common/cache_control.rs | 3 +- src/header/common/connection.rs | 2 +- src/header/common/content_length.rs | 2 +- src/header/common/content_type.rs | 2 +- src/header/common/date.rs | 4 +- src/header/common/etag.rs | 2 +- src/header/common/expires.rs | 4 +- src/header/common/host.rs | 2 +- src/header/common/if_modified_since.rs | 4 +- src/header/common/last_modified.rs | 4 +- src/header/common/location.rs | 2 +- src/header/common/mod.rs | 118 ++++++------------ src/header/common/referer.rs | 2 +- src/header/common/transfer_encoding.rs | 55 +------- src/header/common/upgrade.rs | 2 +- src/header/common/user_agent.rs | 2 +- src/header/common/vary.rs | 2 +- src/header/mod.rs | 16 ++- src/header/{shared/util.rs => parsing.rs} | 33 +++++ src/header/shared/mod.rs | 27 +--- src/server/mod.rs | 5 +- src/server/request.rs | 6 +- src/server/response.rs | 18 ++- 37 files changed, 224 insertions(+), 273 deletions(-) rename src/header/{shared/util.rs => parsing.rs} (54%) diff --git a/examples/server.rs b/examples/server.rs index 2ab23d6d85..43e6040e67 100644 --- a/examples/server.rs +++ b/examples/server.rs @@ -6,7 +6,7 @@ use std::io::util::copy; use std::io::net::ip::Ipv4Addr; use hyper::{Get, Post}; -use hyper::header::common::ContentLength; +use hyper::header::ContentLength; use hyper::server::{Server, Request, Response}; use hyper::uri::RequestUri::AbsolutePath; diff --git a/src/client/mod.rs b/src/client/mod.rs index 43befdbca8..1e00868121 100644 --- a/src/client/mod.rs +++ b/src/client/mod.rs @@ -26,7 +26,7 @@ use url::UrlParser; use url::ParseError as UrlError; use header::{Headers, Header, HeaderFormat}; -use header::common::{ContentLength, Location}; +use header::{ContentLength, Location}; use method::Method; use net::{NetworkConnector, HttpConnector, ContextVerifier}; use status::StatusClass::Redirection; @@ -353,7 +353,7 @@ fn get_host_and_port(url: &Url) -> HttpResult<(String, Port)> { #[cfg(test)] mod tests { - use header::common::Server; + use header::Server; use super::{Client, RedirectPolicy}; use url::Url; diff --git a/src/client/request.rs b/src/client/request.rs index da3edba24c..8495db1be7 100644 --- a/src/client/request.rs +++ b/src/client/request.rs @@ -5,7 +5,7 @@ use url::Url; use method::{self, Method}; use header::Headers; -use header::common::{self, Host}; +use header::{self, Host}; use net::{NetworkStream, NetworkConnector, HttpConnector, Fresh, Streaming}; use http::{HttpWriter, LINE_ENDING}; use http::HttpWriter::{ThroughWriter, ChunkedWriter, SizedWriter, EmptyWriter}; @@ -95,7 +95,7 @@ impl Request { let mut chunked = true; let mut len = 0; - match self.headers.get::() { + match self.headers.get::() { Some(cl) => { chunked = false; len = **cl; @@ -105,18 +105,18 @@ impl Request { // cant do in match above, thanks borrowck if chunked { - let encodings = match self.headers.get_mut::() { - Some(&mut common::TransferEncoding(ref mut encodings)) => { + let encodings = match self.headers.get_mut::() { + Some(&mut header::TransferEncoding(ref mut encodings)) => { //TODO: check if chunked is already in encodings. use HashSet? - encodings.push(common::transfer_encoding::Encoding::Chunked); + encodings.push(header::Encoding::Chunked); false }, None => true }; if encodings { - self.headers.set::( - common::TransferEncoding(vec![common::transfer_encoding::Encoding::Chunked])) + self.headers.set::( + header::TransferEncoding(vec![header::Encoding::Chunked])) } } diff --git a/src/client/response.rs b/src/client/response.rs index 73150b7c2f..a93770d43f 100644 --- a/src/client/response.rs +++ b/src/client/response.rs @@ -3,8 +3,8 @@ use std::num::FromPrimitive; use std::io::{BufferedReader, IoResult}; use header; -use header::common::{ContentLength, TransferEncoding}; -use header::common::transfer_encoding::Encoding::Chunked; +use header::{ContentLength, TransferEncoding}; +use header::Encoding::Chunked; use net::{NetworkStream, HttpStream}; use http::{read_status_line, HttpReader, RawStatus}; use http::HttpReader::{SizedReader, ChunkedReader, EofReader}; @@ -100,8 +100,8 @@ mod tests { use std::io::BufferedReader; use header::Headers; - use header::common::TransferEncoding; - use header::common::transfer_encoding::Encoding; + use header::TransferEncoding; + use header::Encoding; use http::HttpReader::EofReader; use http::RawStatus; use mock::MockStream; diff --git a/src/header/common/accept.rs b/src/header/common/accept.rs index d5527824e7..0bbf7a79bc 100644 --- a/src/header/common/accept.rs +++ b/src/header/common/accept.rs @@ -1,7 +1,7 @@ use std::fmt; use header; -use header::shared; +use header::parsing; use mime; @@ -15,8 +15,8 @@ use mime; /// /// ``` /// # use hyper::header::Headers; -/// # use hyper::header::common::Accept; -/// # use hyper::header::shared::qitem; +/// # use hyper::header::Accept; +/// # use hyper::header::qitem; /// use hyper::mime::Mime; /// use hyper::mime::TopLevel::Text; /// use hyper::mime::SubLevel::{Html, Xml}; @@ -26,9 +26,9 @@ use mime; /// qitem(Mime(Text, Xml, vec![])) ])); /// ``` #[derive(Clone, PartialEq, Show)] -pub struct Accept(pub Vec>); +pub struct Accept(pub Vec>); -deref!(Accept => Vec>); +deref!(Accept => Vec>); impl header::Header for Accept { fn header_name(_: Option) -> &'static str { @@ -37,13 +37,13 @@ impl header::Header for Accept { fn parse_header(raw: &[Vec]) -> Option { // TODO: Return */* if no value is given. - shared::from_comma_delimited(raw).map(Accept) + parsing::from_comma_delimited(raw).map(Accept) } } impl header::HeaderFormat for Accept { fn fmt_header(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - shared::fmt_comma_delimited(fmt, &self[]) + parsing::fmt_comma_delimited(fmt, &self[]) } } @@ -53,7 +53,7 @@ bench_header!(bench, Accept, { vec![b"text/plain; q=0.5, text/html".to_vec()] }) fn test_parse_header_no_quality() { let a: Accept = header::Header::parse_header([b"text/plain; charset=utf-8".to_vec()].as_slice()).unwrap(); let b = Accept(vec![ - shared::QualityItem{item: mime::Mime(mime::TopLevel::Text, mime::SubLevel::Plain, vec![(mime::Attr::Charset, mime::Value::Utf8)]), quality: 1f32}, + header::QualityItem{item: mime::Mime(mime::TopLevel::Text, mime::SubLevel::Plain, vec![(mime::Attr::Charset, mime::Value::Utf8)]), quality: 1f32}, ]); assert_eq!(a, b); } @@ -62,7 +62,7 @@ fn test_parse_header_no_quality() { fn test_parse_header_with_quality() { let a: Accept = header::Header::parse_header([b"text/plain; charset=utf-8; q=0.5".to_vec()].as_slice()).unwrap(); let b = Accept(vec![ - shared::QualityItem{item: mime::Mime(mime::TopLevel::Text, mime::SubLevel::Plain, vec![(mime::Attr::Charset, mime::Value::Utf8)]), quality: 0.5f32}, + header::QualityItem{item: mime::Mime(mime::TopLevel::Text, mime::SubLevel::Plain, vec![(mime::Attr::Charset, mime::Value::Utf8)]), quality: 0.5f32}, ]); assert_eq!(a, b); } diff --git a/src/header/common/accept_encoding.rs b/src/header/common/accept_encoding.rs index 2e630f09b8..a67bf8c0b7 100644 --- a/src/header/common/accept_encoding.rs +++ b/src/header/common/accept_encoding.rs @@ -1,22 +1,22 @@ -use header::{self, shared}; +use header::{self, 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, Show)] -pub struct AcceptEncoding(pub Vec>); +pub struct AcceptEncoding(pub Vec>); impl_list_header!(AcceptEncoding, "Accept-Encoding", - Vec>); + Vec>); #[test] fn test_parse_header() { let a: AcceptEncoding = header::Header::parse_header([b"gzip;q=1.0, identity; q=0.5".to_vec()].as_slice()).unwrap(); let b = AcceptEncoding(vec![ - shared::QualityItem{item: shared::Gzip, quality: 1f32}, - shared::QualityItem{item: shared::Identity, quality: 0.5f32}, + QualityItem{item: Encoding::Gzip, quality: 1f32}, + QualityItem{item: Encoding::Identity, quality: 0.5f32}, ]); assert_eq!(a, b); } diff --git a/src/header/common/access_control/allow_headers.rs b/src/header/common/access_control/allow_headers.rs index 26a741b0e1..7ac934e7af 100644 --- a/src/header/common/access_control/allow_headers.rs +++ b/src/header/common/access_control/allow_headers.rs @@ -1,10 +1,17 @@ use std::fmt::{self}; use header; -use header::shared; -#[derive(Clone)] -struct AccessControlAllowHeaders(pub Vec); +/// The `Access-Control-Allow-Headers` response header, +/// part of [CORS](http://www.w3.org/TR/cors/). +/// +/// > The `Access-Control-Allow-Headers` header indicates, as part of the +/// > response to a preflight request, which header field names can be used +/// > during the actual request. +/// +/// Spec: www.w3.org/TR/cors/#access-control-allow-headers-response-header +#[derive(Clone, PartialEq, Show)] +pub struct AccessControlAllowHeaders(pub Vec); impl header::Header for AccessControlAllowHeaders { #[inline] @@ -13,13 +20,13 @@ impl header::Header for AccessControlAllowHeaders { } fn parse_header(raw: &[Vec]) -> Option { - shared::from_comma_delimited(raw).map(AccessControlAllowHeaders) + header::parsing::from_comma_delimited(raw).map(AccessControlAllowHeaders) } } impl header::HeaderFormat for AccessControlAllowHeaders { fn fmt_header(&self, f: &mut fmt::Formatter) -> fmt::Result { let AccessControlAllowHeaders(ref parts) = *self; - shared::fmt_comma_delimited(f, parts.as_slice()) + header::parsing::fmt_comma_delimited(f, parts.as_slice()) } } diff --git a/src/header/common/access_control/allow_methods.rs b/src/header/common/access_control/allow_methods.rs index cdd7189663..37b880040f 100644 --- a/src/header/common/access_control/allow_methods.rs +++ b/src/header/common/access_control/allow_methods.rs @@ -1,11 +1,18 @@ use std::fmt::{self}; use header; -use header::shared; use method; -#[derive(Clone)] -struct AccessControlAllowMethods(pub Vec); +/// The `Access-Control-Allow-Methods` response header, +/// part of [CORS](http://www.w3.org/TR/cors/). +/// +/// > The `Access-Control-Allow-Methods` header indicates, as part of the +/// > response to a preflight request, which methods can be used during the +/// > actual request. +/// +/// Spec: www.w3.org/TR/cors/#access-control-allow-methods-response-header +#[derive(Clone, PartialEq, Show)] +pub struct AccessControlAllowMethods(pub Vec); impl header::Header for AccessControlAllowMethods { #[inline] @@ -14,13 +21,13 @@ impl header::Header for AccessControlAllowMethods { } fn parse_header(raw: &[Vec]) -> Option { - shared::from_comma_delimited(raw).map(AccessControlAllowMethods) + header::parsing::from_comma_delimited(raw).map(AccessControlAllowMethods) } } impl header::HeaderFormat for AccessControlAllowMethods { fn fmt_header(&self, f: &mut fmt::Formatter) -> fmt::Result { let AccessControlAllowMethods(ref parts) = *self; - shared::fmt_comma_delimited(f, parts.as_slice()) + header::parsing::fmt_comma_delimited(f, parts.as_slice()) } } diff --git a/src/header/common/access_control/allow_origin.rs b/src/header/common/access_control/allow_origin.rs index 07f6750815..292cb367c5 100644 --- a/src/header/common/access_control/allow_origin.rs +++ b/src/header/common/access_control/allow_origin.rs @@ -5,9 +5,19 @@ use std::str; use header; -#[derive(Clone)] -enum AccessControlAllowOrigin { +/// The `Access-Control-Allow-Origin` response header, +/// part of [CORS](http://www.w3.org/TR/cors/). +/// +/// > The `Access-Control-Allow-Origin` header indicates whether a resource +/// > can be shared based by returning the value of the Origin request header, +/// > "*", or "null" in the response. +/// +/// Spec: www.w3.org/TR/cors/#access-control-allow-origin-response-header +#[derive(Clone, PartialEq, Show)] +pub enum AccessControlAllowOrigin { + /// Allow all origins AllowStar, + /// Allow one particular origin AllowOrigin(url::Url), } diff --git a/src/header/common/access_control/max_age.rs b/src/header/common/access_control/max_age.rs index 98b52b478d..84dcfc32db 100644 --- a/src/header/common/access_control/max_age.rs +++ b/src/header/common/access_control/max_age.rs @@ -1,10 +1,16 @@ use std::fmt; use header; -use header::shared; -#[derive(Clone)] -struct AccessControlMaxAge(pub u32); +/// The `Access-Control-Max-Age` response header, +/// part of [CORS](http://www.w3.org/TR/cors/). +/// +/// > The `Access-Control-Max-Age` header indicates how long the results of a +/// > preflight request can be cached in a preflight result cache. +/// +/// Spec: www.w3.org/TR/cors/#access-control-max-age-response-header +#[derive(Clone, Copy, PartialEq, Show)] +pub struct AccessControlMaxAge(pub u32); impl header::Header for AccessControlMaxAge { #[inline] @@ -13,7 +19,7 @@ impl header::Header for AccessControlMaxAge { } fn parse_header(raw: &[Vec]) -> Option { - shared::from_one_raw_str(raw).map(AccessControlMaxAge) + header::parsing::from_one_raw_str(raw).map(AccessControlMaxAge) } } diff --git a/src/header/common/access_control/mod.rs b/src/header/common/access_control/mod.rs index d8e6e21ffe..526e6f5526 100644 --- a/src/header/common/access_control/mod.rs +++ b/src/header/common/access_control/mod.rs @@ -1,17 +1,13 @@ -/// Exposes the AccessControlAllowHeaders header -pub mod allow_headers; - -/// Exposes the AccessControlAllowMethods header -pub mod allow_methods; - -/// Exposes the AccessControlAllowOrigin header -pub mod allow_origin; - -/// Exposes the AccessControlMaxAge header -pub mod max_age; - -/// Exposes the AccessControlRequestHeaders header -pub mod request_headers; - -/// Exposes the AccessControlRequestMethod header -pub mod request_method; +pub use self::allow_headers::AccessControlAllowHeaders; +pub use self::allow_methods::AccessControlAllowMethods; +pub use self::allow_origin::AccessControlAllowOrigin; +pub use self::max_age::AccessControlMaxAge; +pub use self::request_headers::AccessControlRequestHeaders; +pub use self::request_method::AccessControlRequestMethod; + +mod allow_headers; +mod allow_methods; +mod allow_origin; +mod max_age; +mod request_headers; +mod request_method; diff --git a/src/header/common/access_control/request_headers.rs b/src/header/common/access_control/request_headers.rs index 1aafea9845..9bf8593061 100644 --- a/src/header/common/access_control/request_headers.rs +++ b/src/header/common/access_control/request_headers.rs @@ -1,10 +1,16 @@ use std::fmt::{self}; use header; -use header::shared; -#[derive(Clone)] -struct AccessControlRequestHeaders(pub Vec); +/// The `Access-Control-Request-Headers` request header, +/// part of [CORS](http://www.w3.org/TR/cors/). +/// +/// > The `Access-Control-Request-Headers` header indicates which headers will +/// > be used in the actual request as part of the preflight request. +/// +/// Spec: www.w3.org/TR/cors/#access-control-request-headers-request-header +#[derive(Clone, PartialEq, Show)] +pub struct AccessControlRequestHeaders(pub Vec); impl header::Header for AccessControlRequestHeaders { #[inline] @@ -13,13 +19,13 @@ impl header::Header for AccessControlRequestHeaders { } fn parse_header(raw: &[Vec]) -> Option { - shared::from_comma_delimited(raw).map(AccessControlRequestHeaders) + header::parsing::from_comma_delimited(raw).map(AccessControlRequestHeaders) } } impl header::HeaderFormat for AccessControlRequestHeaders { fn fmt_header(&self, f: &mut fmt::Formatter) -> fmt::Result { let AccessControlRequestHeaders(ref parts) = *self; - shared::fmt_comma_delimited(f, parts.as_slice()) + header::parsing::fmt_comma_delimited(f, parts.as_slice()) } } diff --git a/src/header/common/access_control/request_method.rs b/src/header/common/access_control/request_method.rs index 4b5a774672..05c0c08000 100644 --- a/src/header/common/access_control/request_method.rs +++ b/src/header/common/access_control/request_method.rs @@ -1,11 +1,17 @@ use std::fmt; use header; -use header::shared; use method::Method; -#[derive(Clone)] -struct AccessControlRequestMethod(pub Method); +/// The `Access-Control-Request-Method` request header, +/// part of [CORS](http://www.w3.org/TR/cors/). +/// +/// > The `Access-Control-Request-Method` header indicates which method will be +/// > used in the actual request as part of the preflight request. +/// +/// Spec: www.w3.org/TR/cors/#access-control-request-method-request-header +#[derive(Clone, PartialEq, Show)] +pub struct AccessControlRequestMethod(pub Method); impl header::Header for AccessControlRequestMethod { #[inline] @@ -14,7 +20,7 @@ impl header::Header for AccessControlRequestMethod { } fn parse_header(raw: &[Vec]) -> Option { - shared::from_one_raw_str(raw).map(AccessControlRequestMethod) + header::parsing::from_one_raw_str(raw).map(AccessControlRequestMethod) } } diff --git a/src/header/common/allow.rs b/src/header/common/allow.rs index 666df2e8be..49b1d0c520 100644 --- a/src/header/common/allow.rs +++ b/src/header/common/allow.rs @@ -1,7 +1,7 @@ use header::{Header, HeaderFormat}; use method::Method; use std::fmt::{self}; -use header::shared::util::{from_comma_delimited, fmt_comma_delimited}; +use header::parsing::{from_comma_delimited, fmt_comma_delimited}; /// The `Allow` header. /// See also https://tools.ietf.org/html/rfc7231#section-7.4.1 diff --git a/src/header/common/cache_control.rs b/src/header/common/cache_control.rs index 8ea6ad253c..6b450011d8 100644 --- a/src/header/common/cache_control.rs +++ b/src/header/common/cache_control.rs @@ -1,7 +1,7 @@ use std::fmt; use std::str::FromStr; use header::{Header, HeaderFormat}; -use header::shared::util::{from_one_comma_delimited, fmt_comma_delimited}; +use header::parsing::{from_one_comma_delimited, fmt_comma_delimited}; /// The Cache-Control header. #[derive(PartialEq, Clone, Show)] @@ -163,4 +163,3 @@ mod tests { } bench_header!(normal, CacheControl, { vec![b"no-cache, private".to_vec(), b"max-age=100".to_vec()] }); - diff --git a/src/header/common/connection.rs b/src/header/common/connection.rs index 809c75ad23..c780f98e42 100644 --- a/src/header/common/connection.rs +++ b/src/header/common/connection.rs @@ -1,7 +1,7 @@ use header::{Header, HeaderFormat}; use std::fmt; use std::str::FromStr; -use header::shared::util::{from_comma_delimited, fmt_comma_delimited}; +use header::parsing::{from_comma_delimited, fmt_comma_delimited}; pub use self::ConnectionOption::{KeepAlive, Close, ConnectionHeader}; diff --git a/src/header/common/content_length.rs b/src/header/common/content_length.rs index 4b243eda21..fe1c380b3b 100644 --- a/src/header/common/content_length.rs +++ b/src/header/common/content_length.rs @@ -1,7 +1,7 @@ use std::fmt; use header::{Header, HeaderFormat}; -use header::shared::util::from_one_raw_str; +use header::parsing::from_one_raw_str; /// The `Content-Length` header. /// diff --git a/src/header/common/content_type.rs b/src/header/common/content_type.rs index 4cc2805ff8..d329210a2b 100644 --- a/src/header/common/content_type.rs +++ b/src/header/common/content_type.rs @@ -1,6 +1,6 @@ use header::{Header, HeaderFormat}; use std::fmt; -use header::shared::util::from_one_raw_str; +use header::parsing::from_one_raw_str; use mime::Mime; /// The `Content-Type` header. diff --git a/src/header/common/date.rs b/src/header/common/date.rs index d14ad23fed..3311f7d8cb 100644 --- a/src/header/common/date.rs +++ b/src/header/common/date.rs @@ -2,8 +2,8 @@ use std::fmt; use std::str::FromStr; use time::Tm; use header::{Header, HeaderFormat}; -use header::shared::util::from_one_raw_str; -use header::shared::time::tm_from_str; +use header::parsing::from_one_raw_str; +use header::parsing::tm_from_str; // Egh, replace as soon as something better than time::Tm exists. /// The `Date` header field. diff --git a/src/header/common/etag.rs b/src/header/common/etag.rs index fa53a7891f..b38cd0bb65 100644 --- a/src/header/common/etag.rs +++ b/src/header/common/etag.rs @@ -1,6 +1,6 @@ use header::{Header, HeaderFormat}; use std::fmt::{self}; -use header::shared::util::from_one_raw_str; +use header::parsing::from_one_raw_str; /// The `Etag` header. /// diff --git a/src/header/common/expires.rs b/src/header/common/expires.rs index eb1ae7f717..530ff1cf8c 100644 --- a/src/header/common/expires.rs +++ b/src/header/common/expires.rs @@ -2,8 +2,8 @@ use std::fmt; use std::str::FromStr; use time::Tm; use header::{Header, HeaderFormat}; -use header::shared::util::from_one_raw_str; -use header::shared::time::tm_from_str; +use header::parsing::from_one_raw_str; +use header::parsing::tm_from_str; /// The `Expires` header field. #[derive(Copy, PartialEq, Clone, Show)] diff --git a/src/header/common/host.rs b/src/header/common/host.rs index cb1ef9cd81..72c004b3a7 100644 --- a/src/header/common/host.rs +++ b/src/header/common/host.rs @@ -1,7 +1,7 @@ use header::{Header, HeaderFormat}; use Port; use std::fmt; -use header::shared::util::from_one_raw_str; +use header::parsing::from_one_raw_str; /// The `Host` header. /// diff --git a/src/header/common/if_modified_since.rs b/src/header/common/if_modified_since.rs index f826d385eb..321f5f7cc6 100644 --- a/src/header/common/if_modified_since.rs +++ b/src/header/common/if_modified_since.rs @@ -2,8 +2,8 @@ use std::fmt; use std::str::FromStr; use time::Tm; use header::{Header, HeaderFormat}; -use header::shared::util::from_one_raw_str; -use header::shared::time::tm_from_str; +use header::parsing::from_one_raw_str; +use header::parsing::tm_from_str; /// The `If-Modified-Since` header field. #[derive(Copy, PartialEq, Clone, Show)] diff --git a/src/header/common/last_modified.rs b/src/header/common/last_modified.rs index 2452e7d489..5d3719d55d 100644 --- a/src/header/common/last_modified.rs +++ b/src/header/common/last_modified.rs @@ -2,8 +2,8 @@ use std::fmt; use std::str::FromStr; use time::Tm; use header::{Header, HeaderFormat}; -use header::shared::util::from_one_raw_str; -use header::shared::time::tm_from_str; +use header::parsing::from_one_raw_str; +use header::parsing::tm_from_str; /// The `LastModified` header field. #[derive(Copy, PartialEq, Clone, Show)] diff --git a/src/header/common/location.rs b/src/header/common/location.rs index 28197c8037..237f5704da 100644 --- a/src/header/common/location.rs +++ b/src/header/common/location.rs @@ -1,6 +1,6 @@ use header::{Header, HeaderFormat}; use std::fmt; -use header::shared::util::from_one_raw_str; +use header::parsing::from_one_raw_str; /// The `Location` header. /// diff --git a/src/header/common/mod.rs b/src/header/common/mod.rs index e7bc451958..5cccd27dd5 100644 --- a/src/header/common/mod.rs +++ b/src/header/common/mod.rs @@ -6,30 +6,34 @@ //! strongly-typed theme, the [mime](http://seanmonstar.github.io/mime.rs) crate //! is used, such as `ContentType(pub Mime)`. +pub use self::access_control::*; pub use self::accept::Accept; pub use self::accept_encoding::AcceptEncoding; pub use self::allow::Allow; pub use self::authorization::Authorization; pub use self::cache_control::CacheControl; -pub use self::cookie::Cookies; pub use self::connection::Connection; pub use self::content_length::ContentLength; pub use self::content_type::ContentType; +pub use self::cookie::Cookies; pub use self::date::Date; pub use self::etag::Etag; pub use self::expires::Expires; pub use self::host::Host; -pub use self::last_modified::LastModified; pub use self::if_modified_since::IfModifiedSince; +pub use self::last_modified::LastModified; pub use self::location::Location; +pub use self::referer::Referer; +pub use self::server::Server; +pub use self::set_cookie::SetCookie; pub use self::transfer_encoding::TransferEncoding; pub use self::upgrade::Upgrade; pub use self::user_agent::UserAgent; pub use self::vary::Vary; -pub use self::server::Server; -pub use self::set_cookie::SetCookie; -pub use self::referer::Referer; +pub use self::connection::ConnectionOption; + +#[macro_export] macro_rules! bench_header( ($name:ident, $ty:ty, $value:expr) => { #[cfg(test)] @@ -59,6 +63,7 @@ macro_rules! bench_header( } ); +#[macro_export] macro_rules! deref( ($from:ty => $to:ty) => { impl ::std::ops::Deref for $from { @@ -77,6 +82,7 @@ macro_rules! deref( } ); +#[macro_export] macro_rules! impl_list_header( ($from:ident, $name:expr, $item:ty) => { deref!($from => $item); @@ -87,13 +93,13 @@ macro_rules! impl_list_header( } fn parse_header(raw: &[Vec]) -> Option<$from> { - $crate::header::shared::from_comma_delimited(raw).map($from) + $crate::header::parsing::from_comma_delimited(raw).map($from) } } impl header::HeaderFormat for $from { fn fmt_header(&self, fmt: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { - $crate::header::shared::fmt_comma_delimited(fmt, &self[]) + $crate::header::parsing::fmt_comma_delimited(fmt, &self[]) } } @@ -106,6 +112,7 @@ macro_rules! impl_list_header( } ); +#[macro_export] macro_rules! impl_header( ($from:ident, $name:expr, $item:ty) => { deref!($from => $item); @@ -116,7 +123,7 @@ macro_rules! impl_header( } fn parse_header(raw: &[Vec]) -> Option<$from> { - $crate::header::shared::from_one_raw_str(raw).map($from) + $crate::header::parsing::from_one_raw_str(raw).map($from) } } @@ -135,75 +142,28 @@ macro_rules! impl_header( } ); -/// Exposes the AccessControl* family of headers. -pub mod access_control; - -/// Exposes the Accept header. -pub mod accept; - -/// Exposes the AcceptEncoding header. -pub mod accept_encoding; - -/// Exposes the Allow header. -pub mod allow; - -/// Exposes the Authorization header. -pub mod authorization; - -/// Exposes the CacheControl header. -pub mod cache_control; - -/// Exposes the Cookie header. -pub mod cookie; - -/// Exposes the Connection header. -pub mod connection; - -/// Exposes the ContentLength header. -pub mod content_length; - -/// Exposes the ContentType header. -pub mod content_type; - -/// Exposes the Date header. -pub mod date; - -/// Exposes the Etag header. -pub mod etag; - -/// Exposes the Expires header. -pub mod expires; - -/// Exposes the Host header. -pub mod host; - -/// Exposes the LastModified header. -pub mod last_modified; - -/// Exposes the If-Modified-Since header. -pub mod if_modified_since; - -/// Exposes the Location header. -pub mod location; - -/// Exposes the Server header. -pub mod server; - -/// Exposes the Set-Cookie header. -pub mod set_cookie; - -/// Exposes the TransferEncoding header. -pub mod transfer_encoding; - -/// Exposes the Upgrade header. -pub mod upgrade; - -/// Exposes the UserAgent header. -pub mod user_agent; - -/// Exposes the Vary header. -pub mod vary; - -/// Exposes the Referer header -pub mod referer; +mod access_control; +mod accept; +mod accept_encoding; +mod allow; +mod authorization; +mod cache_control; +mod cookie; +mod connection; +mod content_length; +mod content_type; +mod date; +mod etag; +mod expires; +mod host; +mod last_modified; +mod if_modified_since; +mod location; +mod referer; +mod server; +mod set_cookie; +mod transfer_encoding; +mod upgrade; +mod user_agent; +mod vary; diff --git a/src/header/common/referer.rs b/src/header/common/referer.rs index f3ef197e5e..8eee7c7b1e 100644 --- a/src/header/common/referer.rs +++ b/src/header/common/referer.rs @@ -1,6 +1,6 @@ use header::{Header, HeaderFormat}; use std::fmt::{self, Show}; -use header::shared::util::from_one_raw_str; +use header::parsing::from_one_raw_str; /// The `Referer` header. /// diff --git a/src/header/common/transfer_encoding.rs b/src/header/common/transfer_encoding.rs index 625c1b3c0b..f06f6baf20 100644 --- a/src/header/common/transfer_encoding.rs +++ b/src/header/common/transfer_encoding.rs @@ -1,9 +1,7 @@ use header::{Header, HeaderFormat}; use std::fmt; -use std::str::FromStr; -use header::shared::util::{from_comma_delimited, fmt_comma_delimited}; - -use self::Encoding::{Chunked, Gzip, Deflate, Compress, EncodingExt}; +use header::Encoding; +use header::parsing::{from_comma_delimited, fmt_comma_delimited}; /// The `Transfer-Encoding` header. /// @@ -23,54 +21,6 @@ pub struct TransferEncoding(pub Vec); deref!(TransferEncoding => Vec); -/// A value to be used with the `Transfer-Encoding` header. -/// -/// Example: -/// -/// ``` -/// # use hyper::header::TransferEncoding; -/// # use hyper::header::transfer_encoding::Encoding::{Gzip, Chunked}; -/// # use hyper::header::Headers; -/// # let mut headers = Headers::new(); -/// headers.set(TransferEncoding(vec![Gzip, Chunked])); -#[derive(Clone, PartialEq, Show)] -pub enum Encoding { - /// The `chunked` encoding. - Chunked, - /// The `gzip` encoding. - Gzip, - /// The `deflate` encoding. - Deflate, - /// The `compress` encoding. - Compress, - /// Some other encoding that is less common, can be any String. - EncodingExt(String) -} - -impl fmt::String for Encoding { - fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - write!(fmt, "{}", match *self { - Chunked => "chunked", - Gzip => "gzip", - Deflate => "deflate", - Compress => "compress", - EncodingExt(ref s) => s.as_slice() - }) - } -} - -impl FromStr for Encoding { - fn from_str(s: &str) -> Option { - match s { - "chunked" => Some(Chunked), - "deflate" => Some(Deflate), - "gzip" => Some(Gzip), - "compress" => Some(Compress), - _ => Some(EncodingExt(s.to_string())) - } - } -} - impl Header for TransferEncoding { fn header_name(_: Option) -> &'static str { "Transfer-Encoding" @@ -89,4 +39,3 @@ impl HeaderFormat for TransferEncoding { 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/upgrade.rs b/src/header/common/upgrade.rs index 979737802c..992505fe95 100644 --- a/src/header/common/upgrade.rs +++ b/src/header/common/upgrade.rs @@ -1,7 +1,7 @@ use header::{Header, HeaderFormat}; use std::fmt; use std::str::FromStr; -use header::shared::util::{from_comma_delimited, fmt_comma_delimited}; +use header::parsing::{from_comma_delimited, fmt_comma_delimited}; use self::Protocol::{WebSocket, ProtocolExt}; diff --git a/src/header/common/user_agent.rs b/src/header/common/user_agent.rs index b49641e33b..5cc0d2fd67 100644 --- a/src/header/common/user_agent.rs +++ b/src/header/common/user_agent.rs @@ -1,6 +1,6 @@ use header::{Header, HeaderFormat}; use std::fmt; -use header::shared::util::from_one_raw_str; +use header::parsing::from_one_raw_str; /// The `User-Agent` header field. /// diff --git a/src/header/common/vary.rs b/src/header/common/vary.rs index 69ca3c5a95..d3d60b628e 100644 --- a/src/header/common/vary.rs +++ b/src/header/common/vary.rs @@ -1,6 +1,6 @@ use header::{Header, HeaderFormat}; use std::fmt::{self}; -use header::shared::util::{from_comma_delimited, fmt_comma_delimited, from_one_raw_str}; +use header::parsing::{from_comma_delimited, fmt_comma_delimited, from_one_raw_str}; use unicase::UniCase; /// The `Allow` header. diff --git a/src/header/mod.rs b/src/header/mod.rs index 6f21234f51..12a2f14f02 100644 --- a/src/header/mod.rs +++ b/src/header/mod.rs @@ -23,13 +23,12 @@ use unicase::UniCase; use {http, HttpResult}; +pub use self::shared::{Encoding, QualityItem, qitem}; pub use self::common::*; -pub use self::shared::*; -/// Common Headers -pub mod common; - -pub mod shared; +mod common; +mod shared; +pub mod parsing; type HeaderName = UniCase>; @@ -237,7 +236,7 @@ impl Headers { /// /// ``` /// # use hyper::header::Headers; - /// # use hyper::header::common::ContentType; + /// # use hyper::header::ContentType; /// # let mut headers = Headers::new(); /// let has_type = headers.has::(); /// ``` @@ -515,9 +514,8 @@ mod tests { use mime::TopLevel::Text; use mime::SubLevel::Plain; use unicase::UniCase; - use super::{Headers, Header, HeaderFormat}; - use super::common::{ContentLength, ContentType, Accept, Host}; - use super::shared::{QualityItem}; + use super::{Headers, Header, HeaderFormat, ContentLength, ContentType, + Accept, Host, QualityItem}; use test::Bencher; diff --git a/src/header/shared/util.rs b/src/header/parsing.rs similarity index 54% rename from src/header/shared/util.rs rename to src/header/parsing.rs index ab8b14fc7b..d42fde3285 100644 --- a/src/header/shared/util.rs +++ b/src/header/parsing.rs @@ -1,5 +1,7 @@ //! Utility functions for Header implementations. +extern crate time; + use std::str; use std::fmt; @@ -50,3 +52,34 @@ pub fn fmt_comma_delimited(fmt: &mut fmt::Formatter, parts: &[T] } Ok(()) } + +/// Get a Tm from HTTP date formats. +// Prior to 1995, there were three different formats commonly used by +// servers to communicate timestamps. For compatibility with old +// implementations, all three are defined here. The preferred format is +// a fixed-length and single-zone subset of the date and time +// specification used by the Internet Message Format [RFC5322]. +// +// HTTP-date = IMF-fixdate / obs-date +// +// An example of the preferred format is +// +// Sun, 06 Nov 1994 08:49:37 GMT ; IMF-fixdate +// +// Examples of the two obsolete formats are +// +// Sunday, 06-Nov-94 08:49:37 GMT ; obsolete RFC 850 format +// Sun Nov 6 08:49:37 1994 ; ANSI C's asctime() format +// +// A recipient that parses a timestamp value in an HTTP header field +// MUST accept all three HTTP-date formats. When a sender generates a +// header field that contains one or more timestamps defined as +// HTTP-date, the sender MUST generate those timestamps in the +// IMF-fixdate format. +pub fn tm_from_str(s: &str) -> Option { + time::strptime(s, "%a, %d %b %Y %T %Z").or_else(|_| { + time::strptime(s, "%A, %d-%b-%y %T %Z") + }).or_else(|_| { + time::strptime(s, "%c") + }).ok() +} diff --git a/src/header/shared/mod.rs b/src/header/shared/mod.rs index 7f4e488a25..85b62f0d8c 100644 --- a/src/header/shared/mod.rs +++ b/src/header/shared/mod.rs @@ -1,26 +1,5 @@ -//! Various functions, structs and enums useful for many headers. - pub use self::encoding::Encoding; -pub use self::encoding::Encoding::{ - Chunked, - Gzip, - Deflate, - Compress, - Identity, - EncodingExt}; - -pub use self::quality_item::QualityItem; -pub use self::quality_item::qitem; - -pub use self::time::tm_from_str; - -pub use self::util::{ - from_one_raw_str, - from_comma_delimited, - from_one_comma_delimited, - fmt_comma_delimited}; +pub use self::quality_item::{QualityItem, qitem}; -pub mod encoding; -pub mod quality_item; -pub mod time; -pub mod util; +mod encoding; +mod quality_item; diff --git a/src/server/mod.rs b/src/server/mod.rs index 3be3abce7a..26445803d6 100644 --- a/src/server/mod.rs +++ b/src/server/mod.rs @@ -13,8 +13,8 @@ pub use net::{Fresh, Streaming}; use HttpError::HttpIoError; use {HttpResult}; -use header::common::Connection; -use header::common::connection::{KeepAlive, Close}; +use header::Connection; +use header::ConnectionOption::{Close, KeepAlive}; use net::{NetworkListener, NetworkStream, NetworkAcceptor, HttpAcceptor, HttpListener}; use version::HttpVersion::{Http10, Http11}; @@ -183,4 +183,3 @@ impl Handler for F where F: Fn(Request, Response), F: Sync + Send { (*self)(req, res) } } - diff --git a/src/server/request.rs b/src/server/request.rs index 3ea817a9d6..c01472c732 100644 --- a/src/server/request.rs +++ b/src/server/request.rs @@ -8,8 +8,7 @@ use std::io::net::ip::SocketAddr; use {HttpResult}; use version::{HttpVersion}; use method::Method::{self, Get, Head}; -use header::Headers; -use header::common::{ContentLength, TransferEncoding}; +use header::{Headers, ContentLength, TransferEncoding}; use http::{read_request_line}; use http::HttpReader; use http::HttpReader::{SizedReader, ChunkedReader, EmptyReader}; @@ -74,8 +73,7 @@ impl<'a> Reader for Request<'a> { #[cfg(test)] mod tests { - use header::common::{Host, TransferEncoding}; - use header::common::transfer_encoding::Encoding; + use header::{Host, TransferEncoding, Encoding}; use mock::MockStream; use super::Request; diff --git a/src/server/response.rs b/src/server/response.rs index 9f44cd7c43..0a528f52c6 100644 --- a/src/server/response.rs +++ b/src/server/response.rs @@ -7,7 +7,6 @@ use std::io::IoResult; use time::now_utc; use header; -use header::common; use http::{CR, LF, LINE_ENDING, HttpWriter}; use http::HttpWriter::{ThroughWriter, ChunkedWriter, SizedWriter}; use status; @@ -70,15 +69,15 @@ impl<'a> Response<'a, Fresh> { debug!("writing head: {:?} {:?}", self.version, self.status); try!(write!(&mut self.body, "{} {}{}{}", self.version, self.status, CR as char, LF as char)); - if !self.headers.has::() { - self.headers.set(common::Date(now_utc())); + if !self.headers.has::() { + self.headers.set(header::Date(now_utc())); } let mut chunked = true; let mut len = 0; - match self.headers.get::() { + match self.headers.get::() { Some(cl) => { chunked = false; len = **cl; @@ -88,18 +87,18 @@ impl<'a> Response<'a, Fresh> { // cant do in match above, thanks borrowck if chunked { - let encodings = match self.headers.get_mut::() { - Some(&mut common::TransferEncoding(ref mut encodings)) => { + let encodings = match self.headers.get_mut::() { + Some(&mut header::TransferEncoding(ref mut encodings)) => { //TODO: check if chunked is already in encodings. use HashSet? - encodings.push(common::transfer_encoding::Encoding::Chunked); + encodings.push(header::Encoding::Chunked); false }, None => true }; if encodings { - self.headers.set::( - common::TransferEncoding(vec![common::transfer_encoding::Encoding::Chunked])) + self.headers.set::( + header::TransferEncoding(vec![header::Encoding::Chunked])) } } @@ -151,4 +150,3 @@ impl<'a> Writer for Response<'a, Streaming> { self.body.flush() } } -