Skip to content

Commit dffae5f

Browse files
committed
don't panic if the connection is closed at any point
1 parent 9993b04 commit dffae5f

File tree

3 files changed

+58
-8
lines changed

3 files changed

+58
-8
lines changed

Diff for: src/client/decode.rs

+6-1
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,12 @@ where
2929
loop {
3030
let bytes_read = reader.read_until(LF, &mut buf).await?;
3131
// No more bytes are yielded from the stream.
32-
assert!(bytes_read != 0, "Empty response"); // TODO: ensure?
32+
33+
match (bytes_read, buf.len()) {
34+
(0, 0) => return Err(format_err!("connection closed")),
35+
(0, _) => return Err(format_err!("empty response")),
36+
_ => {}
37+
}
3338

3439
// Prevent CWE-400 DDOS with large HTTP Headers.
3540
ensure!(

Diff for: tests/client_decode.rs

+25
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,9 @@
1+
mod test_utils;
2+
13
mod client_decode {
4+
use std::io::Write;
5+
6+
use super::test_utils::CloseableCursor;
27
use async_h1::client;
38
use async_std::io::Cursor;
49
use http_types::headers;
@@ -42,6 +47,26 @@ mod client_decode {
4247
Ok(())
4348
}
4449

50+
#[async_std::test]
51+
async fn connection_closure() -> Result<()> {
52+
let mut cursor = CloseableCursor::default();
53+
cursor.write_all(b"HTTP/1.1 200 OK\r\nhost: example.com")?;
54+
cursor.close();
55+
assert_eq!(
56+
client::decode(cursor).await.unwrap_err().to_string(),
57+
"empty response"
58+
);
59+
60+
let cursor = CloseableCursor::default();
61+
cursor.close();
62+
assert_eq!(
63+
client::decode(cursor).await.unwrap_err().to_string(),
64+
"connection closed"
65+
);
66+
67+
Ok(())
68+
}
69+
4570
#[async_std::test]
4671
async fn response_newlines() -> Result<()> {
4772
let res = decode_lines(vec![

Diff for: tests/test_utils.rs

+27-7
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use async_h1::{
22
client::Encoder,
33
server::{ConnectionStatus, Server},
44
};
5-
use async_std::io::{Read, Write};
5+
use async_std::io::{Read as AsyncRead, Write as AsyncWrite};
66
use http_types::{Request, Response, Result};
77
use std::{
88
fmt::{Debug, Display},
@@ -58,7 +58,7 @@ where
5858
}
5959
}
6060

61-
impl<F, Fut> Read for TestServer<F, Fut>
61+
impl<F, Fut> AsyncRead for TestServer<F, Fut>
6262
where
6363
F: Fn(Request) -> Fut,
6464
Fut: Future<Output = Result<Response>>,
@@ -72,7 +72,7 @@ where
7272
}
7373
}
7474

75-
impl<F, Fut> Write for TestServer<F, Fut>
75+
impl<F, Fut> AsyncWrite for TestServer<F, Fut>
7676
where
7777
F: Fn(Request) -> Fut,
7878
Fut: Future<Output = Result<Response>>,
@@ -187,7 +187,17 @@ impl Debug for CloseableCursor {
187187
}
188188
}
189189

190-
impl Read for &CloseableCursor {
190+
impl AsyncRead for CloseableCursor {
191+
fn poll_read(
192+
self: Pin<&mut Self>,
193+
cx: &mut Context<'_>,
194+
buf: &mut [u8],
195+
) -> Poll<io::Result<usize>> {
196+
Pin::new(&mut &*self).poll_read(cx, buf)
197+
}
198+
}
199+
200+
impl AsyncRead for &CloseableCursor {
191201
fn poll_read(
192202
self: Pin<&mut Self>,
193203
cx: &mut Context<'_>,
@@ -209,7 +219,7 @@ impl Read for &CloseableCursor {
209219
}
210220
}
211221

212-
impl Write for &CloseableCursor {
222+
impl AsyncWrite for &CloseableCursor {
213223
fn poll_write(
214224
self: Pin<&mut Self>,
215225
_cx: &mut Context<'_>,
@@ -237,7 +247,7 @@ impl Write for &CloseableCursor {
237247
}
238248
}
239249

240-
impl Read for TestIO {
250+
impl AsyncRead for TestIO {
241251
fn poll_read(
242252
self: Pin<&mut Self>,
243253
cx: &mut Context<'_>,
@@ -247,7 +257,7 @@ impl Read for TestIO {
247257
}
248258
}
249259

250-
impl Write for TestIO {
260+
impl AsyncWrite for TestIO {
251261
fn poll_write(
252262
self: Pin<&mut Self>,
253263
cx: &mut Context<'_>,
@@ -264,3 +274,13 @@ impl Write for TestIO {
264274
Pin::new(&mut &*self.write).poll_close(cx)
265275
}
266276
}
277+
278+
impl std::io::Write for CloseableCursor {
279+
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
280+
self.0.write().unwrap().data.write(buf)
281+
}
282+
283+
fn flush(&mut self) -> io::Result<()> {
284+
Ok(())
285+
}
286+
}

0 commit comments

Comments
 (0)