Skip to content

Commit 14e4c74

Browse files
committed
fix(tokio-proto): return end-of-body frame correctly for tokio-proto
Closes #1414
1 parent 73511ac commit 14e4c74

File tree

2 files changed

+40
-14
lines changed

2 files changed

+40
-14
lines changed

src/proto/conn.rs

+39-11
Original file line numberDiff line numberDiff line change
@@ -237,20 +237,17 @@ where I: AsyncRead + AsyncWrite,
237237
Reading::Body(ref mut decoder) => {
238238
match decoder.decode(&mut self.io) {
239239
Ok(Async::Ready(slice)) => {
240-
let chunk = if !slice.is_empty() {
241-
Some(super::Chunk::from(slice))
242-
} else {
243-
None
244-
};
245-
let reading = if decoder.is_eof() {
240+
let (reading, chunk) = if !slice.is_empty() {
241+
return Ok(Async::Ready(Some(super::Chunk::from(slice))));
242+
} else if decoder.is_eof() {
246243
debug!("incoming body completed");
247-
Reading::KeepAlive
248-
} else if chunk.is_some() {
249-
Reading::Body(decoder.clone())
244+
(Reading::KeepAlive, None)
250245
} else {
251246
trace!("decode stream unexpectedly ended");
252-
//TODO: Should this return an UnexpectedEof?
253-
Reading::Closed
247+
// this should actually be unreachable:
248+
// the decoder will return an UnexpectedEof if there were
249+
// no bytes to read and it isn't eof yet...
250+
(Reading::Closed, None)
254251
};
255252
(reading, Ok(Async::Ready(chunk)))
256253
},
@@ -1078,6 +1075,37 @@ mod tests {
10781075
}).wait();
10791076
}
10801077

1078+
#[test]
1079+
fn test_conn_read_body_end() {
1080+
let _: Result<(), ()> = future::lazy(|| {
1081+
let io = AsyncIo::new_buf(b"POST / HTTP/1.1\r\nContent-Length: 5\r\n\r\n12345".to_vec(), 1024);
1082+
let mut conn = Conn::<_, proto::Chunk, ServerTransaction>::new(io, Default::default());
1083+
conn.state.busy();
1084+
1085+
match conn.poll() {
1086+
Ok(Async::Ready(Some(Frame::Message { body: true, .. }))) => (),
1087+
other => panic!("unexpected frame: {:?}", other)
1088+
}
1089+
1090+
match conn.poll() {
1091+
Ok(Async::Ready(Some(Frame::Body { chunk: Some(_) }))) => (),
1092+
other => panic!("unexpected frame: {:?}", other)
1093+
}
1094+
1095+
// When the body is done, `poll` MUST return a `Body` frame with chunk set to `None`
1096+
match conn.poll() {
1097+
Ok(Async::Ready(Some(Frame::Body { chunk: None }))) => (),
1098+
other => panic!("unexpected frame: {:?}", other)
1099+
}
1100+
1101+
match conn.poll() {
1102+
Ok(Async::NotReady) => (),
1103+
other => panic!("unexpected frame: {:?}", other)
1104+
}
1105+
Ok(())
1106+
}).wait();
1107+
}
1108+
10811109
#[test]
10821110
fn test_conn_closed_read() {
10831111
let io = AsyncIo::new_buf(vec![], 0);

src/proto/h1/decode.rs

+1-3
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,6 @@ impl Decoder {
7575
// methods
7676

7777
pub fn is_eof(&self) -> bool {
78-
trace!("is_eof? {:?}", self);
7978
match self.kind {
8079
Length(0) |
8180
Chunked(ChunkedState::End, _) |
@@ -85,16 +84,15 @@ impl Decoder {
8584
}
8685

8786
pub fn decode<R: MemRead>(&mut self, body: &mut R) -> Poll<Bytes, io::Error> {
87+
trace!("decode; state={:?}", self.kind);
8888
match self.kind {
8989
Length(ref mut remaining) => {
90-
trace!("Sized read, remaining={:?}", remaining);
9190
if *remaining == 0 {
9291
Ok(Async::Ready(Bytes::new()))
9392
} else {
9493
let to_read = *remaining as usize;
9594
let buf = try_ready!(body.read_mem(to_read));
9695
let num = buf.as_ref().len() as u64;
97-
trace!("Length read: {}", num);
9896
if num > *remaining {
9997
*remaining = 0;
10098
} else if num == 0 {

0 commit comments

Comments
 (0)