diff --git a/src/header/common/date.rs b/src/header/common/date.rs index e0a9e58c..a829f6a2 100644 --- a/src/header/common/date.rs +++ b/src/header/common/date.rs @@ -2,31 +2,25 @@ use header::HttpDate; header! { /// `Date` header, defined in [RFC7231](http://tools.ietf.org/html/rfc7231#section-7.1.1.2) - /// + /// /// The `Date` header field represents the date and time at which the /// message was originated. - /// + /// /// # ABNF /// ```plain /// Date = HTTP-date /// ``` - /// + /// /// # Example values /// * `Tue, 15 Nov 1994 08:12:31 GMT` - /// + /// /// # Example /// ``` - /// # extern crate time; - /// # extern crate hyper; - /// # fn main() { - /// // extern crate time; - /// - /// use hyper::header::{Headers, Date, HttpDate}; - /// use time; - /// + /// use hyper::header::{Headers, Date}; + /// use std::time::SystemTime; + /// /// let mut headers = Headers::new(); - /// headers.set(Date(HttpDate(time::now()))); - /// # } + /// headers.set(Date(SystemTime::now().into())); /// ``` (Date, "Date") => [HttpDate] diff --git a/src/header/common/expires.rs b/src/header/common/expires.rs index 839798b2..eed05762 100644 --- a/src/header/common/expires.rs +++ b/src/header/common/expires.rs @@ -2,35 +2,30 @@ use header::HttpDate; header! { /// `Expires` header, defined in [RFC7234](http://tools.ietf.org/html/rfc7234#section-5.3) - /// + /// /// The `Expires` header field gives the date/time after which the /// response is considered stale. - /// + /// /// The presence of an Expires field does not imply that the original /// resource will change or cease to exist at, before, or after that /// time. - /// + /// /// # ABNF /// ```plain /// Expires = HTTP-date /// ``` - /// + /// /// # Example values /// * `Thu, 01 Dec 1994 16:00:00 GMT` - /// + /// /// # Example /// ``` - /// # extern crate hyper; - /// # extern crate time; - /// # fn main() { - /// // extern crate time; - /// - /// use hyper::header::{Headers, Expires, HttpDate}; - /// use time::{self, Duration}; - /// + /// use hyper::header::{Headers, Expires}; + /// use std::time::{SystemTime, Duration}; + /// /// let mut headers = Headers::new(); - /// headers.set(Expires(HttpDate(time::now() + Duration::days(1)))); - /// # } + /// let expiration = SystemTime::now() + Duration::from_secs(60 * 60 * 24); + /// headers.set(Expires(expiration.into())); /// ``` (Expires, "Expires") => [HttpDate] diff --git a/src/header/common/if_modified_since.rs b/src/header/common/if_modified_since.rs index 7a0aee2d..d00a3427 100644 --- a/src/header/common/if_modified_since.rs +++ b/src/header/common/if_modified_since.rs @@ -3,34 +3,29 @@ use header::HttpDate; header! { /// `If-Modified-Since` header, defined in /// [RFC7232](http://tools.ietf.org/html/rfc7232#section-3.3) - /// + /// /// The `If-Modified-Since` header field makes a GET or HEAD request /// method conditional on the selected representation's modification date /// being more recent than the date provided in the field-value. /// Transfer of the selected representation's data is avoided if that /// data has not changed. - /// + /// /// # ABNF /// ```plain /// If-Unmodified-Since = HTTP-date /// ``` - /// + /// /// # Example values /// * `Sat, 29 Oct 1994 19:43:31 GMT` - /// + /// /// # Example /// ``` - /// # extern crate hyper; - /// # extern crate time; - /// # fn main() { - /// // extern crate time; - /// - /// use hyper::header::{Headers, IfModifiedSince, HttpDate}; - /// use time::{self, Duration}; - /// + /// use hyper::header::{Headers, IfModifiedSince}; + /// use std::time::{SystemTime, Duration}; + /// /// let mut headers = Headers::new(); - /// headers.set(IfModifiedSince(HttpDate(time::now() - Duration::days(1)))); - /// # } + /// let modified = SystemTime::now() - Duration::from_secs(60 * 60 * 24); + /// headers.set(IfModifiedSince(modified.into())); /// ``` (IfModifiedSince, "If-Modified-Since") => [HttpDate] diff --git a/src/header/common/if_range.rs b/src/header/common/if_range.rs index 5380a6e5..a2f6098d 100644 --- a/src/header/common/if_range.rs +++ b/src/header/common/if_range.rs @@ -33,17 +33,12 @@ use header::{self, Header, Raw, EntityTag, HttpDate}; /// headers.set(IfRange::EntityTag(EntityTag::new(false, "xyzzy".to_owned()))); /// ``` /// ``` -/// # extern crate hyper; -/// # extern crate time; -/// # fn main() { -/// // extern crate time; -/// -/// use hyper::header::{Headers, IfRange, HttpDate}; -/// use time::{self, Duration}; +/// use hyper::header::{Headers, IfRange}; +/// use std::time::{SystemTime, Duration}; /// /// let mut headers = Headers::new(); -/// headers.set(IfRange::Date(HttpDate(time::now() - Duration::days(1)))); -/// # } +/// let fetched = SystemTime::now() - Duration::from_secs(60 * 60 * 24); +/// headers.set(IfRange::Date(fetched.into())); /// ``` #[derive(Clone, Debug, PartialEq)] pub enum IfRange { diff --git a/src/header/common/if_unmodified_since.rs b/src/header/common/if_unmodified_since.rs index 99124169..9226820f 100644 --- a/src/header/common/if_unmodified_since.rs +++ b/src/header/common/if_unmodified_since.rs @@ -3,34 +3,29 @@ use header::HttpDate; header! { /// `If-Unmodified-Since` header, defined in /// [RFC7232](http://tools.ietf.org/html/rfc7232#section-3.4) - /// + /// /// The `If-Unmodified-Since` header field makes the request method /// conditional on the selected representation's last modification date /// being earlier than or equal to the date provided in the field-value. /// This field accomplishes the same purpose as If-Match for cases where /// the user agent does not have an entity-tag for the representation. - /// + /// /// # ABNF /// ```plain /// If-Unmodified-Since = HTTP-date /// ``` - /// + /// /// # Example values /// * `Sat, 29 Oct 1994 19:43:31 GMT` - /// + /// /// # Example /// ``` - /// # extern crate hyper; - /// # extern crate time; - /// # fn main() { - /// // extern crate time; - /// - /// use hyper::header::{Headers, IfUnmodifiedSince, HttpDate}; - /// use time::{self, Duration}; - /// + /// use hyper::header::{Headers, IfUnmodifiedSince}; + /// use std::time::{SystemTime, Duration}; + /// /// let mut headers = Headers::new(); - /// headers.set(IfUnmodifiedSince(HttpDate(time::now() - Duration::days(1)))); - /// # } + /// let modified = SystemTime::now() - Duration::from_secs(60 * 60 * 24); + /// headers.set(IfUnmodifiedSince(modified.into())); /// ``` (IfUnmodifiedSince, "If-Unmodified-Since") => [HttpDate] diff --git a/src/header/common/last_modified.rs b/src/header/common/last_modified.rs index 24fa1c39..d607f856 100644 --- a/src/header/common/last_modified.rs +++ b/src/header/common/last_modified.rs @@ -3,33 +3,28 @@ use header::HttpDate; header! { /// `Last-Modified` header, defined in /// [RFC7232](http://tools.ietf.org/html/rfc7232#section-2.2) - /// + /// /// The `Last-Modified` header field in a response provides a timestamp /// indicating the date and time at which the origin server believes the /// selected representation was last modified, as determined at the /// conclusion of handling the request. - /// + /// /// # ABNF /// ```plain /// Expires = HTTP-date /// ``` - /// + /// /// # Example values /// * `Sat, 29 Oct 1994 19:43:31 GMT` - /// + /// /// # Example /// ``` - /// # extern crate hyper; - /// # extern crate time; - /// # fn main() { - /// // extern crate time; - /// - /// use hyper::header::{Headers, LastModified, HttpDate}; - /// use time::{self, Duration}; - /// + /// use hyper::header::{Headers, LastModified}; + /// use std::time::{SystemTime, Duration}; + /// /// let mut headers = Headers::new(); - /// headers.set(LastModified(HttpDate(time::now() - Duration::days(1)))); - /// # } + /// let modified = SystemTime::now() - Duration::from_secs(60 * 60 * 24); + /// headers.set(LastModified(modified.into())); /// ``` (LastModified, "Last-Modified") => [HttpDate] diff --git a/src/header/common/retry_after.rs b/src/header/common/retry_after.rs index 1a827596..ddc24549 100644 --- a/src/header/common/retry_after.rs +++ b/src/header/common/retry_after.rs @@ -35,11 +35,11 @@ // Version 2.0, January 2004 // http://www.apache.org/licenses/ +use std::fmt; +use std::time::Duration; + use header::{Header, Raw}; use header::shared::HttpDate; -use time; -use time::{Duration, Tm}; -use std::fmt; /// The `Retry-After` header. /// @@ -53,33 +53,23 @@ use std::fmt; /// /// # Examples /// ``` -/// # extern crate hyper; -/// # extern crate time; -/// # fn main() { -/// // extern crate time; -/// use time::{Duration}; +/// use std::time::Duration; /// use hyper::header::{Headers, RetryAfter}; /// /// let mut headers = Headers::new(); /// headers.set( -/// RetryAfter::Delay(Duration::seconds(300)) +/// RetryAfter::Delay(Duration::from_secs(300)) /// ); -/// # } /// ``` /// ``` -/// # extern crate hyper; -/// # extern crate time; -/// # fn main() { -/// // extern crate time; -/// use time; -/// use time::{Duration}; +/// use std::time::{SystemTime, Duration}; /// use hyper::header::{Headers, RetryAfter}; /// /// let mut headers = Headers::new(); +/// let date = SystemTime::now() + Duration::from_secs(300); /// headers.set( -/// RetryAfter::DateTime(time::now_utc() + Duration::seconds(300)) +/// RetryAfter::DateTime(date.into()) /// ); -/// # } /// ``` /// Retry-After header, defined in [RFC7231](http://tools.ietf.org/html/rfc7231#section-7.1.3) @@ -91,7 +81,7 @@ pub enum RetryAfter { Delay(Duration), /// Retry after the given DateTime - DateTime(Tm), + DateTime(HttpDate), } impl Header for RetryAfter { @@ -108,11 +98,11 @@ impl Header for RetryAfter { }; if let Ok(datetime) = utf8_str.parse::() { - return Ok(RetryAfter::DateTime(datetime.0)) + return Ok(RetryAfter::DateTime(datetime)) } - if let Ok(seconds) = utf8_str.parse::() { - return Ok(RetryAfter::Delay(Duration::seconds(seconds))); + if let Ok(seconds) = utf8_str.parse::() { + return Ok(RetryAfter::Delay(Duration::from_secs(seconds))); } Err(::Error::Header) @@ -130,16 +120,10 @@ impl fmt::Display for RetryAfter { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { RetryAfter::Delay(ref duration) => { - write!(f, "{}", duration.num_seconds()) + write!(f, "{}", duration.as_secs()) }, RetryAfter::DateTime(ref datetime) => { - // According to RFC7231, the sender of an HTTP-date must use the RFC1123 format. - // http://tools.ietf.org/html/rfc7231#section-7.1.1.1 - if let Ok(date_string) = time::strftime("%a, %d %b %Y %T GMT", datetime) { - write!(f, "{}", date_string) - } else { - Err(fmt::Error::default()) - } + fmt::Display::fmt(datetime, f) } } } @@ -147,9 +131,9 @@ impl fmt::Display for RetryAfter { #[cfg(test)] mod tests { + use std::time::Duration; use header::Header; use header::shared::HttpDate; - use time::{Duration}; use super::RetryAfter; @@ -162,7 +146,7 @@ mod tests { fn parse_delay() { let retry_after = RetryAfter::parse_header(&vec![b"1234".to_vec()].into()).unwrap(); - assert_eq!(RetryAfter::Delay(Duration::seconds(1234)), retry_after); + assert_eq!(RetryAfter::Delay(Duration::from_secs(1234)), retry_after); } macro_rules! test_retry_after_datetime { @@ -172,7 +156,7 @@ mod tests { let dt = "Sun, 06 Nov 1994 08:49:37 GMT".parse::().unwrap(); let retry_after = RetryAfter::parse_header(&vec![$bytes.to_vec()].into()).expect("parse_header ok"); - assert_eq!(RetryAfter::DateTime(dt.0), retry_after); + assert_eq!(RetryAfter::DateTime(dt), retry_after); } } } @@ -184,7 +168,7 @@ mod tests { #[test] fn hyper_headers_from_raw_delay() { let retry_after = RetryAfter::parse_header(&b"300".to_vec().into()).unwrap(); - assert_eq!(retry_after, RetryAfter::Delay(Duration::seconds(300))); + assert_eq!(retry_after, RetryAfter::Delay(Duration::from_secs(300))); } #[test] @@ -192,6 +176,6 @@ mod tests { let retry_after = RetryAfter::parse_header(&b"Sun, 06 Nov 1994 08:49:37 GMT".to_vec().into()).unwrap(); let expected = "Sun, 06 Nov 1994 08:49:37 GMT".parse::().unwrap(); - assert_eq!(retry_after, RetryAfter::DateTime(expected.0)); + assert_eq!(retry_after, RetryAfter::DateTime(expected)); } } diff --git a/src/header/common/warning.rs b/src/header/common/warning.rs index 451cf97e..48f01233 100644 --- a/src/header/common/warning.rs +++ b/src/header/common/warning.rs @@ -33,7 +33,7 @@ use header::parsing::from_one_raw_str; /// # Examples /// ``` /// use hyper::header::{Headers, Warning}; -/// +/// /// let mut headers = Headers::new(); /// headers.set( /// Warning{ @@ -46,7 +46,7 @@ use header::parsing::from_one_raw_str; /// ``` /// ``` /// use hyper::header::{Headers, HttpDate, Warning}; -/// +/// /// let mut headers = Headers::new(); /// headers.set( /// Warning{ @@ -58,21 +58,18 @@ use header::parsing::from_one_raw_str; /// ); /// ``` /// ``` -/// # extern crate hyper; -/// # extern crate time; -/// # fn main() { -/// use hyper::header::{Headers, HttpDate, Warning}; -/// +/// use std::time::SystemTime; +/// use hyper::header::{Headers, Warning}; +/// /// let mut headers = Headers::new(); /// headers.set( /// Warning{ /// code: 199, /// agent: "api.hyper.rs".to_owned(), /// text: "Deprecated".to_owned(), -/// date: Some(HttpDate(time::now())) +/// date: Some(SystemTime::now().into()) /// } /// ); -/// # } /// ``` #[derive(PartialEq, Clone, Debug)] pub struct Warning { diff --git a/src/header/shared/httpdate.rs b/src/header/shared/httpdate.rs index 1a2dee81..a88cd21f 100644 --- a/src/header/shared/httpdate.rs +++ b/src/header/shared/httpdate.rs @@ -1,10 +1,10 @@ -use std::str::FromStr; use std::fmt::{self, Display}; +use std::str::FromStr; +use std::time::{Duration, SystemTime, UNIX_EPOCH}; use time; -/// A `time::Time` with HTTP formatting and parsing -/// +/// A timestamp with HTTP formatting and parsing // 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 @@ -28,7 +28,7 @@ use time; // HTTP-date, the sender MUST generate those timestamps in the // IMF-fixdate format. #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)] -pub struct HttpDate(pub time::Tm); +pub struct HttpDate(time::Tm); impl FromStr for HttpDate { type Err = ::Error; @@ -50,6 +50,32 @@ impl Display for HttpDate { } } +impl From for HttpDate { + fn from(sys: SystemTime) -> HttpDate { + let tmspec = match sys.duration_since(UNIX_EPOCH) { + Ok(dur) => { + time::Timespec::new(dur.as_secs() as i64, dur.subsec_nanos() as i32) + }, + Err(err) => { + let neg = err.duration(); + time::Timespec::new(-(neg.as_secs() as i64), -(neg.subsec_nanos() as i32)) + }, + }; + HttpDate(time::at_utc(tmspec)) + } +} + +impl From for SystemTime { + fn from(date: HttpDate) -> SystemTime { + let spec = date.0.to_timespec(); + if spec.sec >= 0 { + UNIX_EPOCH + Duration::new(spec.sec as u64, spec.nsec as u32) + } else { + UNIX_EPOCH - Duration::new(spec.sec as u64, spec.nsec as u32) + } + } +} + #[cfg(test)] mod tests { use time::Tm; diff --git a/src/http/h1/parse.rs b/src/http/h1/parse.rs index dc7e6a00..8a952099 100644 --- a/src/http/h1/parse.rs +++ b/src/http/h1/parse.rs @@ -1,5 +1,6 @@ use std::borrow::Cow; use std::fmt::{self, Write}; +use std::time::SystemTime; use httparse; use bytes::{BytesMut, Bytes}; @@ -94,7 +95,7 @@ impl Http1Transaction for ServerTransaction { trace!("writing head: {:?}", head); if !head.headers.has::() { - head.headers.set(header::Date(header::HttpDate(::time::now_utc()))); + head.headers.set(header::Date(SystemTime::now().into())); } let mut is_chunked = true;