Skip to content

Commit 0961ee1

Browse files
committed
Merge branch 'master' into headers_encoding
2 parents ca704fc + 4cdea56 commit 0961ee1

File tree

6 files changed

+75
-55
lines changed

6 files changed

+75
-55
lines changed

.github/workflows/ci.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ name: CI
33
on: [push, pull_request]
44

55
env:
6-
minrust: 1.41.0
6+
minrust: 1.46.0
77

88
jobs:
99
test:

Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "headers"
3-
version = "0.3.4" # don't forget to update html_root_url
3+
version = "0.3.5" # don't forget to update html_root_url
44
description = "typed HTTP headers"
55
license = "MIT"
66
readme = "README.md"
@@ -25,7 +25,7 @@ itertools = "0.9"
2525
bytes = "1"
2626
mime = "0.3.14"
2727
sha-1 = "0.9"
28-
time = "0.1.34"
28+
httpdate = "1"
2929

3030
[features]
3131
nightly = []

src/common/access_control_allow_origin.rs

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
use std::convert::TryFrom;
2+
13
use super::origin::Origin;
24
use util::{IterExt, TryFromValues};
35
use HeaderValue;
@@ -25,9 +27,11 @@ use HeaderValue;
2527
/// ```
2628
/// # extern crate headers;
2729
/// use headers::AccessControlAllowOrigin;
30+
/// use std::convert::TryFrom;
2831
///
2932
/// let any_origin = AccessControlAllowOrigin::ANY;
3033
/// let null_origin = AccessControlAllowOrigin::NULL;
34+
/// let origin = AccessControlAllowOrigin::try_from("http://web-platform.test:8000");
3135
/// ```
3236
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
3337
pub struct AccessControlAllowOrigin(OriginOrAny);
@@ -60,6 +64,26 @@ impl AccessControlAllowOrigin {
6064
}
6165
}
6266

67+
impl TryFrom<&str> for AccessControlAllowOrigin {
68+
type Error = ::Error;
69+
70+
fn try_from(s: &str) -> Result<Self, ::Error> {
71+
let header_value = HeaderValue::from_str(s).map_err(|_| ::Error::invalid())?;
72+
let origin = OriginOrAny::try_from(&header_value)?;
73+
Ok(Self(origin))
74+
}
75+
}
76+
77+
impl TryFrom<&HeaderValue> for OriginOrAny {
78+
type Error = ::Error;
79+
80+
fn try_from(header_value: &HeaderValue) -> Result<Self, ::Error> {
81+
Origin::try_from_value(header_value)
82+
.map(OriginOrAny::Origin)
83+
.ok_or_else(::Error::invalid)
84+
}
85+
}
86+
6387
impl TryFromValues for OriginOrAny {
6488
fn try_from_values<'i, I>(values: &mut I) -> Result<Self, ::Error>
6589
where
@@ -89,12 +113,14 @@ impl<'a> From<&'a OriginOrAny> for HeaderValue {
89113

90114
#[cfg(test)]
91115
mod tests {
116+
92117
use super::super::{test_decode, test_encode};
93118
use super::*;
94119

95120
#[test]
96121
fn origin() {
97122
let s = "http://web-platform.test:8000";
123+
98124
let allow_origin = test_decode::<AccessControlAllowOrigin>(&[s]).unwrap();
99125
{
100126
let origin = allow_origin.origin().unwrap();
@@ -107,6 +133,22 @@ mod tests {
107133
assert_eq!(headers["access-control-allow-origin"], s);
108134
}
109135

136+
#[test]
137+
fn try_from_origin() {
138+
let s = "http://web-platform.test:8000";
139+
140+
let allow_origin = AccessControlAllowOrigin::try_from(s).unwrap();
141+
{
142+
let origin = allow_origin.origin().unwrap();
143+
assert_eq!(origin.scheme(), "http");
144+
assert_eq!(origin.hostname(), "web-platform.test");
145+
assert_eq!(origin.port(), Some(8000));
146+
}
147+
148+
let headers = test_encode(allow_origin);
149+
assert_eq!(headers["access-control-allow-origin"], s);
150+
}
151+
110152
#[test]
111153
fn any() {
112154
let allow_origin = test_decode::<AccessControlAllowOrigin>(&["*"]).unwrap();

src/common/origin.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
use std::fmt;
21
use std::convert::TryFrom;
2+
use std::fmt;
33

44
use bytes::Bytes;
55
use http::uri::{self, Authority, Scheme, Uri};

src/lib.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
#![deny(missing_debug_implementations)]
33
#![cfg_attr(test, deny(warnings))]
44
#![cfg_attr(all(test, feature = "nightly"), feature(test))]
5-
#![doc(html_root_url = "https://docs.rs/headers/0.3.4")]
5+
#![doc(html_root_url = "https://docs.rs/headers/0.3.5")]
66

77
//! # Typed HTTP Headers
88
//!
@@ -78,12 +78,12 @@ extern crate bitflags;
7878
extern crate bytes;
7979
extern crate headers_core;
8080
extern crate http;
81+
extern crate httpdate;
8182
extern crate itertools;
8283
extern crate mime;
8384
extern crate sha1;
8485
#[cfg(all(test, feature = "nightly"))]
8586
extern crate test;
86-
extern crate time;
8787

8888
pub use headers_core::{Error, Header};
8989

src/util/http_date.rs

Lines changed: 27 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
use std::fmt;
22
use std::str::FromStr;
3-
use std::time::{Duration, SystemTime, UNIX_EPOCH};
3+
use std::time::SystemTime;
44

55
use bytes::Bytes;
66
use http::header::HeaderValue;
7-
use time;
7+
use httpdate;
88

99
use super::IterExt;
1010

@@ -32,7 +32,7 @@ use super::IterExt;
3232
// HTTP-date, the sender MUST generate those timestamps in the
3333
// IMF-fixdate format.
3434
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
35-
pub(crate) struct HttpDate(time::Tm);
35+
pub(crate) struct HttpDate(httpdate::HttpDate);
3636

3737
impl HttpDate {
3838
pub(crate) fn from_val(val: &HeaderValue) -> Option<Self> {
@@ -74,96 +74,74 @@ impl<'a> From<&'a HttpDate> for HeaderValue {
7474
impl FromStr for HttpDate {
7575
type Err = Error;
7676
fn from_str(s: &str) -> Result<HttpDate, Error> {
77-
time::strptime(s, "%a, %d %b %Y %T %Z")
78-
.or_else(|_| time::strptime(s, "%A, %d-%b-%y %T %Z"))
79-
.or_else(|_| time::strptime(s, "%c"))
80-
.map(HttpDate)
81-
.map_err(|_| Error(()))
77+
Ok(HttpDate(s.parse().map_err(|_| Error(()))?))
8278
}
8379
}
8480

8581
impl fmt::Debug for HttpDate {
8682
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
87-
fmt::Display::fmt(&self.0.to_utc().rfc822(), f)
83+
fmt::Display::fmt(&self.0, f)
8884
}
8985
}
9086

9187
impl fmt::Display for HttpDate {
9288
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
93-
fmt::Display::fmt(&self.0.to_utc().rfc822(), f)
89+
fmt::Display::fmt(&self.0, f)
9490
}
9591
}
9692

9793
impl From<SystemTime> for HttpDate {
9894
fn from(sys: SystemTime) -> HttpDate {
99-
let tmspec = match sys.duration_since(UNIX_EPOCH) {
100-
Ok(dur) => {
101-
// subsec nanos always dropped
102-
time::Timespec::new(dur.as_secs() as i64, 0)
103-
}
104-
Err(err) => {
105-
let neg = err.duration();
106-
// subsec nanos always dropped
107-
time::Timespec::new(-(neg.as_secs() as i64), 0)
108-
}
109-
};
110-
HttpDate(time::at_utc(tmspec))
95+
HttpDate(sys.into())
11196
}
11297
}
11398

11499
impl From<HttpDate> for SystemTime {
115100
fn from(date: HttpDate) -> SystemTime {
116-
let spec = date.0.to_timespec();
117-
if spec.sec >= 0 {
118-
UNIX_EPOCH + Duration::new(spec.sec as u64, spec.nsec as u32)
119-
} else {
120-
UNIX_EPOCH - Duration::new(spec.sec as u64, spec.nsec as u32)
121-
}
101+
SystemTime::from(date.0)
122102
}
123103
}
124104

125105
#[cfg(test)]
126106
mod tests {
127107
use super::HttpDate;
128-
use time::Tm;
129-
130-
const NOV_07: HttpDate = HttpDate(Tm {
131-
tm_nsec: 0,
132-
tm_sec: 37,
133-
tm_min: 48,
134-
tm_hour: 8,
135-
tm_mday: 7,
136-
tm_mon: 10,
137-
tm_year: 94,
138-
tm_wday: 0,
139-
tm_isdst: 0,
140-
tm_yday: 0,
141-
tm_utcoff: 0,
142-
});
108+
109+
use std::time::{Duration, UNIX_EPOCH};
110+
111+
// The old tests had Sunday, but 1994-11-07 is a Monday.
112+
// See https://github.com/pyfisch/httpdate/pull/6#issuecomment-846881001
113+
fn nov_07() -> HttpDate {
114+
HttpDate((UNIX_EPOCH + Duration::new(784198117, 0)).into())
115+
}
116+
117+
#[test]
118+
fn test_display_is_imf_fixdate() {
119+
assert_eq!("Mon, 07 Nov 1994 08:48:37 GMT", &nov_07().to_string());
120+
}
143121

144122
#[test]
145123
fn test_imf_fixdate() {
146124
assert_eq!(
147-
"Sun, 07 Nov 1994 08:48:37 GMT".parse::<HttpDate>().unwrap(),
148-
NOV_07
125+
"Mon, 07 Nov 1994 08:48:37 GMT".parse::<HttpDate>().unwrap(),
126+
nov_07()
149127
);
150128
}
151129

152130
#[test]
153131
fn test_rfc_850() {
154132
assert_eq!(
155-
"Sunday, 07-Nov-94 08:48:37 GMT"
133+
"Monday, 07-Nov-94 08:48:37 GMT"
156134
.parse::<HttpDate>()
157135
.unwrap(),
158-
NOV_07
136+
nov_07()
159137
);
160138
}
161139

162140
#[test]
163141
fn test_asctime() {
164142
assert_eq!(
165-
"Sun Nov 7 08:48:37 1994".parse::<HttpDate>().unwrap(),
166-
NOV_07
143+
"Mon Nov 7 08:48:37 1994".parse::<HttpDate>().unwrap(),
144+
nov_07()
167145
);
168146
}
169147

0 commit comments

Comments
 (0)