1
0
mirror of https://github.com/actix/actix-extras.git synced 2024-11-30 18:34:36 +01:00

process transfer-encoding before content-length, fix tests on 32bit platform

This commit is contained in:
Nikolay Kim 2018-03-24 09:22:34 -07:00
parent 5127b85672
commit a56e5113ee
4 changed files with 31 additions and 21 deletions

View File

@ -150,6 +150,7 @@ pub(crate) fn write_status_line(version: Version, mut n: u16, bytes: &mut BytesM
} }
} }
/// NOTE: bytes object has to contain enough space
pub(crate) fn write_content_length(mut n: usize, bytes: &mut BytesMut) { pub(crate) fn write_content_length(mut n: usize, bytes: &mut BytesMut) {
if n < 10 { if n < 10 {
let mut buf: [u8; 21] = [b'\r',b'\n',b'c',b'o',b'n',b't',b'e', let mut buf: [u8; 21] = [b'\r',b'\n',b'c',b'o',b'n',b't',b'e',
@ -244,24 +245,34 @@ mod tests {
#[test] #[test]
fn test_write_content_length() { fn test_write_content_length() {
let mut bytes = BytesMut::new(); let mut bytes = BytesMut::new();
bytes.reserve(50);
write_content_length(0, &mut bytes); write_content_length(0, &mut bytes);
assert_eq!(bytes.take().freeze(), b"\r\ncontent-length: 0\r\n"[..]); assert_eq!(bytes.take().freeze(), b"\r\ncontent-length: 0\r\n"[..]);
bytes.reserve(50);
write_content_length(9, &mut bytes); write_content_length(9, &mut bytes);
assert_eq!(bytes.take().freeze(), b"\r\ncontent-length: 9\r\n"[..]); assert_eq!(bytes.take().freeze(), b"\r\ncontent-length: 9\r\n"[..]);
bytes.reserve(50);
write_content_length(10, &mut bytes); write_content_length(10, &mut bytes);
assert_eq!(bytes.take().freeze(), b"\r\ncontent-length: 10\r\n"[..]); assert_eq!(bytes.take().freeze(), b"\r\ncontent-length: 10\r\n"[..]);
bytes.reserve(50);
write_content_length(99, &mut bytes); write_content_length(99, &mut bytes);
assert_eq!(bytes.take().freeze(), b"\r\ncontent-length: 99\r\n"[..]); assert_eq!(bytes.take().freeze(), b"\r\ncontent-length: 99\r\n"[..]);
bytes.reserve(50);
write_content_length(100, &mut bytes); write_content_length(100, &mut bytes);
assert_eq!(bytes.take().freeze(), b"\r\ncontent-length: 100\r\n"[..]); assert_eq!(bytes.take().freeze(), b"\r\ncontent-length: 100\r\n"[..]);
bytes.reserve(50);
write_content_length(101, &mut bytes); write_content_length(101, &mut bytes);
assert_eq!(bytes.take().freeze(), b"\r\ncontent-length: 101\r\n"[..]); assert_eq!(bytes.take().freeze(), b"\r\ncontent-length: 101\r\n"[..]);
bytes.reserve(50);
write_content_length(998, &mut bytes); write_content_length(998, &mut bytes);
assert_eq!(bytes.take().freeze(), b"\r\ncontent-length: 998\r\n"[..]); assert_eq!(bytes.take().freeze(), b"\r\ncontent-length: 998\r\n"[..]);
bytes.reserve(50);
write_content_length(1000, &mut bytes); write_content_length(1000, &mut bytes);
assert_eq!(bytes.take().freeze(), b"\r\ncontent-length: 1000\r\n"[..]); assert_eq!(bytes.take().freeze(), b"\r\ncontent-length: 1000\r\n"[..]);
bytes.reserve(50);
write_content_length(1001, &mut bytes); write_content_length(1001, &mut bytes);
assert_eq!(bytes.take().freeze(), b"\r\ncontent-length: 1001\r\n"[..]); assert_eq!(bytes.take().freeze(), b"\r\ncontent-length: 1001\r\n"[..]);
bytes.reserve(50);
write_content_length(5909, &mut bytes); write_content_length(5909, &mut bytes);
assert_eq!(bytes.take().freeze(), b"\r\ncontent-length: 5909\r\n"[..]); assert_eq!(bytes.take().freeze(), b"\r\ncontent-length: 5909\r\n"[..]);
} }

View File

@ -494,6 +494,7 @@ impl Reader {
// Parse http message // Parse http message
let mut has_te = false; let mut has_te = false;
let mut has_upgrade = false; let mut has_upgrade = false;
let mut has_length = false;
let msg = { let msg = {
let bytes_ptr = buf.as_ref().as_ptr() as usize; let bytes_ptr = buf.as_ref().as_ptr() as usize;
let mut headers: [httparse::Header; MAX_HEADERS] = let mut headers: [httparse::Header; MAX_HEADERS] =
@ -505,10 +506,10 @@ impl Reader {
match req.parse(b)? { match req.parse(b)? {
httparse::Status::Complete(len) => { httparse::Status::Complete(len) => {
let method = Method::from_bytes( let method = Method::from_bytes(
req.method.unwrap_or("").as_bytes()) req.method.unwrap().as_bytes())
.map_err(|_| ParseError::Method)?; .map_err(|_| ParseError::Method)?;
let path = Uri::try_from(req.path.unwrap())?; let path = Uri::try_from(req.path.unwrap())?;
let version = if req.version.unwrap_or(1) == 1 { let version = if req.version.unwrap() == 1 {
Version::HTTP_11 Version::HTTP_11
} else { } else {
Version::HTTP_10 Version::HTTP_10
@ -528,6 +529,7 @@ impl Reader {
for header in headers[..headers_len].iter() { for header in headers[..headers_len].iter() {
if let Ok(name) = HeaderName::from_bytes(header.name.as_bytes()) { if let Ok(name) = HeaderName::from_bytes(header.name.as_bytes()) {
has_te = has_te || name == header::TRANSFER_ENCODING; has_te = has_te || name == header::TRANSFER_ENCODING;
has_length = has_length || name == header::CONTENT_LENGTH;
has_upgrade = has_upgrade || name == header::UPGRADE; has_upgrade = has_upgrade || name == header::UPGRADE;
let v_start = header.value.as_ptr() as usize - bytes_ptr; let v_start = header.value.as_ptr() as usize - bytes_ptr;
let v_end = v_start + header.value.len(); let v_end = v_start + header.value.len();
@ -547,10 +549,12 @@ impl Reader {
msg msg
}; };
let decoder = if let Some(len) = let decoder = if has_te && chunked(&msg.get_mut().headers)? {
msg.get_ref().headers.get(header::CONTENT_LENGTH) // Chunked encoding
{ Some(Decoder::chunked())
} else if has_length {
// Content-Length // Content-Length
let len = msg.get_ref().headers.get(header::CONTENT_LENGTH).unwrap();
if let Ok(s) = len.to_str() { if let Ok(s) = len.to_str() {
if let Ok(len) = s.parse::<u64>() { if let Ok(len) = s.parse::<u64>() {
Some(Decoder::length(len)) Some(Decoder::length(len))
@ -562,10 +566,8 @@ impl Reader {
debug!("illegal Content-Length: {:?}", len); debug!("illegal Content-Length: {:?}", len);
return Err(ParseError::Header) return Err(ParseError::Header)
} }
} else if has_te && chunked(&msg.get_mut().headers)? {
// Chunked encoding
Some(Decoder::chunked())
} else if has_upgrade || msg.get_ref().method == Method::CONNECT { } else if has_upgrade || msg.get_ref().method == Method::CONNECT {
// upgrade(websocket) or connect
Some(Decoder::eof()) Some(Decoder::eof())
} else { } else {
None None

View File

@ -134,24 +134,26 @@ impl<T: AsyncWrite, H: 'static> Writer for H1Writer<T, H> {
// render message // render message
{ {
let mut buffer = self.buffer.get_mut(); let mut buffer = self.buffer.get_mut();
let reason = msg.reason().as_bytes();
let mut is_bin = if let Body::Binary(ref bytes) = body { let mut is_bin = if let Body::Binary(ref bytes) = body {
buffer.reserve( buffer.reserve(
256 + msg.headers().len() * AVERAGE_HEADER_SIZE + bytes.len()); 256 + msg.headers().len() * AVERAGE_HEADER_SIZE
+ bytes.len() + reason.len());
true true
} else { } else {
buffer.reserve(256 + msg.headers().len() * AVERAGE_HEADER_SIZE); buffer.reserve(
256 + msg.headers().len() * AVERAGE_HEADER_SIZE + reason.len());
false false
}; };
// status line // status line
helpers::write_status_line(version, msg.status().as_u16(), &mut buffer); helpers::write_status_line(version, msg.status().as_u16(), &mut buffer);
SharedBytes::extend_from_slice_(buffer, msg.reason().as_bytes()); SharedBytes::extend_from_slice_(buffer, reason);
match body { match body {
Body::Empty => Body::Empty =>
if req.method != Method::HEAD { if req.method != Method::HEAD {
SharedBytes::put_slice( SharedBytes::put_slice(buffer, b"\r\ncontent-length: 0\r\n");
buffer, b"\r\ncontent-length: 0\r\n");
} else { } else {
SharedBytes::put_slice(buffer, b"\r\n"); SharedBytes::put_slice(buffer, b"\r\n");
}, },
@ -192,15 +194,10 @@ impl<T: AsyncWrite, H: 'static> Writer for H1Writer<T, H> {
buf[pos..pos+2].copy_from_slice(b"\r\n"); buf[pos..pos+2].copy_from_slice(b"\r\n");
pos += 2; pos += 2;
remaining -= len; remaining -= len;
//buffer.put_slice(k);
//buffer.put_slice(b": ");
//buffer.put_slice(v);
//buffer.put_slice(b"\r\n");
} }
unsafe{buffer.advance_mut(pos)}; unsafe{buffer.advance_mut(pos)};
// optimized date header // optimized date header, set_date writes \r\n
if !has_date { if !has_date {
self.settings.set_date(&mut buffer); self.settings.set_date(&mut buffer);
} else { } else {

View File

@ -639,7 +639,7 @@ impl<H: IntoHttpHandler> Handler<StopServer> for HttpServer<H>
// we need to stop system if server was spawned // we need to stop system if server was spawned
if slf.exit { if slf.exit {
ctx.run_later(Duration::from_millis(500), |_, _| { ctx.run_later(Duration::from_millis(300), |_, _| {
Arbiter::system().do_send(actix::msgs::SystemExit(0)) Arbiter::system().do_send(actix::msgs::SystemExit(0))
}); });
} }
@ -654,7 +654,7 @@ impl<H: IntoHttpHandler> Handler<StopServer> for HttpServer<H>
} else { } else {
// we need to stop system if server was spawned // we need to stop system if server was spawned
if self.exit { if self.exit {
ctx.run_later(Duration::from_millis(500), |_, _| { ctx.run_later(Duration::from_millis(300), |_, _| {
Arbiter::system().do_send(actix::msgs::SystemExit(0)) Arbiter::system().do_send(actix::msgs::SystemExit(0))
}); });
} }