refactor(header): change HttpDate to opaque over SystemTime
				
					
				
			This removes the need for someone to use the `time` crate to create a date compatible with HTTP headers. It now works with the `SystemTime` type from the standard library. BREAKING CHANGE: `HttpDate` no longer has public fields. Convert between `HttpDate` and `SystemTime` as needed.
This commit is contained in:
		| @@ -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] | ||||
|  | ||||
|   | ||||
| @@ -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] | ||||
|  | ||||
|   | ||||
| @@ -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] | ||||
|  | ||||
|   | ||||
| @@ -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 { | ||||
|   | ||||
| @@ -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] | ||||
|  | ||||
|   | ||||
| @@ -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] | ||||
|  | ||||
|   | ||||
| @@ -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::<HttpDate>() { | ||||
|                 return Ok(RetryAfter::DateTime(datetime.0)) | ||||
|                 return Ok(RetryAfter::DateTime(datetime)) | ||||
|             } | ||||
|  | ||||
|             if let Ok(seconds) = utf8_str.parse::<i64>() { | ||||
|                 return Ok(RetryAfter::Delay(Duration::seconds(seconds))); | ||||
|             if let Ok(seconds) = utf8_str.parse::<u64>() { | ||||
|                 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::<HttpDate>().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::<HttpDate>().unwrap(); | ||||
|  | ||||
|         assert_eq!(retry_after, RetryAfter::DateTime(expected.0)); | ||||
|         assert_eq!(retry_after, RetryAfter::DateTime(expected)); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -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 { | ||||
|   | ||||
		Reference in New Issue
	
	Block a user