Skip to content

Commit b7b70c8

Browse files
authored
Merge branch 'master' into master
2 parents 0c7101d + 24bd096 commit b7b70c8

File tree

7 files changed

+44
-13
lines changed

7 files changed

+44
-13
lines changed

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "async-h1"
3-
version = "2.0.0"
3+
version = "2.0.2"
44
license = "MIT OR Apache-2.0"
55
repository = "https://github.com/http-rs/async-h1"
66
documentation = "https://docs.rs/async-h1"

src/server/decode.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ fn url_from_httparse_req(req: &httparse::Request<'_, '_>) -> http_types::Result<
128128
}
129129

130130
const EXPECT_HEADER_VALUE: &str = "100-continue";
131-
const EXPECT_RESPONSE: &[u8] = b"HTTP/1.1 100 Continue\r\n";
131+
const EXPECT_RESPONSE: &[u8] = b"HTTP/1.1 100 Continue\r\n\r\n";
132132

133133
async fn handle_100_continue<IO>(req: &Request, io: &mut IO) -> http_types::Result<()>
134134
where
@@ -223,7 +223,7 @@ mod tests {
223223
let result = async_std::task::block_on(handle_100_continue(&request, &mut io));
224224
assert_eq!(
225225
std::str::from_utf8(&io.into_inner()).unwrap(),
226-
"HTTP/1.1 100 Continue\r\n"
226+
"HTTP/1.1 100 Continue\r\n\r\n"
227227
);
228228
assert!(result.is_ok());
229229
}

src/server/encode.rs

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use async_std::io;
66
use async_std::io::prelude::*;
77
use async_std::task::{Context, Poll};
88
use http_types::headers::{CONTENT_LENGTH, DATE, TRANSFER_ENCODING};
9-
use http_types::Response;
9+
use http_types::{Method, Response};
1010

1111
use crate::chunked::ChunkedEncoder;
1212
use crate::date::fmt_http_date;
@@ -36,6 +36,8 @@ pub struct Encoder {
3636
body_bytes_written: usize,
3737
/// An encoder for chunked encoding.
3838
chunked: ChunkedEncoder,
39+
/// the http method that this response is in reply to
40+
method: Method,
3941
}
4042

4143
#[derive(Debug)]
@@ -80,6 +82,7 @@ impl Encoder {
8082
body_len: 0,
8183
body_bytes_written: 0,
8284
chunked: ChunkedEncoder::new(),
85+
method,
8386
}
8487
}
8588

@@ -97,7 +100,7 @@ impl Encoder {
97100
match self.state {
98101
Start => assert!(matches!(state, ComputeHead)),
99102
ComputeHead => assert!(matches!(state, EncodeHead)),
100-
EncodeHead => assert!(matches!(state, EncodeChunkedBody | EncodeFixedBody)),
103+
EncodeHead => assert!(matches!(state, EncodeChunkedBody | EncodeFixedBody | End)),
101104
EncodeFixedBody => assert!(matches!(state, End)),
102105
EncodeChunkedBody => assert!(matches!(state, End)),
103106
End => panic!("No state transitions allowed after the ServerEncoder has ended"),
@@ -176,14 +179,20 @@ impl Encoder {
176179
// If we've read the total length of the head we're done
177180
// reading the head and can transition to reading the body
178181
if self.head_bytes_written == head_len {
179-
// The response length lets us know if we are encoding
180-
// our body in chunks or not
181-
match self.res.len() {
182-
Some(body_len) => {
183-
self.body_len = body_len;
184-
self.dispatch(State::EncodeFixedBody, cx, buf)
182+
if self.method == Method::Head {
183+
// If we are responding to a HEAD request, we MUST NOT send
184+
// body content
185+
self.dispatch(State::End, cx, buf)
186+
} else {
187+
// The response length lets us know if we are encoding
188+
// our body in chunks or not
189+
match self.res.len() {
190+
Some(body_len) => {
191+
self.body_len = body_len;
192+
self.dispatch(State::EncodeFixedBody, cx, buf)
193+
}
194+
None => self.dispatch(State::EncodeChunkedBody, cx, buf),
185195
}
186-
None => self.dispatch(State::EncodeChunkedBody, cx, buf),
187196
}
188197
} else {
189198
// If we haven't read the entire header it means `buf` isn't

src/server/mod.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,9 +70,11 @@ where
7070
}
7171
};
7272

73+
let method = req.method();
7374
// Pass the request to the endpoint and encode the response.
7475
let res = endpoint(req).await?;
75-
let mut encoder = Encoder::new(res);
76+
77+
let mut encoder = Encoder::new(res, method);
7678

7779
// Stream the response to the writer.
7880
io::copy(&mut encoder, &mut io).await?;

tests/fixtures/head_request.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
HEAD / HTTP/1.1
2+
host: example.com
3+
user-agent: curl/7.54.0
4+

tests/fixtures/head_response.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
HTTP/1.1 200 OK
2+
content-length: 5
3+
date: {DATE}
4+
content-type: text/plain;charset=utf-8
5+

tests/server.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,3 +144,14 @@ async fn test_invalid_trailer() {
144144

145145
assert!(case.read_result().await.is_empty());
146146
}
147+
#[async_std::test]
148+
async fn empty_body_for_head_requests() {
149+
let case =
150+
TestCase::new_server("fixtures/head_request.txt", "fixtures/head_response.txt").await;
151+
152+
async_h1::accept(case.clone(), |_| async { Ok("hello".into()) })
153+
.await
154+
.unwrap();
155+
156+
case.assert().await;
157+
}

0 commit comments

Comments
 (0)