mirror of
https://github.com/actix/actix-web.git
synced 2024-11-26 19:41:12 +00:00
parent
9cc6f6b1e4
commit
a0e6313d56
6 changed files with 162 additions and 32 deletions
|
@ -2,6 +2,8 @@
|
||||||
|
|
||||||
## 0.4.5 (2018-03-xx)
|
## 0.4.5 (2018-03-xx)
|
||||||
|
|
||||||
|
* Fix compression #103 and #104
|
||||||
|
|
||||||
* Enable compression support for `NamedFile`
|
* Enable compression support for `NamedFile`
|
||||||
|
|
||||||
* Better support for `NamedFile` type
|
* Better support for `NamedFile` type
|
||||||
|
|
|
@ -78,6 +78,7 @@ impl HttpResponseParser {
|
||||||
-> Poll<Option<Bytes>, PayloadError>
|
-> Poll<Option<Bytes>, PayloadError>
|
||||||
where T: IoStream
|
where T: IoStream
|
||||||
{
|
{
|
||||||
|
println!("PARSE payload, {:?}", self.decoder.is_some());
|
||||||
if self.decoder.is_some() {
|
if self.decoder.is_some() {
|
||||||
loop {
|
loop {
|
||||||
// read payload
|
// read payload
|
||||||
|
|
|
@ -154,7 +154,7 @@ pub(crate) const HAS_OPENSSL: bool = false;
|
||||||
// #[cfg(not(feature="tls"))]
|
// #[cfg(not(feature="tls"))]
|
||||||
// pub(crate) const HAS_TLS: bool = false;
|
// pub(crate) const HAS_TLS: bool = false;
|
||||||
|
|
||||||
|
#[doc(hidden)]
|
||||||
#[deprecated(since="0.4.4", note="please use `actix::header` module")]
|
#[deprecated(since="0.4.4", note="please use `actix::header` module")]
|
||||||
pub mod headers {
|
pub mod headers {
|
||||||
//! Headers implementation
|
//! Headers implementation
|
||||||
|
|
|
@ -246,18 +246,14 @@ impl PayloadStream {
|
||||||
if let Some(ref mut decoder) = *decoder {
|
if let Some(ref mut decoder) = *decoder {
|
||||||
decoder.as_mut().get_mut().eof = true;
|
decoder.as_mut().get_mut().eof = true;
|
||||||
|
|
||||||
loop {
|
self.dst.reserve(8192);
|
||||||
self.dst.reserve(8192);
|
match decoder.read(unsafe{self.dst.bytes_mut()}) {
|
||||||
match decoder.read(unsafe{self.dst.bytes_mut()}) {
|
Ok(n) => {
|
||||||
Ok(n) => {
|
unsafe{self.dst.advance_mut(n)};
|
||||||
if n == 0 {
|
return Ok(Some(self.dst.take().freeze()))
|
||||||
return Ok(Some(self.dst.take().freeze()))
|
|
||||||
} else {
|
|
||||||
unsafe{self.dst.advance_mut(n)};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Err(e) => return Err(e),
|
|
||||||
}
|
}
|
||||||
|
Err(e) =>
|
||||||
|
return Err(e),
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Ok(None)
|
Ok(None)
|
||||||
|
@ -283,8 +279,9 @@ impl PayloadStream {
|
||||||
pub fn feed_data(&mut self, data: Bytes) -> io::Result<Option<Bytes>> {
|
pub fn feed_data(&mut self, data: Bytes) -> io::Result<Option<Bytes>> {
|
||||||
match self.decoder {
|
match self.decoder {
|
||||||
Decoder::Br(ref mut decoder) => {
|
Decoder::Br(ref mut decoder) => {
|
||||||
match decoder.write(&data).and_then(|_| decoder.flush()) {
|
match decoder.write_all(&data) {
|
||||||
Ok(_) => {
|
Ok(_) => {
|
||||||
|
decoder.flush()?;
|
||||||
let b = decoder.get_mut().take();
|
let b = decoder.get_mut().take();
|
||||||
if !b.is_empty() {
|
if !b.is_empty() {
|
||||||
Ok(Some(b))
|
Ok(Some(b))
|
||||||
|
@ -306,23 +303,31 @@ impl PayloadStream {
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
self.dst.reserve(8192);
|
self.dst.reserve(8192);
|
||||||
match decoder.as_mut().as_mut().unwrap().read(unsafe{self.dst.bytes_mut()}) {
|
match decoder.as_mut()
|
||||||
|
.as_mut().unwrap().read(unsafe{self.dst.bytes_mut()})
|
||||||
|
{
|
||||||
Ok(n) => {
|
Ok(n) => {
|
||||||
|
if n != 0 {
|
||||||
|
unsafe{self.dst.advance_mut(n)};
|
||||||
|
}
|
||||||
if n == 0 {
|
if n == 0 {
|
||||||
return Ok(Some(self.dst.take().freeze()));
|
return Ok(Some(self.dst.take().freeze()));
|
||||||
} else {
|
|
||||||
unsafe{self.dst.advance_mut(n)};
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
|
if e.kind() == io::ErrorKind::WouldBlock && !self.dst.is_empty()
|
||||||
|
{
|
||||||
|
return Ok(Some(self.dst.take().freeze()));
|
||||||
|
}
|
||||||
return Err(e)
|
return Err(e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Decoder::Deflate(ref mut decoder) => {
|
Decoder::Deflate(ref mut decoder) => {
|
||||||
match decoder.write(&data).and_then(|_| decoder.flush()) {
|
match decoder.write_all(&data) {
|
||||||
Ok(_) => {
|
Ok(_) => {
|
||||||
|
decoder.flush()?;
|
||||||
let b = decoder.get_mut().take();
|
let b = decoder.get_mut().take();
|
||||||
if !b.is_empty() {
|
if !b.is_empty() {
|
||||||
Ok(Some(b))
|
Ok(Some(b))
|
||||||
|
@ -590,9 +595,8 @@ impl ContentEncoder {
|
||||||
pub fn write(&mut self, data: Binary) -> Result<(), io::Error> {
|
pub fn write(&mut self, data: Binary) -> Result<(), io::Error> {
|
||||||
match *self {
|
match *self {
|
||||||
ContentEncoder::Br(ref mut encoder) => {
|
ContentEncoder::Br(ref mut encoder) => {
|
||||||
match encoder.write(data.as_ref()) {
|
match encoder.write_all(data.as_ref()) {
|
||||||
Ok(_) =>
|
Ok(_) => Ok(()),
|
||||||
encoder.flush(),
|
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
trace!("Error decoding br encoding: {}", err);
|
trace!("Error decoding br encoding: {}", err);
|
||||||
Err(err)
|
Err(err)
|
||||||
|
@ -600,9 +604,8 @@ impl ContentEncoder {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
ContentEncoder::Gzip(ref mut encoder) => {
|
ContentEncoder::Gzip(ref mut encoder) => {
|
||||||
match encoder.write(data.as_ref()) {
|
match encoder.write_all(data.as_ref()) {
|
||||||
Ok(_) =>
|
Ok(_) => Ok(()),
|
||||||
encoder.flush(),
|
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
trace!("Error decoding gzip encoding: {}", err);
|
trace!("Error decoding gzip encoding: {}", err);
|
||||||
Err(err)
|
Err(err)
|
||||||
|
@ -610,9 +613,8 @@ impl ContentEncoder {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ContentEncoder::Deflate(ref mut encoder) => {
|
ContentEncoder::Deflate(ref mut encoder) => {
|
||||||
match encoder.write(data.as_ref()) {
|
match encoder.write_all(data.as_ref()) {
|
||||||
Ok(_) =>
|
Ok(_) => Ok(()),
|
||||||
encoder.flush(),
|
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
trace!("Error decoding deflate encoding: {}", err);
|
trace!("Error decoding deflate encoding: {}", err);
|
||||||
Err(err)
|
Err(err)
|
||||||
|
|
|
@ -3,6 +3,7 @@ extern crate actix_web;
|
||||||
extern crate bytes;
|
extern crate bytes;
|
||||||
extern crate futures;
|
extern crate futures;
|
||||||
extern crate flate2;
|
extern crate flate2;
|
||||||
|
extern crate rand;
|
||||||
|
|
||||||
use std::io::Read;
|
use std::io::Read;
|
||||||
|
|
||||||
|
@ -10,6 +11,7 @@ use bytes::Bytes;
|
||||||
use futures::Future;
|
use futures::Future;
|
||||||
use futures::stream::once;
|
use futures::stream::once;
|
||||||
use flate2::read::GzDecoder;
|
use flate2::read::GzDecoder;
|
||||||
|
use rand::Rng;
|
||||||
|
|
||||||
use actix_web::*;
|
use actix_web::*;
|
||||||
|
|
||||||
|
@ -143,7 +145,12 @@ fn test_client_gzip_encoding_large() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_client_brotli_encoding() {
|
fn test_client_gzip_encoding_large_random() {
|
||||||
|
let data = rand::thread_rng()
|
||||||
|
.gen_ascii_chars()
|
||||||
|
.take(100_000)
|
||||||
|
.collect::<String>();
|
||||||
|
|
||||||
let mut srv = test::TestServer::new(|app| app.handler(|req: HttpRequest| {
|
let mut srv = test::TestServer::new(|app| app.handler(|req: HttpRequest| {
|
||||||
req.body()
|
req.body()
|
||||||
.and_then(|bytes: Bytes| {
|
.and_then(|bytes: Bytes| {
|
||||||
|
@ -154,6 +161,30 @@ fn test_client_brotli_encoding() {
|
||||||
}).responder()}
|
}).responder()}
|
||||||
));
|
));
|
||||||
|
|
||||||
|
// client request
|
||||||
|
let request = srv.post()
|
||||||
|
.content_encoding(headers::ContentEncoding::Gzip)
|
||||||
|
.body(data.clone()).unwrap();
|
||||||
|
let response = srv.execute(request.send()).unwrap();
|
||||||
|
assert!(response.status().is_success());
|
||||||
|
|
||||||
|
// read response
|
||||||
|
let bytes = srv.execute(response.body()).unwrap();
|
||||||
|
assert_eq!(bytes, Bytes::from(data));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_client_brotli_encoding() {
|
||||||
|
let mut srv = test::TestServer::new(|app| app.handler(|req: HttpRequest| {
|
||||||
|
req.body()
|
||||||
|
.and_then(|bytes: Bytes| {
|
||||||
|
Ok(httpcodes::HTTPOk
|
||||||
|
.build()
|
||||||
|
.content_encoding(headers::ContentEncoding::Gzip)
|
||||||
|
.body(bytes))
|
||||||
|
}).responder()}
|
||||||
|
));
|
||||||
|
|
||||||
// client request
|
// client request
|
||||||
let request = srv.client(Method::POST, "/")
|
let request = srv.client(Method::POST, "/")
|
||||||
.content_encoding(headers::ContentEncoding::Br)
|
.content_encoding(headers::ContentEncoding::Br)
|
||||||
|
@ -166,6 +197,36 @@ fn test_client_brotli_encoding() {
|
||||||
assert_eq!(bytes, Bytes::from_static(STR.as_ref()));
|
assert_eq!(bytes, Bytes::from_static(STR.as_ref()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_client_brotli_encoding_large_random() {
|
||||||
|
let data = rand::thread_rng()
|
||||||
|
.gen_ascii_chars()
|
||||||
|
.take(70_000)
|
||||||
|
.collect::<String>();
|
||||||
|
|
||||||
|
let mut srv = test::TestServer::new(|app| app.handler(|req: HttpRequest| {
|
||||||
|
req.body()
|
||||||
|
.and_then(move |bytes: Bytes| {
|
||||||
|
Ok(httpcodes::HTTPOk
|
||||||
|
.build()
|
||||||
|
.content_encoding(headers::ContentEncoding::Gzip)
|
||||||
|
.body(bytes))
|
||||||
|
}).responder()}
|
||||||
|
));
|
||||||
|
|
||||||
|
// client request
|
||||||
|
let request = srv.client(Method::POST, "/")
|
||||||
|
.content_encoding(headers::ContentEncoding::Br)
|
||||||
|
.body(data.clone()).unwrap();
|
||||||
|
let response = srv.execute(request.send()).unwrap();
|
||||||
|
assert!(response.status().is_success());
|
||||||
|
|
||||||
|
// read response
|
||||||
|
let bytes = srv.execute(response.body()).unwrap();
|
||||||
|
assert_eq!(bytes.len(), data.len());
|
||||||
|
assert_eq!(bytes, Bytes::from(data));
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_client_deflate_encoding() {
|
fn test_client_deflate_encoding() {
|
||||||
let mut srv = test::TestServer::new(|app| app.handler(|req: HttpRequest| {
|
let mut srv = test::TestServer::new(|app| app.handler(|req: HttpRequest| {
|
||||||
|
@ -190,6 +251,35 @@ fn test_client_deflate_encoding() {
|
||||||
assert_eq!(bytes, Bytes::from_static(STR.as_ref()));
|
assert_eq!(bytes, Bytes::from_static(STR.as_ref()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_client_deflate_encoding_large_random() {
|
||||||
|
let data = rand::thread_rng()
|
||||||
|
.gen_ascii_chars()
|
||||||
|
.take(70_000)
|
||||||
|
.collect::<String>();
|
||||||
|
|
||||||
|
let mut srv = test::TestServer::new(|app| app.handler(|req: HttpRequest| {
|
||||||
|
req.body()
|
||||||
|
.and_then(|bytes: Bytes| {
|
||||||
|
Ok(httpcodes::HTTPOk
|
||||||
|
.build()
|
||||||
|
.content_encoding(headers::ContentEncoding::Br)
|
||||||
|
.body(bytes))
|
||||||
|
}).responder()}
|
||||||
|
));
|
||||||
|
|
||||||
|
// client request
|
||||||
|
let request = srv.post()
|
||||||
|
.content_encoding(headers::ContentEncoding::Deflate)
|
||||||
|
.body(data.clone()).unwrap();
|
||||||
|
let response = srv.execute(request.send()).unwrap();
|
||||||
|
assert!(response.status().is_success());
|
||||||
|
|
||||||
|
// read response
|
||||||
|
let bytes = srv.execute(response.body()).unwrap();
|
||||||
|
assert_eq!(bytes, Bytes::from(data));
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_client_streaming_explicit() {
|
fn test_client_streaming_explicit() {
|
||||||
let mut srv = test::TestServer::new(
|
let mut srv = test::TestServer::new(
|
||||||
|
|
|
@ -241,7 +241,7 @@ fn test_body_gzip_large() {
|
||||||
fn test_body_gzip_large_random() {
|
fn test_body_gzip_large_random() {
|
||||||
let data = rand::thread_rng()
|
let data = rand::thread_rng()
|
||||||
.gen_ascii_chars()
|
.gen_ascii_chars()
|
||||||
.take(70000)
|
.take(70_000)
|
||||||
.collect::<String>();
|
.collect::<String>();
|
||||||
let srv_data = Arc::new(data.clone());
|
let srv_data = Arc::new(data.clone());
|
||||||
|
|
||||||
|
@ -525,10 +525,10 @@ fn test_gzip_encoding_large() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_gzip_encoding_large_random() {
|
fn test_reading_gzip_encoding_large_random() {
|
||||||
let data = rand::thread_rng()
|
let data = rand::thread_rng()
|
||||||
.gen_ascii_chars()
|
.gen_ascii_chars()
|
||||||
.take(6000)
|
.take(60_000)
|
||||||
.collect::<String>();
|
.collect::<String>();
|
||||||
|
|
||||||
let mut srv = test::TestServer::new(|app| app.handler(|req: HttpRequest| {
|
let mut srv = test::TestServer::new(|app| app.handler(|req: HttpRequest| {
|
||||||
|
@ -554,11 +554,12 @@ fn test_gzip_encoding_large_random() {
|
||||||
|
|
||||||
// read response
|
// read response
|
||||||
let bytes = srv.execute(response.body()).unwrap();
|
let bytes = srv.execute(response.body()).unwrap();
|
||||||
|
assert_eq!(bytes.len(), data.len());
|
||||||
assert_eq!(bytes, Bytes::from(data));
|
assert_eq!(bytes, Bytes::from(data));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_deflate_encoding() {
|
fn test_reading_deflate_encoding() {
|
||||||
let mut srv = test::TestServer::new(|app| app.handler(|req: HttpRequest| {
|
let mut srv = test::TestServer::new(|app| app.handler(|req: HttpRequest| {
|
||||||
req.body()
|
req.body()
|
||||||
.and_then(|bytes: Bytes| {
|
.and_then(|bytes: Bytes| {
|
||||||
|
@ -586,7 +587,7 @@ fn test_deflate_encoding() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_deflate_encoding_large() {
|
fn test_reading_deflate_encoding_large() {
|
||||||
let data = STR.repeat(10);
|
let data = STR.repeat(10);
|
||||||
let mut srv = test::TestServer::new(|app| app.handler(|req: HttpRequest| {
|
let mut srv = test::TestServer::new(|app| app.handler(|req: HttpRequest| {
|
||||||
req.body()
|
req.body()
|
||||||
|
@ -614,6 +615,40 @@ fn test_deflate_encoding_large() {
|
||||||
assert_eq!(bytes, Bytes::from(data));
|
assert_eq!(bytes, Bytes::from(data));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_reading_deflate_encoding_large_random() {
|
||||||
|
let data = rand::thread_rng()
|
||||||
|
.gen_ascii_chars()
|
||||||
|
.take(160_000)
|
||||||
|
.collect::<String>();
|
||||||
|
|
||||||
|
let mut srv = test::TestServer::new(|app| app.handler(|req: HttpRequest| {
|
||||||
|
req.body()
|
||||||
|
.and_then(|bytes: Bytes| {
|
||||||
|
Ok(httpcodes::HTTPOk
|
||||||
|
.build()
|
||||||
|
.content_encoding(headers::ContentEncoding::Identity)
|
||||||
|
.body(bytes))
|
||||||
|
}).responder()}
|
||||||
|
));
|
||||||
|
|
||||||
|
let mut e = DeflateEncoder::new(Vec::new(), Compression::default());
|
||||||
|
e.write_all(data.as_ref()).unwrap();
|
||||||
|
let enc = e.finish().unwrap();
|
||||||
|
|
||||||
|
// client request
|
||||||
|
let request = srv.post()
|
||||||
|
.header(header::CONTENT_ENCODING, "deflate")
|
||||||
|
.body(enc).unwrap();
|
||||||
|
let response = srv.execute(request.send()).unwrap();
|
||||||
|
assert!(response.status().is_success());
|
||||||
|
|
||||||
|
// read response
|
||||||
|
let bytes = srv.execute(response.body()).unwrap();
|
||||||
|
assert_eq!(bytes.len(), data.len());
|
||||||
|
assert_eq!(bytes, Bytes::from(data));
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_brotli_encoding() {
|
fn test_brotli_encoding() {
|
||||||
let mut srv = test::TestServer::new(|app| app.handler(|req: HttpRequest| {
|
let mut srv = test::TestServer::new(|app| app.handler(|req: HttpRequest| {
|
||||||
|
|
Loading…
Reference in a new issue