update changelogs

This commit is contained in:
Rob Ede 2022-01-02 11:57:17 +00:00
parent fb63ebe5f7
commit 4468d7d153
No known key found for this signature in database
GPG Key ID: 97C636207D3EF933
6 changed files with 141 additions and 142 deletions

View File

@ -1,6 +1,22 @@
# Changes # Changes
## Unreleased - 2021-xx-xx ## Unreleased - 2021-xx-xx
### Added
- `impl Hash` for `http::header::Encoding`. [#2501]
- `AcceptEncoding::negotiate()`. [#2501]
### Changed
- `AcceptEncoding::preference` now returns `Option<Preference<Encoding>>`. [#2501]
- Rename methods `BodyEncoding::{encoding => encode_with, get_encoding => preferred_encoding}`. [#2501]
- `http::header::Encoding` now only represents `Content-Encoding` types. [#2501]
### Fixed
- Auto-negotiation of content encoding is more fault-tolerant when using the `Compress` middleware. [#2501]
### Removed
- `Compress::new`; restricting compression algorithm is done through feature flags. [#2501]
[#2501]: https://github.com/actix/actix-web/pull/2501
## 4.0.0-beta.18 - 2021-12-29 ## 4.0.0-beta.18 - 2021-12-29
@ -19,22 +35,18 @@
### Added ### Added
- `guard::GuardContext` for use with the `Guard` trait. [#2552] - `guard::GuardContext` for use with the `Guard` trait. [#2552]
- `ServiceRequest::guard_ctx` for obtaining a guard context. [#2552] - `ServiceRequest::guard_ctx` for obtaining a guard context. [#2552]
- `impl Hash` for `http::header::Encoding`. [#2501]
- `AcceptEncoding::negotiate`. [#2501]
### Changed ### Changed
- `Guard` trait now receives a `&GuardContext`. [#2552] - `Guard` trait now receives a `&GuardContext`. [#2552]
- `guard::fn_guard` functions now receives a `&GuardContext`. [#2552] - `guard::fn_guard` functions now receives a `&GuardContext`. [#2552]
- Some guards now return `impl Guard` and their concrete types are made private: `guard::Header` and all the method guards. [#2552] - Some guards now return `impl Guard` and their concrete types are made private: `guard::Header` and all the method guards. [#2552]
- The `Not` guard is now generic over the type of guard it wraps. [#2552] - The `Not` guard is now generic over the type of guard it wraps. [#2552]
- `AcceptEncoding::preference` now returns `Option<Preference<Encoding>>`. [#2501]
### Fixed ### Fixed
- Rename `ConnectionInfo::{remote_addr => peer_addr}`, deprecating the old name. [#2554] - Rename `ConnectionInfo::{remote_addr => peer_addr}`, deprecating the old name. [#2554]
- `ConnectionInfo::peer_addr` will not return the port number. [#2554] - `ConnectionInfo::peer_addr` will not return the port number. [#2554]
- `ConnectionInfo::realip_remote_addr` will not return the port number if sourcing the IP from the peer's socket address. [#2554] - `ConnectionInfo::realip_remote_addr` will not return the port number if sourcing the IP from the peer's socket address. [#2554]
[#2501]: https://github.com/actix/actix-web/pull/2501
[#2552]: https://github.com/actix/actix-web/pull/2552 [#2552]: https://github.com/actix/actix-web/pull/2552
[#2554]: https://github.com/actix/actix-web/pull/2554 [#2554]: https://github.com/actix/actix-web/pull/2554

View File

@ -6,12 +6,22 @@
- `impl Copy` for `QualityItem` where `T: Copy`. [#2501] - `impl Copy` for `QualityItem` where `T: Copy`. [#2501]
- `Quality::ZERO` equivalent to `q=0`. [#2501] - `Quality::ZERO` equivalent to `q=0`. [#2501]
- `QualityItem::zero` that uses `Quality::ZERO`. [#2501] - `QualityItem::zero` that uses `Quality::ZERO`. [#2501]
- `ContentEncoding::to_header_value()`. [#2501]
### Changed ### Changed
- `Quality::MIN` is now the smallest non-zero value. [#2501] - `Quality::MIN` is now the smallest non-zero value. [#2501]
- `QualityItem::min` has different semantics due to the `QualityItem::MIN` change. [#2501] - `QualityItem::min` semantics changed with `QualityItem::MIN`. [#2501]
- Rename `ContentEncoding::{Br => Brotli}`. [#2501]
- Minimum supported Rust version (MSRV) is now 1.54. - Minimum supported Rust version (MSRV) is now 1.54.
### Fixed
- `ContentEncoding::Identity` can now be parsed from a string. [#2501]
- A `Vary` header is now correctly sent along with compressed content. [#2501]
### Removed
- `ContentEncoding::Auto` variant. [#2501]
- `ContentEncoding::is_compression()`. [#2501]
[#2501]: https://github.com/actix/actix-web/pull/2501 [#2501]: https://github.com/actix/actix-web/pull/2501

View File

@ -60,18 +60,19 @@ pub trait BodyEncoding {
/// [`Compress`]: crate::middleware::Compress /// [`Compress`]: crate::middleware::Compress
fn encode_with(&mut self, encoding: ContentEncoding) -> &mut Self; fn encode_with(&mut self, encoding: ContentEncoding) -> &mut Self;
/// Flags that a file already is encoded so that [`Compress`] does not modify it. // /// Flags that a file already is encoded so that [`Compress`] does not modify it.
/// // ///
/// Effectively a shortcut for `compress_with("identity")` // /// Effectively a shortcut for `compress_with("identity")`
/// plus `insert_header(ContentEncoding, encoding)`. // /// plus `insert_header(ContentEncoding, encoding)`.
/// // ///
/// [`Compress`]: crate::middleware::Compress // /// [`Compress`]: crate::middleware::Compress
fn pre_encoded_with(&mut self, encoding: ContentEncoding) -> &mut Self; // fn pre_encoded_with(&mut self, encoding: ContentEncoding) -> &mut Self;
} }
struct CompressWith(ContentEncoding); struct CompressWith(ContentEncoding);
struct PreCompressed(ContentEncoding); // TODO: add or delete this
// struct PreCompressed(ContentEncoding);
impl BodyEncoding for crate::HttpResponseBuilder { impl BodyEncoding for crate::HttpResponseBuilder {
fn preferred_encoding(&self) -> Option<ContentEncoding> { fn preferred_encoding(&self) -> Option<ContentEncoding> {
@ -83,10 +84,10 @@ impl BodyEncoding for crate::HttpResponseBuilder {
self self
} }
fn pre_encoded_with(&mut self, encoding: ContentEncoding) -> &mut Self { // fn pre_encoded_with(&mut self, encoding: ContentEncoding) -> &mut Self {
self.extensions_mut().insert(PreCompressed(encoding)); // self.extensions_mut().insert(PreCompressed(encoding));
self // self
} // }
} }
impl<B> BodyEncoding for crate::HttpResponse<B> { impl<B> BodyEncoding for crate::HttpResponse<B> {
@ -99,10 +100,10 @@ impl<B> BodyEncoding for crate::HttpResponse<B> {
self self
} }
fn pre_encoded_with(&mut self, encoding: ContentEncoding) -> &mut Self { // fn pre_encoded_with(&mut self, encoding: ContentEncoding) -> &mut Self {
self.extensions_mut().insert(PreCompressed(encoding)); // self.extensions_mut().insert(PreCompressed(encoding));
self // self
} // }
} }
impl<B> BodyEncoding for ServiceResponse<B> { impl<B> BodyEncoding for ServiceResponse<B> {
@ -120,32 +121,33 @@ impl<B> BodyEncoding for ServiceResponse<B> {
self self
} }
fn pre_encoded_with(&mut self, encoding: ContentEncoding) -> &mut Self { // fn pre_encoded_with(&mut self, encoding: ContentEncoding) -> &mut Self {
self.request() // self.request()
.extensions_mut() // .extensions_mut()
.insert(PreCompressed(encoding)); // .insert(PreCompressed(encoding));
// self
// }
}
// TODO: remove these impls ?
impl BodyEncoding for actix_http::ResponseBuilder {
fn preferred_encoding(&self) -> Option<ContentEncoding> {
self.extensions().get::<CompressWith>().map(|enc| enc.0)
}
fn encode_with(&mut self, encoding: ContentEncoding) -> &mut Self {
self.extensions_mut().insert(CompressWith(encoding));
self self
} }
} }
// impl BodyEncoding for actix_http::ResponseBuilder { impl<B> BodyEncoding for actix_http::Response<B> {
// fn get_encoding(&self) -> Option<ContentEncoding> { fn preferred_encoding(&self) -> Option<ContentEncoding> {
// self.extensions().get::<Enc>().map(|enc| enc.0) self.extensions().get::<CompressWith>().map(|enc| enc.0)
// } }
// fn compress_with(&mut self, encoding: ContentEncoding) -> &mut Self { fn encode_with(&mut self, encoding: ContentEncoding) -> &mut Self {
// self.extensions_mut().insert(Enc(encoding)); self.extensions_mut().insert(CompressWith(encoding));
// self self
// } }
// } }
// impl<B> BodyEncoding for actix_http::Response<B> {
// fn get_encoding(&self) -> Option<ContentEncoding> {
// self.extensions().get::<Enc>().map(|enc| enc.0)
// }
// fn compress_with(&mut self, encoding: ContentEncoding) -> &mut Self {
// self.extensions_mut().insert(Enc(encoding));
// self
// }
// }

View File

@ -18,7 +18,7 @@ use crate::{
body::{EitherBody, MessageBody}, body::{EitherBody, MessageBody},
dev::BodyEncoding as _, dev::BodyEncoding as _,
http::{ http::{
header::{self, AcceptEncoding, ContentEncoding, Encoding, HeaderValue}, header::{self, AcceptEncoding, Encoding, HeaderValue},
StatusCode, StatusCode,
}, },
service::{ServiceRequest, ServiceResponse}, service::{ServiceRequest, ServiceResponse},
@ -38,26 +38,10 @@ use crate::{
/// .wrap(middleware::Compress::default()) /// .wrap(middleware::Compress::default())
/// .default_service(web::to(|| HttpResponse::NotFound())); /// .default_service(web::to(|| HttpResponse::NotFound()));
/// ``` /// ```
#[derive(Debug, Clone)] #[derive(Debug, Clone, Default)]
#[non_exhaustive] #[non_exhaustive]
pub struct Compress; pub struct Compress;
impl Compress {
/// Create new `Compress` middleware with the specified encoding.
// TODO: remove
pub fn new(_encoding: ContentEncoding) -> Self {
// Compress(encoding)
Compress
}
}
impl Default for Compress {
fn default() -> Self {
// Compress::new(ContentEncoding::Auto)
Compress
}
}
impl<S, B> Transform<S, ServiceRequest> for Compress impl<S, B> Transform<S, ServiceRequest> for Compress
where where
B: MessageBody, B: MessageBody,
@ -70,73 +54,14 @@ where
type Future = Ready<Result<Self::Transform, Self::InitError>>; type Future = Ready<Result<Self::Transform, Self::InitError>>;
fn new_transform(&self, service: S) -> Self::Future { fn new_transform(&self, service: S) -> Self::Future {
ok(CompressMiddleware { ok(CompressMiddleware { service })
service,
// encoding: self.0,
})
} }
} }
pub struct CompressMiddleware<S> { pub struct CompressMiddleware<S> {
service: S, service: S,
// encoding: ContentEncoding,
} }
static SUPPORTED_ENCODINGS_STRING: Lazy<String> = Lazy::new(|| {
#[allow(unused_mut)] // only unused when no compress features enabled
let mut encoding: Vec<&str> = vec![];
#[cfg(feature = "compress-brotli")]
{
encoding.push("br");
}
#[cfg(feature = "compress-gzip")]
{
encoding.push("gzip");
encoding.push("deflate");
}
#[cfg(feature = "compress-zstd")]
{
encoding.push("zstd");
}
assert!(
!encoding.is_empty(),
"encoding can not be empty unless __compress feature has been explicitly enabled by itself"
);
encoding.join(", ")
});
static SUPPORTED_ENCODINGS: Lazy<Vec<Encoding>> = Lazy::new(|| {
let mut encodings = vec![Encoding::identity()];
#[cfg(feature = "compress-brotli")]
{
encodings.push(Encoding::brotli());
}
#[cfg(feature = "compress-gzip")]
{
encodings.push(Encoding::gzip());
encodings.push(Encoding::deflate());
}
#[cfg(feature = "compress-zstd")]
{
encodings.push(Encoding::zstd());
}
assert!(
!encodings.is_empty(),
"encodings can not be empty unless __compress feature has been explicitly enabled by itself"
);
encodings
});
impl<S, B> Service<ServiceRequest> for CompressMiddleware<S> impl<S, B> Service<ServiceRequest> for CompressMiddleware<S>
where where
S: Service<ServiceRequest, Response = ServiceResponse<B>, Error = Error>, S: Service<ServiceRequest, Response = ServiceResponse<B>, Error = Error>,
@ -237,3 +162,58 @@ where
} }
} }
} }
static SUPPORTED_ENCODINGS_STRING: Lazy<String> = Lazy::new(|| {
#[allow(unused_mut)] // only unused when no compress features enabled
let mut encoding: Vec<&str> = vec![];
#[cfg(feature = "compress-brotli")]
{
encoding.push("br");
}
#[cfg(feature = "compress-gzip")]
{
encoding.push("gzip");
encoding.push("deflate");
}
#[cfg(feature = "compress-zstd")]
{
encoding.push("zstd");
}
assert!(
!encoding.is_empty(),
"encoding can not be empty unless __compress feature has been explicitly enabled by itself"
);
encoding.join(", ")
});
static SUPPORTED_ENCODINGS: Lazy<Vec<Encoding>> = Lazy::new(|| {
let mut encodings = vec![Encoding::identity()];
#[cfg(feature = "compress-brotli")]
{
encodings.push(Encoding::brotli());
}
#[cfg(feature = "compress-gzip")]
{
encodings.push(Encoding::gzip());
encodings.push(Encoding::deflate());
}
#[cfg(feature = "compress-zstd")]
{
encodings.push(Encoding::zstd());
}
assert!(
!encodings.is_empty(),
"encodings can not be empty unless __compress feature has been explicitly enabled by itself"
);
encodings
});

View File

@ -288,6 +288,7 @@ async fn deny_identity_coding_no_decompress() {
} }
// TODO: fix test // TODO: fix test
// currently fails because negotiation doesn't consider unknown encoding types
#[ignore] #[ignore]
#[actix_rt::test] #[actix_rt::test]
async fn deny_identity_for_manual_coding() { async fn deny_identity_for_manual_coding() {

View File

@ -133,7 +133,7 @@ async fn test_body() {
async fn test_body_encoding_override() { async fn test_body_encoding_override() {
let srv = actix_test::start_with(actix_test::config().h1(), || { let srv = actix_test::start_with(actix_test::config().h1(), || {
App::new() App::new()
.wrap(Compress::new(ContentEncoding::Gzip)) .wrap(Compress::default())
.service(web::resource("/").route(web::to(|| { .service(web::resource("/").route(web::to(|| {
HttpResponse::Ok() HttpResponse::Ok()
.encode_with(ContentEncoding::Deflate) .encode_with(ContentEncoding::Deflate)
@ -183,12 +183,9 @@ async fn body_gzip_large() {
let srv = actix_test::start_with(actix_test::config().h1(), move || { let srv = actix_test::start_with(actix_test::config().h1(), move || {
let data = srv_data.clone(); let data = srv_data.clone();
App::new() App::new().wrap(Compress::default()).service(
.wrap(Compress::new(ContentEncoding::Gzip)) web::resource("/").route(web::to(move || HttpResponse::Ok().body(data.clone()))),
.service( )
web::resource("/")
.route(web::to(move || HttpResponse::Ok().body(data.clone()))),
)
}); });
let mut res = srv let mut res = srv
@ -217,12 +214,9 @@ async fn test_body_gzip_large_random() {
let srv = actix_test::start_with(actix_test::config().h1(), move || { let srv = actix_test::start_with(actix_test::config().h1(), move || {
let data = srv_data.clone(); let data = srv_data.clone();
App::new() App::new().wrap(Compress::default()).service(
.wrap(Compress::new(ContentEncoding::Gzip)) web::resource("/").route(web::to(move || HttpResponse::Ok().body(data.clone()))),
.service( )
web::resource("/")
.route(web::to(move || HttpResponse::Ok().body(data.clone()))),
)
}); });
let mut res = srv let mut res = srv
@ -244,7 +238,7 @@ async fn test_body_gzip_large_random() {
async fn test_body_chunked_implicit() { async fn test_body_chunked_implicit() {
let srv = actix_test::start_with(actix_test::config().h1(), || { let srv = actix_test::start_with(actix_test::config().h1(), || {
App::new() App::new()
.wrap(Compress::new(ContentEncoding::Gzip)) .wrap(Compress::default())
.service(web::resource("/").route(web::get().to(move || { .service(web::resource("/").route(web::get().to(move || {
HttpResponse::Ok() HttpResponse::Ok()
.streaming(TestBody::new(Bytes::from_static(STR.as_ref()), 24)) .streaming(TestBody::new(Bytes::from_static(STR.as_ref()), 24))
@ -271,7 +265,7 @@ async fn test_body_chunked_implicit() {
async fn test_body_br_streaming() { async fn test_body_br_streaming() {
let srv = actix_test::start_with(actix_test::config().h1(), || { let srv = actix_test::start_with(actix_test::config().h1(), || {
App::new() App::new()
.wrap(Compress::new(ContentEncoding::Brotli)) .wrap(Compress::default())
.service(web::resource("/").route(web::to(move || { .service(web::resource("/").route(web::to(move || {
HttpResponse::Ok() HttpResponse::Ok()
.streaming(TestBody::new(Bytes::from_static(STR.as_ref()), 24)) .streaming(TestBody::new(Bytes::from_static(STR.as_ref()), 24))
@ -337,7 +331,7 @@ async fn test_no_chunking() {
async fn test_body_deflate() { async fn test_body_deflate() {
let srv = actix_test::start_with(actix_test::config().h1(), || { let srv = actix_test::start_with(actix_test::config().h1(), || {
App::new() App::new()
.wrap(Compress::new(ContentEncoding::Deflate)) .wrap(Compress::default())
.service(web::resource("/").route(web::to(move || HttpResponse::Ok().body(STR)))) .service(web::resource("/").route(web::to(move || HttpResponse::Ok().body(STR))))
}); });
@ -360,7 +354,7 @@ async fn test_body_deflate() {
async fn test_body_brotli() { async fn test_body_brotli() {
let srv = actix_test::start_with(actix_test::config().h1(), || { let srv = actix_test::start_with(actix_test::config().h1(), || {
App::new() App::new()
.wrap(Compress::new(ContentEncoding::Brotli)) .wrap(Compress::default())
.service(web::resource("/").route(web::to(move || HttpResponse::Ok().body(STR)))) .service(web::resource("/").route(web::to(move || HttpResponse::Ok().body(STR))))
}); });
@ -383,7 +377,7 @@ async fn test_body_brotli() {
async fn test_body_zstd() { async fn test_body_zstd() {
let srv = actix_test::start_with(actix_test::config().h1(), || { let srv = actix_test::start_with(actix_test::config().h1(), || {
App::new() App::new()
.wrap(Compress::new(ContentEncoding::Zstd)) .wrap(Compress::default())
.service(web::resource("/").route(web::to(move || HttpResponse::Ok().body(STR)))) .service(web::resource("/").route(web::to(move || HttpResponse::Ok().body(STR))))
}); });
@ -406,7 +400,7 @@ async fn test_body_zstd() {
async fn test_body_zstd_streaming() { async fn test_body_zstd_streaming() {
let srv = actix_test::start_with(actix_test::config().h1(), || { let srv = actix_test::start_with(actix_test::config().h1(), || {
App::new() App::new()
.wrap(Compress::new(ContentEncoding::Zstd)) .wrap(Compress::default())
.service(web::resource("/").route(web::to(move || { .service(web::resource("/").route(web::to(move || {
HttpResponse::Ok() HttpResponse::Ok()
.streaming(TestBody::new(Bytes::from_static(STR.as_ref()), 24)) .streaming(TestBody::new(Bytes::from_static(STR.as_ref()), 24))