Merge pull request #936 from jwilm/fix-chunked-decode
fix(http): Chunked decoder reads last \r\n
This commit is contained in:
@@ -58,6 +58,8 @@ enum ChunkedState {
|
|||||||
Body,
|
Body,
|
||||||
BodyCr,
|
BodyCr,
|
||||||
BodyLf,
|
BodyLf,
|
||||||
|
EndCr,
|
||||||
|
EndLf,
|
||||||
End,
|
End,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -148,6 +150,8 @@ impl ChunkedState {
|
|||||||
Body => try!(ChunkedState::read_body(body, size, buf, read)),
|
Body => try!(ChunkedState::read_body(body, size, buf, read)),
|
||||||
BodyCr => try!(ChunkedState::read_body_cr(body)),
|
BodyCr => try!(ChunkedState::read_body_cr(body)),
|
||||||
BodyLf => try!(ChunkedState::read_body_lf(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,
|
End => ChunkedState::End,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -201,10 +205,11 @@ impl ChunkedState {
|
|||||||
trace!("Chunk size is {:?}", size);
|
trace!("Chunk size is {:?}", size);
|
||||||
match byte!(rdr) {
|
match byte!(rdr) {
|
||||||
b'\n' if *size > 0 => Ok(ChunkedState::Body),
|
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")),
|
_ => Err(io::Error::new(io::ErrorKind::InvalidInput, "Invalid chunk size LF")),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn read_body<R: Read>(rdr: &mut R,
|
fn read_body<R: Read>(rdr: &mut R,
|
||||||
rem: &mut u64,
|
rem: &mut u64,
|
||||||
buf: &mut [u8],
|
buf: &mut [u8],
|
||||||
@@ -250,6 +255,19 @@ impl ChunkedState {
|
|||||||
_ => Err(io::Error::new(io::ErrorKind::InvalidInput, "Invalid chunk body LF")),
|
_ => 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)]
|
#[cfg(test)]
|
||||||
@@ -276,7 +294,7 @@ mod tests {
|
|||||||
let desc = format!("read_size failed for {:?}", s);
|
let desc = format!("read_size failed for {:?}", s);
|
||||||
state = result.expect(desc.as_str());
|
state = result.expect(desc.as_str());
|
||||||
trace!("State {:?}", state);
|
trace!("State {:?}", state);
|
||||||
if state == ChunkedState::Body || state == ChunkedState::End {
|
if state == ChunkedState::Body || state == ChunkedState::EndCr {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -375,7 +393,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_read_chunked_after_eof() {
|
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 mock_buf = io::Cursor::new(content);
|
||||||
let mut buf = [0u8; 50];
|
let mut buf = [0u8; 50];
|
||||||
let mut decoder = Decoder::chunked();
|
let mut decoder = Decoder::chunked();
|
||||||
|
|||||||
Reference in New Issue
Block a user