mirror of
https://github.com/fafhrd91/actix-web
synced 2025-04-20 20:27:01 +02:00
Compare commits
5 Commits
master
...
http-v2.2.
Author | SHA1 | Date | |
---|---|---|---|
|
bc54cdd772 | ||
|
ad7e3c06e7 | ||
|
0669ed0f06 | ||
|
c9c36679e4 | ||
|
655d7b4f05 |
@ -3,6 +3,13 @@
|
|||||||
## Unreleased - 2020-xx-xx
|
## Unreleased - 2020-xx-xx
|
||||||
|
|
||||||
|
|
||||||
|
## 3.3.3 - 2021-12-18
|
||||||
|
### Changed
|
||||||
|
* Soft-deprecate `NormalizePath::default()`, noting upcoming behavior change in v4. [#2529]
|
||||||
|
|
||||||
|
[#2529]: https://github.com/actix/actix-web/pull/2529
|
||||||
|
|
||||||
|
|
||||||
## 3.3.2 - 2020-12-01
|
## 3.3.2 - 2020-12-01
|
||||||
### Fixed
|
### Fixed
|
||||||
* Removed an occasional `unwrap` on `None` panic in `NormalizePathNormalization`. [#1762]
|
* Removed an occasional `unwrap` on `None` panic in `NormalizePathNormalization`. [#1762]
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "actix-web"
|
name = "actix-web"
|
||||||
version = "3.3.2"
|
version = "3.3.3"
|
||||||
authors = ["Nikolay Kim <fafhrd91@gmail.com>"]
|
authors = ["Nikolay Kim <fafhrd91@gmail.com>"]
|
||||||
description = "Actix Web is a powerful, pragmatic, and extremely fast web framework for Rust"
|
description = "Actix Web is a powerful, pragmatic, and extremely fast web framework for Rust"
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
@ -115,7 +115,7 @@ actix-http = { version = "2.1.0", features = ["actors"] }
|
|||||||
rand = "0.7"
|
rand = "0.7"
|
||||||
env_logger = "0.8"
|
env_logger = "0.8"
|
||||||
serde_derive = "1.0"
|
serde_derive = "1.0"
|
||||||
brotli2 = "0.3.2"
|
brotli = "3.3.3"
|
||||||
flate2 = "1.0.13"
|
flate2 = "1.0.13"
|
||||||
criterion = "0.3"
|
criterion = "0.3"
|
||||||
|
|
||||||
|
@ -6,10 +6,10 @@
|
|||||||
<p>
|
<p>
|
||||||
|
|
||||||
[](https://crates.io/crates/actix-web)
|
[](https://crates.io/crates/actix-web)
|
||||||
[](https://docs.rs/actix-web/3.3.2)
|
[](https://docs.rs/actix-web/3.3.3)
|
||||||
[](https://blog.rust-lang.org/2020/03/12/Rust-1.42.html)
|
[](https://blog.rust-lang.org/2020/03/12/Rust-1.42.html)
|
||||||

|

|
||||||
[](https://deps.rs/crate/actix-web/3.3.2)
|
[](https://deps.rs/crate/actix-web/3.3.3)
|
||||||
<br />
|
<br />
|
||||||
[](https://travis-ci.org/actix/actix-web)
|
[](https://travis-ci.org/actix/actix-web)
|
||||||
[](https://codecov.io/gh/actix/actix-web)
|
[](https://codecov.io/gh/actix/actix-web)
|
||||||
|
@ -3,6 +3,18 @@
|
|||||||
## Unreleased - 2020-xx-xx
|
## Unreleased - 2020-xx-xx
|
||||||
|
|
||||||
|
|
||||||
|
## 2.2.2 - 2022-01-21
|
||||||
|
### Changed
|
||||||
|
- Migrate to `brotli` crate. [ad7e3c06]
|
||||||
|
|
||||||
|
[ad7e3c06]: https://github.com/actix/actix-web/commit/ad7e3c06
|
||||||
|
|
||||||
|
|
||||||
|
## 2.2.1 - 2021-08-09
|
||||||
|
### Fixed
|
||||||
|
- Potential HTTP request smuggling vulnerabilities. [RUSTSEC-2021-0081](https://github.com/rustsec/advisory-db/pull/977)
|
||||||
|
|
||||||
|
|
||||||
## 2.2.0 - 2020-11-25
|
## 2.2.0 - 2020-11-25
|
||||||
### Added
|
### Added
|
||||||
* HttpResponse builders for 1xx status codes. [#1768]
|
* HttpResponse builders for 1xx status codes. [#1768]
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "actix-http"
|
name = "actix-http"
|
||||||
version = "2.2.0"
|
version = "2.2.2"
|
||||||
authors = ["Nikolay Kim <fafhrd91@gmail.com>"]
|
authors = ["Nikolay Kim <fafhrd91@gmail.com>"]
|
||||||
description = "HTTP primitives for the Actix ecosystem"
|
description = "HTTP primitives for the Actix ecosystem"
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
@ -31,7 +31,7 @@ openssl = ["actix-tls/openssl", "actix-connect/openssl"]
|
|||||||
rustls = ["actix-tls/rustls", "actix-connect/rustls"]
|
rustls = ["actix-tls/rustls", "actix-connect/rustls"]
|
||||||
|
|
||||||
# enable compressison support
|
# enable compressison support
|
||||||
compress = ["flate2", "brotli2"]
|
compress = ["flate2", "brotli"]
|
||||||
|
|
||||||
# support for secure cookies
|
# support for secure cookies
|
||||||
secure-cookies = ["cookie/secure"]
|
secure-cookies = ["cookie/secure"]
|
||||||
@ -82,7 +82,7 @@ serde_urlencoded = "0.7"
|
|||||||
time = { version = "0.2.7", default-features = false, features = ["std"] }
|
time = { version = "0.2.7", default-features = false, features = ["std"] }
|
||||||
|
|
||||||
# compression
|
# compression
|
||||||
brotli2 = { version="0.3.2", optional = true }
|
brotli = { version = "3.3.3", optional = true }
|
||||||
flate2 = { version = "1.0.13", optional = true }
|
flate2 = { version = "1.0.13", optional = true }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
|
@ -3,9 +3,9 @@
|
|||||||
> HTTP primitives for the Actix ecosystem.
|
> HTTP primitives for the Actix ecosystem.
|
||||||
|
|
||||||
[](https://crates.io/crates/actix-http)
|
[](https://crates.io/crates/actix-http)
|
||||||
[](https://docs.rs/actix-http/2.2.0)
|
[](https://docs.rs/actix-http/2.2.2)
|
||||||

|

|
||||||
[](https://deps.rs/crate/actix-http/2.2.0)
|
[](https://deps.rs/crate/actix-http/2.2.2)
|
||||||
[](https://gitter.im/actix/actix-web?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
[](https://gitter.im/actix/actix-web?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
||||||
|
|
||||||
## Documentation & Resources
|
## Documentation & Resources
|
||||||
|
@ -4,7 +4,7 @@ use std::pin::Pin;
|
|||||||
use std::task::{Context, Poll};
|
use std::task::{Context, Poll};
|
||||||
|
|
||||||
use actix_threadpool::{run, CpuFuture};
|
use actix_threadpool::{run, CpuFuture};
|
||||||
use brotli2::write::BrotliDecoder;
|
use brotli::DecompressorWriter as BrotliDecoder;
|
||||||
use bytes::Bytes;
|
use bytes::Bytes;
|
||||||
use flate2::write::{GzDecoder, ZlibDecoder};
|
use flate2::write::{GzDecoder, ZlibDecoder};
|
||||||
use futures_core::{ready, Stream};
|
use futures_core::{ready, Stream};
|
||||||
@ -31,7 +31,7 @@ where
|
|||||||
pub fn new(stream: S, encoding: ContentEncoding) -> Decoder<S> {
|
pub fn new(stream: S, encoding: ContentEncoding) -> Decoder<S> {
|
||||||
let decoder = match encoding {
|
let decoder = match encoding {
|
||||||
ContentEncoding::Br => Some(ContentDecoder::Br(Box::new(
|
ContentEncoding::Br => Some(ContentDecoder::Br(Box::new(
|
||||||
BrotliDecoder::new(Writer::new()),
|
BrotliDecoder::new(Writer::new(), 8 * 1024),
|
||||||
))),
|
))),
|
||||||
ContentEncoding::Deflate => Some(ContentDecoder::Deflate(Box::new(
|
ContentEncoding::Deflate => Some(ContentDecoder::Deflate(Box::new(
|
||||||
ZlibDecoder::new(Writer::new()),
|
ZlibDecoder::new(Writer::new()),
|
||||||
|
@ -5,7 +5,7 @@ use std::pin::Pin;
|
|||||||
use std::task::{Context, Poll};
|
use std::task::{Context, Poll};
|
||||||
|
|
||||||
use actix_threadpool::{run, CpuFuture};
|
use actix_threadpool::{run, CpuFuture};
|
||||||
use brotli2::write::BrotliEncoder;
|
use brotli::CompressorWriter as BrotliEncoder;
|
||||||
use bytes::Bytes;
|
use bytes::Bytes;
|
||||||
use flate2::write::{GzEncoder, ZlibEncoder};
|
use flate2::write::{GzEncoder, ZlibEncoder};
|
||||||
use futures_core::ready;
|
use futures_core::ready;
|
||||||
@ -212,9 +212,12 @@ impl ContentEncoder {
|
|||||||
Writer::new(),
|
Writer::new(),
|
||||||
flate2::Compression::fast(),
|
flate2::Compression::fast(),
|
||||||
))),
|
))),
|
||||||
ContentEncoding::Br => {
|
ContentEncoding::Br => Some(ContentEncoder::Br(BrotliEncoder::new(
|
||||||
Some(ContentEncoder::Br(BrotliEncoder::new(Writer::new(), 3)))
|
Writer::new(),
|
||||||
}
|
32 * 1024,
|
||||||
|
3,
|
||||||
|
22,
|
||||||
|
))),
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -230,8 +233,8 @@ impl ContentEncoder {
|
|||||||
|
|
||||||
fn finish(self) -> Result<Bytes, io::Error> {
|
fn finish(self) -> Result<Bytes, io::Error> {
|
||||||
match self {
|
match self {
|
||||||
ContentEncoder::Br(encoder) => match encoder.finish() {
|
ContentEncoder::Br(mut encoder) => match encoder.flush() {
|
||||||
Ok(writer) => Ok(writer.buf.freeze()),
|
Ok(()) => Ok(encoder.into_inner().buf.freeze()),
|
||||||
Err(err) => Err(err),
|
Err(err) => Err(err),
|
||||||
},
|
},
|
||||||
ContentEncoder::Gzip(encoder) => match encoder.finish() {
|
ContentEncoder::Gzip(encoder) => match encoder.finish() {
|
||||||
|
@ -55,7 +55,7 @@ impl Error {
|
|||||||
|
|
||||||
/// Similar to `as_response_error` but downcasts.
|
/// Similar to `as_response_error` but downcasts.
|
||||||
pub fn as_error<T: ResponseError + 'static>(&self) -> Option<&T> {
|
pub fn as_error<T: ResponseError + 'static>(&self) -> Option<&T> {
|
||||||
ResponseError::downcast_ref(self.cause.as_ref())
|
<dyn ResponseError>::downcast_ref(self.cause.as_ref())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -67,6 +67,7 @@ pub(crate) trait MessageType: Sized {
|
|||||||
let mut has_upgrade_websocket = false;
|
let mut has_upgrade_websocket = false;
|
||||||
let mut expect = false;
|
let mut expect = false;
|
||||||
let mut chunked = false;
|
let mut chunked = false;
|
||||||
|
let mut seen_te = false;
|
||||||
let mut content_length = None;
|
let mut content_length = None;
|
||||||
|
|
||||||
{
|
{
|
||||||
@ -85,8 +86,17 @@ pub(crate) trait MessageType: Sized {
|
|||||||
};
|
};
|
||||||
|
|
||||||
match name {
|
match name {
|
||||||
header::CONTENT_LENGTH => {
|
header::CONTENT_LENGTH if content_length.is_some() => {
|
||||||
if let Ok(s) = value.to_str() {
|
debug!("multiple Content-Length");
|
||||||
|
return Err(ParseError::Header);
|
||||||
|
}
|
||||||
|
|
||||||
|
header::CONTENT_LENGTH => match value.to_str() {
|
||||||
|
Ok(s) if s.trim().starts_with("+") => {
|
||||||
|
debug!("illegal Content-Length: {:?}", s);
|
||||||
|
return Err(ParseError::Header);
|
||||||
|
}
|
||||||
|
Ok(s) => {
|
||||||
if let Ok(len) = s.parse::<u64>() {
|
if let Ok(len) = s.parse::<u64>() {
|
||||||
if len != 0 {
|
if len != 0 {
|
||||||
content_length = Some(len);
|
content_length = Some(len);
|
||||||
@ -95,15 +105,31 @@ pub(crate) trait MessageType: Sized {
|
|||||||
debug!("illegal Content-Length: {:?}", s);
|
debug!("illegal Content-Length: {:?}", s);
|
||||||
return Err(ParseError::Header);
|
return Err(ParseError::Header);
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
|
Err(_) => {
|
||||||
debug!("illegal Content-Length: {:?}", value);
|
debug!("illegal Content-Length: {:?}", value);
|
||||||
return Err(ParseError::Header);
|
return Err(ParseError::Header);
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
|
||||||
// transfer-encoding
|
// transfer-encoding
|
||||||
|
header::TRANSFER_ENCODING if seen_te => {
|
||||||
|
debug!("multiple Transfer-Encoding not allowed");
|
||||||
|
return Err(ParseError::Header);
|
||||||
|
}
|
||||||
|
|
||||||
header::TRANSFER_ENCODING => {
|
header::TRANSFER_ENCODING => {
|
||||||
|
seen_te = true;
|
||||||
|
|
||||||
if let Ok(s) = value.to_str().map(|s| s.trim()) {
|
if let Ok(s) = value.to_str().map(|s| s.trim()) {
|
||||||
chunked = s.eq_ignore_ascii_case("chunked");
|
if s.eq_ignore_ascii_case("chunked") {
|
||||||
|
chunked = true;
|
||||||
|
} else if s.eq_ignore_ascii_case("identity") {
|
||||||
|
// allow silently since multiple TE headers are already checked
|
||||||
|
} else {
|
||||||
|
debug!("illegal Transfer-Encoding: {:?}", s);
|
||||||
|
return Err(ParseError::Header);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
return Err(ParseError::Header);
|
return Err(ParseError::Header);
|
||||||
}
|
}
|
||||||
@ -510,19 +536,11 @@ impl ChunkedState {
|
|||||||
size: &mut u64,
|
size: &mut u64,
|
||||||
) -> Poll<Result<ChunkedState, io::Error>> {
|
) -> Poll<Result<ChunkedState, io::Error>> {
|
||||||
let radix = 16;
|
let radix = 16;
|
||||||
match byte!(rdr) {
|
|
||||||
b @ b'0'..=b'9' => {
|
let rem = match byte!(rdr) {
|
||||||
*size *= radix;
|
b @ b'0'..=b'9' => b - b'0',
|
||||||
*size += u64::from(b - b'0');
|
b @ b'a'..=b'f' => b + 10 - b'a',
|
||||||
}
|
b @ b'A'..=b'F' => b + 10 - b'A',
|
||||||
b @ b'a'..=b'f' => {
|
|
||||||
*size *= radix;
|
|
||||||
*size += u64::from(b + 10 - b'a');
|
|
||||||
}
|
|
||||||
b @ b'A'..=b'F' => {
|
|
||||||
*size *= radix;
|
|
||||||
*size += u64::from(b + 10 - b'A');
|
|
||||||
}
|
|
||||||
b'\t' | b' ' => return Poll::Ready(Ok(ChunkedState::SizeLws)),
|
b'\t' | b' ' => return Poll::Ready(Ok(ChunkedState::SizeLws)),
|
||||||
b';' => return Poll::Ready(Ok(ChunkedState::Extension)),
|
b';' => return Poll::Ready(Ok(ChunkedState::Extension)),
|
||||||
b'\r' => return Poll::Ready(Ok(ChunkedState::SizeLf)),
|
b'\r' => return Poll::Ready(Ok(ChunkedState::SizeLf)),
|
||||||
@ -532,8 +550,23 @@ impl ChunkedState {
|
|||||||
"Invalid chunk size line: Invalid Size",
|
"Invalid chunk size line: Invalid Size",
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
match size.checked_mul(radix) {
|
||||||
|
Some(n) => {
|
||||||
|
*size = n as u64;
|
||||||
|
*size += rem as u64;
|
||||||
|
|
||||||
|
Poll::Ready(Ok(ChunkedState::Size))
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
debug!("chunk size would overflow");
|
||||||
|
Poll::Ready(Err(io::Error::new(
|
||||||
|
io::ErrorKind::InvalidInput,
|
||||||
|
"Invalid chunk size line: Invalid Size",
|
||||||
|
)))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Poll::Ready(Ok(ChunkedState::Size))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn read_size_lws(rdr: &mut BytesMut) -> Poll<Result<ChunkedState, io::Error>> {
|
fn read_size_lws(rdr: &mut BytesMut) -> Poll<Result<ChunkedState, io::Error>> {
|
||||||
@ -552,6 +585,11 @@ impl ChunkedState {
|
|||||||
fn read_extension(rdr: &mut BytesMut) -> Poll<Result<ChunkedState, io::Error>> {
|
fn read_extension(rdr: &mut BytesMut) -> Poll<Result<ChunkedState, io::Error>> {
|
||||||
match byte!(rdr) {
|
match byte!(rdr) {
|
||||||
b'\r' => Poll::Ready(Ok(ChunkedState::SizeLf)),
|
b'\r' => Poll::Ready(Ok(ChunkedState::SizeLf)),
|
||||||
|
// strictly 0x20 (space) should be disallowed but we don't parse quoted strings here
|
||||||
|
0x00..=0x08 | 0x0a..=0x1f | 0x7f => Poll::Ready(Err(io::Error::new(
|
||||||
|
io::ErrorKind::InvalidInput,
|
||||||
|
"Invalid character in chunk extension",
|
||||||
|
))),
|
||||||
_ => Poll::Ready(Ok(ChunkedState::Extension)), // no supported extensions
|
_ => Poll::Ready(Ok(ChunkedState::Extension)), // no supported extensions
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -977,13 +1015,7 @@ mod tests {
|
|||||||
"GET /test HTTP/1.1\r\n\
|
"GET /test HTTP/1.1\r\n\
|
||||||
transfer-encoding: chnked\r\n\r\n",
|
transfer-encoding: chnked\r\n\r\n",
|
||||||
);
|
);
|
||||||
let req = parse_ready!(&mut buf);
|
expect_parse_err!(&mut buf);
|
||||||
|
|
||||||
if let Ok(val) = req.chunked() {
|
|
||||||
assert!(!val);
|
|
||||||
} else {
|
|
||||||
unreachable!("Error");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -80,6 +80,7 @@ pub(crate) trait MessageType: Sized {
|
|||||||
match length {
|
match length {
|
||||||
BodySize::Stream => {
|
BodySize::Stream => {
|
||||||
if chunked {
|
if chunked {
|
||||||
|
skip_len = true;
|
||||||
if camel_case {
|
if camel_case {
|
||||||
dst.put_slice(b"\r\nTransfer-Encoding: chunked\r\n")
|
dst.put_slice(b"\r\nTransfer-Encoding: chunked\r\n")
|
||||||
} else {
|
} else {
|
||||||
|
@ -65,7 +65,7 @@ actix-http-test = { version = "2.0.0", features = ["openssl"] }
|
|||||||
actix-utils = "2.0.0"
|
actix-utils = "2.0.0"
|
||||||
actix-server = "1.0.0"
|
actix-server = "1.0.0"
|
||||||
actix-tls = { version = "2.0.0", features = ["openssl", "rustls"] }
|
actix-tls = { version = "2.0.0", features = ["openssl", "rustls"] }
|
||||||
brotli2 = "0.3.2"
|
brotli = "3.3.3"
|
||||||
flate2 = "1.0.13"
|
flate2 = "1.0.13"
|
||||||
futures-util = { version = "0.3.5", default-features = false }
|
futures-util = { version = "0.3.5", default-features = false }
|
||||||
env_logger = "0.7"
|
env_logger = "0.7"
|
||||||
|
@ -4,7 +4,7 @@ use std::sync::atomic::{AtomicUsize, Ordering};
|
|||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
use brotli2::write::BrotliEncoder;
|
use brotli::CompressorWriter as BrotliEncoder;
|
||||||
use bytes::Bytes;
|
use bytes::Bytes;
|
||||||
use flate2::read::GzDecoder;
|
use flate2::read::GzDecoder;
|
||||||
use flate2::write::GzEncoder;
|
use flate2::write::GzEncoder;
|
||||||
@ -506,9 +506,10 @@ async fn test_client_gzip_encoding_large_random() {
|
|||||||
async fn test_client_brotli_encoding() {
|
async fn test_client_brotli_encoding() {
|
||||||
let srv = test::start(|| {
|
let srv = test::start(|| {
|
||||||
App::new().service(web::resource("/").route(web::to(|data: Bytes| {
|
App::new().service(web::resource("/").route(web::to(|data: Bytes| {
|
||||||
let mut e = BrotliEncoder::new(Vec::new(), 5);
|
let mut e = BrotliEncoder::new(Vec::new(), 8096, 5, 22);
|
||||||
e.write_all(&data).unwrap();
|
e.write_all(&data).unwrap();
|
||||||
let data = e.finish().unwrap();
|
e.flush().unwrap();
|
||||||
|
let data = e.into_inner();
|
||||||
HttpResponse::Ok()
|
HttpResponse::Ok()
|
||||||
.header("content-encoding", "br")
|
.header("content-encoding", "br")
|
||||||
.body(data)
|
.body(data)
|
||||||
@ -533,9 +534,9 @@ async fn test_client_brotli_encoding_large_random() {
|
|||||||
|
|
||||||
let srv = test::start(|| {
|
let srv = test::start(|| {
|
||||||
App::new().service(web::resource("/").route(web::to(|data: Bytes| {
|
App::new().service(web::resource("/").route(web::to(|data: Bytes| {
|
||||||
let mut e = BrotliEncoder::new(Vec::new(), 5);
|
let mut e = BrotliEncoder::new(Vec::new(), 8096, 5, 22);
|
||||||
e.write_all(&data).unwrap();
|
e.write_all(&data).unwrap();
|
||||||
let data = e.finish().unwrap();
|
let data = e.into_inner();
|
||||||
HttpResponse::Ok()
|
HttpResponse::Ok()
|
||||||
.header("content-encoding", "br")
|
.header("content-encoding", "br")
|
||||||
.body(data)
|
.body(data)
|
||||||
|
@ -31,7 +31,7 @@ impl Default for TrailingSlash {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default, Clone, Copy)]
|
#[derive(Clone, Copy)]
|
||||||
/// `Middleware` to normalize request's URI in place
|
/// `Middleware` to normalize request's URI in place
|
||||||
///
|
///
|
||||||
/// Performs following:
|
/// Performs following:
|
||||||
@ -56,6 +56,18 @@ impl Default for TrailingSlash {
|
|||||||
|
|
||||||
pub struct NormalizePath(TrailingSlash);
|
pub struct NormalizePath(TrailingSlash);
|
||||||
|
|
||||||
|
impl Default for NormalizePath {
|
||||||
|
fn default() -> Self {
|
||||||
|
log::warn!(
|
||||||
|
"`NormalizePath::default()` is deprecated. The default trailing slash behavior will \
|
||||||
|
change in v4 from `Always` to `Trim`. Update your call to `NormalizePath::new(...)` to \
|
||||||
|
avoid inaccessible routes when upgrading."
|
||||||
|
);
|
||||||
|
|
||||||
|
Self(TrailingSlash::default())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl NormalizePath {
|
impl NormalizePath {
|
||||||
/// Create new `NormalizePath` middleware with the specified trailing slash style.
|
/// Create new `NormalizePath` middleware with the specified trailing slash style.
|
||||||
pub fn new(trailing_slash_style: TrailingSlash) -> Self {
|
pub fn new(trailing_slash_style: TrailingSlash) -> Self {
|
||||||
|
@ -7,7 +7,8 @@ use actix_http::http::header::{
|
|||||||
ContentEncoding, ACCEPT_ENCODING, CONTENT_ENCODING, CONTENT_LENGTH,
|
ContentEncoding, ACCEPT_ENCODING, CONTENT_ENCODING, CONTENT_LENGTH,
|
||||||
TRANSFER_ENCODING,
|
TRANSFER_ENCODING,
|
||||||
};
|
};
|
||||||
use brotli2::write::{BrotliDecoder, BrotliEncoder};
|
|
||||||
|
use brotli::{CompressorWriter as BrotliEncoder, DecompressorWriter as BrotliDecoder};
|
||||||
use bytes::Bytes;
|
use bytes::Bytes;
|
||||||
use flate2::read::GzDecoder;
|
use flate2::read::GzDecoder;
|
||||||
use flate2::write::{GzEncoder, ZlibDecoder, ZlibEncoder};
|
use flate2::write::{GzEncoder, ZlibDecoder, ZlibEncoder};
|
||||||
@ -340,9 +341,9 @@ async fn test_body_br_streaming() {
|
|||||||
println!("TEST: {:?}", bytes.len());
|
println!("TEST: {:?}", bytes.len());
|
||||||
|
|
||||||
// decode br
|
// decode br
|
||||||
let mut e = BrotliDecoder::new(Vec::with_capacity(2048));
|
let mut e = BrotliDecoder::new(Vec::with_capacity(2048), 8096);
|
||||||
e.write_all(bytes.as_ref()).unwrap();
|
e.write_all(bytes.as_ref()).unwrap();
|
||||||
let dec = e.finish().unwrap();
|
let dec = e.into_inner().unwrap();
|
||||||
println!("T: {:?}", Bytes::copy_from_slice(&dec));
|
println!("T: {:?}", Bytes::copy_from_slice(&dec));
|
||||||
assert_eq!(Bytes::from(dec), Bytes::from_static(STR.as_ref()));
|
assert_eq!(Bytes::from(dec), Bytes::from_static(STR.as_ref()));
|
||||||
}
|
}
|
||||||
@ -439,9 +440,9 @@ async fn test_body_brotli() {
|
|||||||
let bytes = response.body().await.unwrap();
|
let bytes = response.body().await.unwrap();
|
||||||
|
|
||||||
// decode brotli
|
// decode brotli
|
||||||
let mut e = BrotliDecoder::new(Vec::with_capacity(2048));
|
let mut e = BrotliDecoder::new(Vec::with_capacity(2048), 8096);
|
||||||
e.write_all(bytes.as_ref()).unwrap();
|
e.write_all(bytes.as_ref()).unwrap();
|
||||||
let dec = e.finish().unwrap();
|
let dec = e.into_inner().unwrap();
|
||||||
assert_eq!(Bytes::from(dec), Bytes::from_static(STR.as_ref()));
|
assert_eq!(Bytes::from(dec), Bytes::from_static(STR.as_ref()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -650,9 +651,10 @@ async fn test_brotli_encoding() {
|
|||||||
)
|
)
|
||||||
});
|
});
|
||||||
|
|
||||||
let mut e = BrotliEncoder::new(Vec::new(), 5);
|
let mut e = BrotliEncoder::new(Vec::new(), 8096, 5, 22);
|
||||||
e.write_all(STR.as_ref()).unwrap();
|
e.write_all(STR.as_ref()).unwrap();
|
||||||
let enc = e.finish().unwrap();
|
e.flush().unwrap();
|
||||||
|
let enc = e.into_inner();
|
||||||
|
|
||||||
// client request
|
// client request
|
||||||
let request = srv
|
let request = srv
|
||||||
@ -684,9 +686,10 @@ async fn test_brotli_encoding_large() {
|
|||||||
)
|
)
|
||||||
});
|
});
|
||||||
|
|
||||||
let mut e = BrotliEncoder::new(Vec::new(), 5);
|
let mut e = BrotliEncoder::new(Vec::new(), 8096, 5, 22);
|
||||||
e.write_all(data.as_ref()).unwrap();
|
e.write_all(data.as_ref()).unwrap();
|
||||||
let enc = e.finish().unwrap();
|
e.flush().unwrap();
|
||||||
|
let enc = e.into_inner();
|
||||||
|
|
||||||
// client request
|
// client request
|
||||||
let request = srv
|
let request = srv
|
||||||
@ -724,9 +727,9 @@ async fn test_brotli_encoding_large_openssl() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// body
|
// body
|
||||||
let mut e = BrotliEncoder::new(Vec::new(), 3);
|
let mut e = BrotliEncoder::new(Vec::new(), 8096, 5, 22);
|
||||||
e.write_all(data.as_ref()).unwrap();
|
e.write_all(data.as_ref()).unwrap();
|
||||||
let enc = e.finish().unwrap();
|
let enc = e.into_inner();
|
||||||
|
|
||||||
// client request
|
// client request
|
||||||
let mut response = srv
|
let mut response = srv
|
||||||
|
Loading…
x
Reference in New Issue
Block a user