Skip to content

Commit 7d64ffc

Browse files
authored
Merge pull request #47 from yoshuawuyts/client-date-header
Add Date header as necessary
2 parents d127c31 + e7d12be commit 7d64ffc

File tree

8 files changed

+93
-28
lines changed

8 files changed

+93
-28
lines changed

src/client.rs

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,15 @@ use async_std::prelude::*;
55
use async_std::task::{Context, Poll};
66
use futures_core::ready;
77
use http_types::{
8-
headers::{HeaderName, HeaderValue, CONTENT_LENGTH, TRANSFER_ENCODING},
8+
headers::{HeaderName, HeaderValue, CONTENT_LENGTH, DATE, TRANSFER_ENCODING},
99
Body, Request, Response, StatusCode,
1010
};
1111

1212
use std::pin::Pin;
1313
use std::str::FromStr;
1414

1515
use crate::chunked::ChunkedDecoder;
16+
use crate::date::fmt_http_date;
1617
use crate::error::HttpError;
1718
use crate::{Exception, MAX_HEADERS};
1819

@@ -77,6 +78,12 @@ pub async fn encode(req: Request) -> Result<Encoder, std::io::Error> {
7778
// See: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Transfer-Encoding
7879
// https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Trailer
7980
}
81+
82+
let date = fmt_http_date(std::time::SystemTime::now());
83+
buf.write_all(b"date: ").await?;
84+
buf.write_all(date.as_bytes()).await?;
85+
buf.write_all(b"\r\n").await?;
86+
8087
for (header, values) in req.iter() {
8188
for value in values.iter() {
8289
let val = format!("{}: {}\r\n", header, value);
@@ -90,7 +97,7 @@ pub async fn encode(req: Request) -> Result<Encoder, std::io::Error> {
9097
Ok(Encoder::new(buf, req))
9198
}
9299

93-
/// Decode an HTTP respons on the client.
100+
/// Decode an HTTP response on the client.
94101
pub async fn decode<R>(reader: R) -> Result<Response, Exception>
95102
where
96103
R: Read + Unpin + Send + Sync + 'static,
@@ -136,6 +143,11 @@ where
136143
res.insert_header(name, value)?;
137144
}
138145

146+
if res.header(&DATE).is_none() {
147+
let date = fmt_http_date(std::time::SystemTime::now());
148+
res.insert_header(DATE, &format!("date: {}\r\n", date)[..])?;
149+
}
150+
139151
let content_length = res.header(&CONTENT_LENGTH);
140152
let transfer_encoding = res.header(&TRANSFER_ENCODING);
141153

tests/client.rs

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
use crate::common::{fixture_path, munge_date};
2+
use async_h1::client;
3+
use async_std::fs::File;
4+
use async_std::io::SeekFrom;
5+
use async_std::prelude::*;
6+
use http_types::{headers, Method, Request};
7+
use url::Url;
8+
9+
mod common;
10+
11+
#[async_std::test]
12+
async fn test_encode_request_add_date() {
13+
let mut request_fixture = File::open(fixture_path("fixtures/client-request1.txt"))
14+
.await
15+
.unwrap();
16+
let mut expected = String::new();
17+
request_fixture.read_to_string(&mut expected).await.unwrap();
18+
19+
let url = Url::parse("http://example.com").unwrap();
20+
let req = Request::new(Method::Get, url);
21+
22+
let mut encoded_req = client::encode(req).await.unwrap();
23+
24+
let mut actual = String::new();
25+
encoded_req.read_to_string(&mut actual).await.unwrap();
26+
27+
munge_date(&mut expected, &mut actual);
28+
29+
pretty_assertions::assert_eq!(actual, expected);
30+
}
31+
32+
#[async_std::test]
33+
async fn test_response_no_date() {
34+
let mut response_fixture = File::open(fixture_path("fixtures/response-no-date.txt"))
35+
.await
36+
.unwrap();
37+
response_fixture.seek(SeekFrom::Start(0)).await.unwrap();
38+
39+
let res = client::decode(response_fixture).await.unwrap();
40+
41+
pretty_assertions::assert_eq!(res.header(&headers::DATE).is_some(), true);
42+
}

tests/common/mod.rs

Lines changed: 18 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -70,29 +70,32 @@ impl TestCase {
7070
assert!(!expected.is_empty(), "Missing expected fixture");
7171

7272
// munge actual and expected so that we don't rely on dates matching exactly
73-
match expected.find("{DATE}") {
74-
Some(i) => {
75-
expected.replace_range(i..i + 6, "");
76-
match expected.get(i..i + 1) {
77-
Some(byte) => {
78-
let j = actual[i..].find(byte).expect("Byte not found");
79-
actual.replace_range(i..i + j, "");
80-
}
81-
None => expected.replace_range(i.., ""),
82-
}
83-
}
84-
None => {}
85-
}
86-
73+
munge_date(&mut expected, &mut actual);
8774
pretty_assertions::assert_eq!(actual, expected);
8875
}
8976
}
9077

91-
fn fixture_path(relative_path: &str) -> PathBuf {
78+
pub(crate) fn fixture_path(relative_path: &str) -> PathBuf {
9279
let directory: PathBuf = env!("CARGO_MANIFEST_DIR").into();
9380
directory.join("tests").join(relative_path)
9481
}
9582

83+
pub(crate) fn munge_date(expected: &mut String, actual: &mut String) {
84+
match expected.find("{DATE}") {
85+
Some(i) => {
86+
expected.replace_range(i..i + 6, "");
87+
match expected.get(i..i + 1) {
88+
Some(byte) => {
89+
let j = actual[i..].find(byte).expect("Byte not found");
90+
actual.replace_range(i..i + j, "");
91+
}
92+
None => expected.replace_range(i.., ""),
93+
}
94+
}
95+
None => {}
96+
}
97+
}
98+
9699
impl Read for TestCase {
97100
fn poll_read(
98101
self: Pin<&mut Self>,

tests/fixtures/client-request1.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
GET / HTTP/1.1
2+
content-length: 0
3+
date: {DATE}
4+
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
GET / HTTP/1.1
2-
Host: example.com
3-
User-Agent: curl/7.54.0
2+
host: example.com
3+
user-agent: curl/7.54.0
44

tests/fixtures/request-chunked-echo.txt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
GET / HTTP/1.1
2-
Host: example.com
3-
User-Agent: curl/7.54.0
4-
Content-Type: text/plain
5-
Transfer-Encoding: chunked
2+
host: example.com
3+
user-agent: curl/7.54.0
4+
content-type: text/plain
5+
transfer-encoding: chunked
66

77
7
88
Mozilla

tests/fixtures/request1.txt

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
POST / HTTP/1.1
2-
Host: localhost:8080
3-
User-Agent: curl/7.54.0
4-
Accept: */*
5-
Content-Length: 2
6-
Content-Type: application/x-www-form-urlencoded
2+
host: localhost:8080
3+
user-agent: curl/7.54.0
4+
accept: */*
5+
content-length: 2
6+
content-type: application/x-www-form-urlencoded
77

tests/fixtures/response-no-date.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
HTTP/1.1 200 OK
2+
transfer-encoding: chunked
3+
content-type: text/plain
4+

0 commit comments

Comments
 (0)