1
0
Fork 0
mirror of https://github.com/actix/actix-web.git synced 2024-11-18 15:41:17 +00: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) {
if n < 10 {
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]
fn test_write_content_length() {
let mut bytes = BytesMut::new();
bytes.reserve(50);
write_content_length(0, &mut bytes);
assert_eq!(bytes.take().freeze(), b"\r\ncontent-length: 0\r\n"[..]);
bytes.reserve(50);
write_content_length(9, &mut bytes);
assert_eq!(bytes.take().freeze(), b"\r\ncontent-length: 9\r\n"[..]);
bytes.reserve(50);
write_content_length(10, &mut bytes);
assert_eq!(bytes.take().freeze(), b"\r\ncontent-length: 10\r\n"[..]);
bytes.reserve(50);
write_content_length(99, &mut bytes);
assert_eq!(bytes.take().freeze(), b"\r\ncontent-length: 99\r\n"[..]);
bytes.reserve(50);
write_content_length(100, &mut bytes);
assert_eq!(bytes.take().freeze(), b"\r\ncontent-length: 100\r\n"[..]);
bytes.reserve(50);
write_content_length(101, &mut bytes);
assert_eq!(bytes.take().freeze(), b"\r\ncontent-length: 101\r\n"[..]);
bytes.reserve(50);
write_content_length(998, &mut bytes);
assert_eq!(bytes.take().freeze(), b"\r\ncontent-length: 998\r\n"[..]);
bytes.reserve(50);
write_content_length(1000, &mut bytes);
assert_eq!(bytes.take().freeze(), b"\r\ncontent-length: 1000\r\n"[..]);
bytes.reserve(50);
write_content_length(1001, &mut bytes);
assert_eq!(bytes.take().freeze(), b"\r\ncontent-length: 1001\r\n"[..]);
bytes.reserve(50);
write_content_length(5909, &mut bytes);
assert_eq!(bytes.take().freeze(), b"\r\ncontent-length: 5909\r\n"[..]);
}

View file

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

View file

@ -134,24 +134,26 @@ impl<T: AsyncWrite, H: 'static> Writer for H1Writer<T, H> {
// render message
{
let mut buffer = self.buffer.get_mut();
let reason = msg.reason().as_bytes();
let mut is_bin = if let Body::Binary(ref bytes) = body {
buffer.reserve(
256 + msg.headers().len() * AVERAGE_HEADER_SIZE + bytes.len());
256 + msg.headers().len() * AVERAGE_HEADER_SIZE
+ bytes.len() + reason.len());
true
} else {
buffer.reserve(256 + msg.headers().len() * AVERAGE_HEADER_SIZE);
buffer.reserve(
256 + msg.headers().len() * AVERAGE_HEADER_SIZE + reason.len());
false
};
// status line
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 {
Body::Empty =>
if req.method != Method::HEAD {
SharedBytes::put_slice(
buffer, b"\r\ncontent-length: 0\r\n");
SharedBytes::put_slice(buffer, b"\r\ncontent-length: 0\r\n");
} else {
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");
pos += 2;
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)};
// optimized date header
// optimized date header, set_date writes \r\n
if !has_date {
self.settings.set_date(&mut buffer);
} else {

View file

@ -639,7 +639,7 @@ impl<H: IntoHttpHandler> Handler<StopServer> for HttpServer<H>
// we need to stop system if server was spawned
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))
});
}
@ -654,7 +654,7 @@ impl<H: IntoHttpHandler> Handler<StopServer> for HttpServer<H>
} else {
// we need to stop system if server was spawned
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))
});
}