mirror of
https://github.com/actix/actix-extras.git
synced 2024-11-28 01:32:57 +01:00
process transfer-encoding before content-length, fix tests on 32bit platform
This commit is contained in:
parent
5127b85672
commit
a56e5113ee
@ -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"[..]);
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
@ -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 {
|
||||||
|
@ -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))
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user