Skip to content

Commit bffde8c

Browse files
committed
fix(http): Chunked decoder reads last \r\n
Before this, the final \r\n for an empty body was not being read. This caused issues with keep-alive connections.
1 parent 7de6f2b commit bffde8c

File tree

1 file changed

+21
-3
lines changed

1 file changed

+21
-3
lines changed

src/http/h1/decode.rs

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,8 @@ enum ChunkedState {
5858
Body,
5959
BodyCr,
6060
BodyLf,
61+
EndCr,
62+
EndLf,
6163
End,
6264
}
6365

@@ -148,6 +150,8 @@ impl ChunkedState {
148150
Body => try!(ChunkedState::read_body(body, size, buf, read)),
149151
BodyCr => try!(ChunkedState::read_body_cr(body)),
150152
BodyLf => try!(ChunkedState::read_body_lf(body)),
153+
EndCr => try!(ChunkedState::read_end_cr(body)),
154+
EndLf => try!(ChunkedState::read_end_lf(body)),
151155
End => ChunkedState::End,
152156
})
153157
}
@@ -201,10 +205,11 @@ impl ChunkedState {
201205
trace!("Chunk size is {:?}", size);
202206
match byte!(rdr) {
203207
b'\n' if *size > 0 => Ok(ChunkedState::Body),
204-
b'\n' if *size == 0 => Ok(ChunkedState::End),
208+
b'\n' if *size == 0 => Ok(ChunkedState::EndCr),
205209
_ => Err(io::Error::new(io::ErrorKind::InvalidInput, "Invalid chunk size LF")),
206210
}
207211
}
212+
208213
fn read_body<R: Read>(rdr: &mut R,
209214
rem: &mut u64,
210215
buf: &mut [u8],
@@ -250,6 +255,19 @@ impl ChunkedState {
250255
_ => Err(io::Error::new(io::ErrorKind::InvalidInput, "Invalid chunk body LF")),
251256
}
252257
}
258+
259+
fn read_end_cr<R: Read>(rdr: &mut R) -> io::Result<ChunkedState> {
260+
match byte!(rdr) {
261+
b'\r' => Ok(ChunkedState::EndLf),
262+
_ => Err(io::Error::new(io::ErrorKind::InvalidInput, "Invalid chunk end CR")),
263+
}
264+
}
265+
fn read_end_lf<R: Read>(rdr: &mut R) -> io::Result<ChunkedState> {
266+
match byte!(rdr) {
267+
b'\n' => Ok(ChunkedState::End),
268+
_ => Err(io::Error::new(io::ErrorKind::InvalidInput, "Invalid chunk end LF")),
269+
}
270+
}
253271
}
254272

255273
#[cfg(test)]
@@ -276,7 +294,7 @@ mod tests {
276294
let desc = format!("read_size failed for {:?}", s);
277295
state = result.expect(desc.as_str());
278296
trace!("State {:?}", state);
279-
if state == ChunkedState::Body || state == ChunkedState::End {
297+
if state == ChunkedState::Body || state == ChunkedState::EndCr {
280298
break;
281299
}
282300
}
@@ -375,7 +393,7 @@ mod tests {
375393

376394
#[test]
377395
fn test_read_chunked_after_eof() {
378-
let content = b"10\r\n1234567890abcdef\r\n0\r\n";
396+
let content = b"10\r\n1234567890abcdef\r\n0\r\n\r\n";
379397
let mut mock_buf = io::Cursor::new(content);
380398
let mut buf = [0u8; 50];
381399
let mut decoder = Decoder::chunked();

0 commit comments

Comments
 (0)