Skip to content

Commit 37ec724

Browse files
committed
fix(http2): add Date header if not present for HTTP2 server responses
1 parent 3e12bcc commit 37ec724

File tree

5 files changed

+149
-36
lines changed

5 files changed

+149
-36
lines changed

src/proto/h1/date.rs

+10
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ use std::cell::RefCell;
22
use std::fmt::{self, Write};
33
use std::str;
44

5+
use http::header::HeaderValue;
56
use time::{self, Duration};
67

78
// "Sun, 06 Nov 1994 08:49:37 GMT".len()
@@ -19,6 +20,15 @@ pub fn update() {
1920
})
2021
}
2122

23+
pub(crate) fn update_and_header_value() -> HeaderValue {
24+
CACHED.with(|cache| {
25+
let mut cache = cache.borrow_mut();
26+
cache.check();
27+
HeaderValue::from_bytes(cache.buffer())
28+
.expect("Date format should be valid HeaderValue")
29+
})
30+
}
31+
2232
struct CachedDate {
2333
bytes: [u8; DATE_VALUE_LENGTH],
2434
pos: usize,

src/proto/h1/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ pub use self::io::Cursor; //TODO: move out of h1::io
1111
pub use self::io::MINIMUM_MAX_BUFFER_SIZE;
1212

1313
mod conn;
14-
mod date;
14+
pub(super) mod date;
1515
mod decode;
1616
pub(crate) mod dispatch;
1717
mod encode;

src/proto/h2/server.rs

+9
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,15 @@ where
193193
let (head, body) = res.into_parts();
194194
let mut res = ::http::Response::from_parts(head, ());
195195
super::strip_connection_headers(res.headers_mut(), false);
196+
197+
// set Date header if it isn't already set...
198+
res
199+
.headers_mut()
200+
.entry(::http::header::DATE)
201+
.expect("DATE is a valid HeaderName")
202+
.or_insert_with(::proto::h1::date::update_and_header_value);
203+
204+
// automatically set Content-Length from body...
196205
if let Some(len) = body.content_length() {
197206
headers::set_content_length_if_missing(res.headers_mut(), len);
198207
}

tests/integration.rs

+24
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@ t! {
1111
;
1212
response:
1313
status: 200,
14+
headers: {
15+
"date" => SOME,
16+
},
1417
;
1518
server:
1619
request:
@@ -37,6 +40,27 @@ t! {
3740
;
3841
}
3942

43+
t! {
44+
date_isnt_overwritten,
45+
client:
46+
request:
47+
;
48+
response:
49+
status: 200,
50+
headers: {
51+
"date" => "let me through",
52+
},
53+
;
54+
server:
55+
request:
56+
;
57+
response:
58+
headers: {
59+
"date" => "let me through",
60+
},
61+
;
62+
}
63+
4064
t! {
4165
get_body,
4266
client:

tests/support/mod.rs

+105-35
Original file line numberDiff line numberDiff line change
@@ -95,21 +95,21 @@ macro_rules! t {
9595
fn $name() {
9696
let c = vec![$((
9797
__CReq {
98-
$($c_req_prop: __internal_req_res_prop!($c_req_prop: $c_req_val),)*
98+
$($c_req_prop: __internal_map_prop!($c_req_prop: $c_req_val),)*
9999
..Default::default()
100100
},
101101
__CRes {
102-
$($c_res_prop: __internal_req_res_prop!($c_res_prop: $c_res_val),)*
102+
$($c_res_prop: __internal_eq_prop!($c_res_prop: $c_res_val),)*
103103
..Default::default()
104104
}
105105
),)*];
106106
let s = vec![$((
107107
__SReq {
108-
$($s_req_prop: __internal_req_res_prop!($s_req_prop: $s_req_val),)*
108+
$($s_req_prop: __internal_eq_prop!($s_req_prop: $s_req_val),)*
109109
..Default::default()
110110
},
111111
__SRes {
112-
$($s_res_prop: __internal_req_res_prop!($s_res_prop: $s_res_val),)*
112+
$($s_res_prop: __internal_map_prop!($s_res_prop: $s_res_val),)*
113113
..Default::default()
114114
}
115115
),)*];
@@ -157,64 +157,140 @@ macro_rules! t {
157157
);
158158
}
159159

160-
macro_rules! __internal_req_res_prop {
161-
(method: $prop_val:expr) => (
162-
$prop_val
163-
);
164-
(status: $prop_val:expr) => (
165-
StatusCode::from_u16($prop_val).expect("status code")
166-
);
160+
macro_rules! __internal_map_prop {
167161
(headers: $map:tt) => ({
168162
#[allow(unused_mut)]
169163
{
170164
let mut headers = HeaderMap::new();
171-
__internal_headers!(headers, $map);
165+
__internal_headers_map!(headers, $map);
166+
headers
167+
}
168+
});
169+
($name:tt: $val:tt) => ({
170+
__internal_req_res_prop!($name: $val)
171+
});
172+
}
173+
174+
macro_rules! __internal_eq_prop {
175+
(headers: $map:tt) => ({
176+
#[allow(unused_mut)]
177+
{
178+
let mut headers = Vec::new();
179+
__internal_headers_eq!(headers, $map);
172180
headers
173181
}
174182
});
183+
($name:tt: $val:tt) => ({
184+
__internal_req_res_prop!($name: $val)
185+
});
186+
}
187+
188+
macro_rules! __internal_req_res_prop {
189+
(method: $prop_val:expr) => (
190+
$prop_val
191+
);
192+
(status: $prop_val:expr) => (
193+
StatusCode::from_u16($prop_val).expect("status code")
194+
);
175195
($prop_name:ident: $prop_val:expr) => (
176196
From::from($prop_val)
177197
)
178198
}
179199

180-
macro_rules! __internal_headers {
200+
macro_rules! __internal_headers_map {
181201
($headers:ident, { $($name:expr => $val:expr,)* }) => {
182202
$(
183203
$headers.insert($name, $val.to_string().parse().expect("header value"));
184204
)*
185205
}
186206
}
187207

188-
#[derive(Clone, Debug, Default)]
208+
macro_rules! __internal_headers_eq {
209+
(@pat $name: expr, $pat:pat) => {
210+
::std::sync::Arc::new(move |__hdrs: &::hyper::HeaderMap| {
211+
match __hdrs.get($name) {
212+
$pat => (),
213+
other => panic!("headers[{}] was not {}: {:?}", stringify!($name), stringify!($pat), other),
214+
}
215+
}) as ::std::sync::Arc<Fn(&::hyper::HeaderMap) + Send + Sync>
216+
};
217+
(@val $name: expr, NONE) => {
218+
__internal_headers_eq!(@pat $name, None);
219+
};
220+
(@val $name: expr, SOME) => {
221+
__internal_headers_eq!(@pat $name, Some(_));
222+
};
223+
(@val $name: expr, $val:expr) => ({
224+
let __val = Option::from($val);
225+
::std::sync::Arc::new(move |__hdrs: &::hyper::HeaderMap| {
226+
if let Some(ref val) = __val {
227+
assert_eq!(__hdrs.get($name).expect(stringify!($name)), val.to_string().as_str(), stringify!($name));
228+
} else {
229+
assert_eq!(__hdrs.get($name), None, stringify!($name));
230+
}
231+
}) as ::std::sync::Arc<Fn(&::hyper::HeaderMap) + Send + Sync>
232+
});
233+
($headers:ident, { $($name:expr => $val:tt,)* }) => {
234+
$(
235+
$headers.push(__internal_headers_eq!(@val $name, $val));
236+
)*
237+
}
238+
}
239+
240+
#[derive(Clone, Debug)]
189241
pub struct __CReq {
190242
pub method: &'static str,
191243
pub uri: &'static str,
192244
pub headers: HeaderMap,
193245
pub body: Vec<u8>,
194246
}
195247

196-
#[derive(Clone, Debug, Default)]
248+
impl Default for __CReq {
249+
fn default() -> __CReq {
250+
__CReq {
251+
method: "GET",
252+
uri: "/",
253+
headers: HeaderMap::new(),
254+
body: Vec::new(),
255+
}
256+
}
257+
}
258+
259+
#[derive(Clone, Default)]
197260
pub struct __CRes {
198261
pub status: hyper::StatusCode,
199262
pub body: Vec<u8>,
200-
pub headers: HeaderMap,
263+
pub headers: __HeadersEq,
201264
}
202265

203-
#[derive(Clone, Debug, Default)]
266+
#[derive(Clone)]
204267
pub struct __SReq {
205268
pub method: &'static str,
206269
pub uri: &'static str,
207-
pub headers: HeaderMap,
270+
pub headers: __HeadersEq,
208271
pub body: Vec<u8>,
209272
}
210273

274+
impl Default for __SReq {
275+
fn default() -> __SReq {
276+
__SReq {
277+
method: "GET",
278+
uri: "/",
279+
headers: Vec::new(),
280+
body: Vec::new(),
281+
}
282+
}
283+
}
284+
211285
#[derive(Clone, Debug, Default)]
212286
pub struct __SRes {
213287
pub status: hyper::StatusCode,
214288
pub body: Vec<u8>,
215289
pub headers: HeaderMap,
216290
}
217291

292+
pub type __HeadersEq = Vec<Arc<Fn(&HeaderMap) + Send + Sync>>;
293+
218294
pub struct __TestConfig {
219295
pub client_version: usize,
220296
pub client_msgs: Vec<(__CReq, __CRes)>,
@@ -257,20 +333,17 @@ pub fn __run_test(cfg: __TestConfig) {
257333
.unwrap()
258334
.remove(0);
259335

260-
assert_eq!(req.uri().path(), sreq.uri);
261-
assert_eq!(req.method(), &sreq.method);
262-
assert_eq!(req.version(), version);
263-
for (name, value) in &sreq.headers {
264-
assert_eq!(
265-
req.headers()[name],
266-
value
267-
);
336+
assert_eq!(req.uri().path(), sreq.uri, "client path");
337+
assert_eq!(req.method(), &sreq.method, "client method");
338+
assert_eq!(req.version(), version, "client version");
339+
for func in &sreq.headers {
340+
func(&req.headers());
268341
}
269342
let sbody = sreq.body;
270343
req.into_body()
271344
.concat2()
272345
.map(move |body| {
273-
assert_eq!(body.as_ref(), sbody.as_slice());
346+
assert_eq!(body.as_ref(), sbody.as_slice(), "client body");
274347

275348
let mut res = Response::builder()
276349
.status(sres.status)
@@ -339,18 +412,15 @@ pub fn __run_test(cfg: __TestConfig) {
339412

340413
client.request(req)
341414
.and_then(move |res| {
342-
assert_eq!(res.status(), cstatus);
343-
assert_eq!(res.version(), version);
344-
for (name, value) in &cheaders {
345-
assert_eq!(
346-
res.headers()[name],
347-
value
348-
);
415+
assert_eq!(res.status(), cstatus, "server status");
416+
assert_eq!(res.version(), version, "server version");
417+
for func in &cheaders {
418+
func(&res.headers());
349419
}
350420
res.into_body().concat2()
351421
})
352422
.map(move |body| {
353-
assert_eq!(body.as_ref(), cbody.as_slice());
423+
assert_eq!(body.as_ref(), cbody.as_slice(), "server body");
354424
})
355425
.map_err(|e| panic!("client error: {}", e))
356426
});

0 commit comments

Comments
 (0)