Skip to content

Commit

Permalink
fix(http): Chunked decoder reads last \r\n
Browse files Browse the repository at this point in the history
Before this, the final \r\n for an empty body was not being read. This
caused issues with keep-alive connections.
  • Loading branch information
jwilm committed Oct 18, 2016
1 parent 7de6f2b commit bffde8c
Showing 1 changed file with 21 additions and 3 deletions.
24 changes: 21 additions & 3 deletions src/http/h1/decode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@ enum ChunkedState {
Body,
BodyCr,
BodyLf,
EndCr,
EndLf,
End,
}

Expand Down Expand Up @@ -148,6 +150,8 @@ impl ChunkedState {
Body => try!(ChunkedState::read_body(body, size, buf, read)),
BodyCr => try!(ChunkedState::read_body_cr(body)),
BodyLf => try!(ChunkedState::read_body_lf(body)),
EndCr => try!(ChunkedState::read_end_cr(body)),
EndLf => try!(ChunkedState::read_end_lf(body)),
End => ChunkedState::End,
})
}
Expand Down Expand Up @@ -201,10 +205,11 @@ impl ChunkedState {
trace!("Chunk size is {:?}", size);
match byte!(rdr) {
b'\n' if *size > 0 => Ok(ChunkedState::Body),
b'\n' if *size == 0 => Ok(ChunkedState::End),
b'\n' if *size == 0 => Ok(ChunkedState::EndCr),
_ => Err(io::Error::new(io::ErrorKind::InvalidInput, "Invalid chunk size LF")),
}
}

fn read_body<R: Read>(rdr: &mut R,
rem: &mut u64,
buf: &mut [u8],
Expand Down Expand Up @@ -250,6 +255,19 @@ impl ChunkedState {
_ => Err(io::Error::new(io::ErrorKind::InvalidInput, "Invalid chunk body LF")),
}
}

fn read_end_cr<R: Read>(rdr: &mut R) -> io::Result<ChunkedState> {
match byte!(rdr) {
b'\r' => Ok(ChunkedState::EndLf),
_ => Err(io::Error::new(io::ErrorKind::InvalidInput, "Invalid chunk end CR")),
}
}
fn read_end_lf<R: Read>(rdr: &mut R) -> io::Result<ChunkedState> {
match byte!(rdr) {
b'\n' => Ok(ChunkedState::End),
_ => Err(io::Error::new(io::ErrorKind::InvalidInput, "Invalid chunk end LF")),
}
}
}

#[cfg(test)]
Expand All @@ -276,7 +294,7 @@ mod tests {
let desc = format!("read_size failed for {:?}", s);
state = result.expect(desc.as_str());
trace!("State {:?}", state);
if state == ChunkedState::Body || state == ChunkedState::End {
if state == ChunkedState::Body || state == ChunkedState::EndCr {
break;
}
}
Expand Down Expand Up @@ -375,7 +393,7 @@ mod tests {

#[test]
fn test_read_chunked_after_eof() {
let content = b"10\r\n1234567890abcdef\r\n0\r\n";
let content = b"10\r\n1234567890abcdef\r\n0\r\n\r\n";
let mut mock_buf = io::Cursor::new(content);
let mut buf = [0u8; 50];
let mut decoder = Decoder::chunked();
Expand Down

0 comments on commit bffde8c

Please sign in to comment.