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:
parent
5127b85672
commit
a56e5113ee
4 changed files with 31 additions and 21 deletions
|
@ -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"[..]);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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))
|
||||
});
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue