mirror of https://github.com/fafhrd91/actix-web
switch encoder/compress to use AnyBody
This commit is contained in:
parent
5167bf16a2
commit
0b13d27b03
|
@ -1,8 +1,11 @@
|
||||||
# Changes
|
# Changes
|
||||||
|
|
||||||
## Unreleased - 2021-xx-xx
|
## Unreleased - 2021-xx-xx
|
||||||
|
### Changed
|
||||||
|
* Compress middleware's response type is now `AnyBody<Encoder<B>>`. [#2448]
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
* Relax `Unpin` bound on `S` (stream) parameter of `HttpResponseBuilder::streaming`. [#????]
|
* Relax `Unpin` bound on `S` (stream) parameter of `HttpResponseBuilder::streaming`. [#2448]
|
||||||
|
|
||||||
[#2423]: https://github.com/actix/actix-web/pull/2423
|
[#2423]: https://github.com/actix/actix-web/pull/2423
|
||||||
|
|
||||||
|
|
|
@ -3,19 +3,21 @@
|
||||||
## Unreleased - 2021-xx-xx
|
## Unreleased - 2021-xx-xx
|
||||||
### Added
|
### Added
|
||||||
* `AnyBody::empty` for quickly creating an empty body. [#2446]
|
* `AnyBody::empty` for quickly creating an empty body. [#2446]
|
||||||
* `impl Clone` for `AnyBody<S> where S: Clone`. [#????]
|
* `impl Clone` for `AnyBody<S> where S: Clone`. [#2448]
|
||||||
* `AnyBody::into_boxed` for quickly converting to a type-erased, boxed body type. [#????]
|
* `AnyBody::into_boxed` for quickly converting to a type-erased, boxed body type. [#2448]
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
* Rename `AnyBody::{Message => Body}`. [#2446]
|
* Rename `AnyBody::{Message => Body}`. [#2446]
|
||||||
* Rename `AnyBody::{from_message => new_boxed}`. [#????]
|
* Rename `AnyBody::{from_message => new_boxed}`. [#2448]
|
||||||
* Rename `AnyBody::{from_slice => copy_from_slice}`. [#????]
|
* Rename `AnyBody::{from_slice => copy_from_slice}`. [#2448]
|
||||||
* Rename `BoxAnyBody` to `BoxBody` [#????]
|
* Rename `BoxAnyBody` to `BoxBody` [#2448]
|
||||||
* Change representation of `AnyBody` to include a type parameter in `Body` variant. Defaults to `BoxBody`. [#????]
|
* Change representation of `AnyBody` to include a type parameter in `Body` variant. Defaults to `BoxBody`. [#2448]
|
||||||
|
* `Encoder::response` now returns `AnyBody<Encoder<B>>`. [#2448]
|
||||||
|
|
||||||
### Removed
|
### Removed
|
||||||
* `AnyBody::Empty`; an empty body can now only be represented as a zero-length `Bytes` variant. [#2446]
|
* `AnyBody::Empty`; an empty body can now only be represented as a zero-length `Bytes` variant. [#2446]
|
||||||
* `BodySize::Empty`; an empty body can now only be represented as a `Sized(0)` variant. [#2446]
|
* `BodySize::Empty`; an empty body can now only be represented as a `Sized(0)` variant. [#2446]
|
||||||
|
* `EncoderError::Boxed`; it is no longer required. [#2446]
|
||||||
|
|
||||||
[#2446]: https://github.com/actix/actix-web/pull/2446
|
[#2446]: https://github.com/actix/actix-web/pull/2446
|
||||||
|
|
||||||
|
|
|
@ -24,7 +24,7 @@ use flate2::write::{GzEncoder, ZlibEncoder};
|
||||||
use zstd::stream::write::Encoder as ZstdEncoder;
|
use zstd::stream::write::Encoder as ZstdEncoder;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
body::{Body, BodySize, BoxBody, MessageBody, ResponseBody},
|
body::{AnyBody, BodySize, MessageBody},
|
||||||
http::{
|
http::{
|
||||||
header::{ContentEncoding, CONTENT_ENCODING},
|
header::{ContentEncoding, CONTENT_ENCODING},
|
||||||
HeaderValue, StatusCode,
|
HeaderValue, StatusCode,
|
||||||
|
@ -50,8 +50,8 @@ impl<B: MessageBody> Encoder<B> {
|
||||||
pub fn response(
|
pub fn response(
|
||||||
encoding: ContentEncoding,
|
encoding: ContentEncoding,
|
||||||
head: &mut ResponseHead,
|
head: &mut ResponseHead,
|
||||||
body: ResponseBody<B>,
|
body: AnyBody<B>,
|
||||||
) -> ResponseBody<Encoder<B>> {
|
) -> AnyBody<Encoder<B>> {
|
||||||
let can_encode = !(head.headers().contains_key(&CONTENT_ENCODING)
|
let can_encode = !(head.headers().contains_key(&CONTENT_ENCODING)
|
||||||
|| head.status == StatusCode::SWITCHING_PROTOCOLS
|
|| head.status == StatusCode::SWITCHING_PROTOCOLS
|
||||||
|| head.status == StatusCode::NO_CONTENT
|
|| head.status == StatusCode::NO_CONTENT
|
||||||
|
@ -59,18 +59,15 @@ impl<B: MessageBody> Encoder<B> {
|
||||||
|| encoding == ContentEncoding::Auto);
|
|| encoding == ContentEncoding::Auto);
|
||||||
|
|
||||||
let body = match body {
|
let body = match body {
|
||||||
ResponseBody::Other(b) => match b {
|
AnyBody::None => return AnyBody::None,
|
||||||
Body::None => return ResponseBody::Other(Body::None),
|
AnyBody::Bytes(buf) => {
|
||||||
Body::Bytes(buf) => {
|
if can_encode {
|
||||||
if can_encode {
|
EncoderBody::Bytes(buf)
|
||||||
EncoderBody::Bytes(buf)
|
} else {
|
||||||
} else {
|
return AnyBody::Bytes(buf);
|
||||||
return ResponseBody::Other(Body::Bytes(buf));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Body::Body(stream) => EncoderBody::BoxedStream(stream),
|
}
|
||||||
},
|
AnyBody::Body(body) => EncoderBody::Stream(body),
|
||||||
ResponseBody::Body(stream) => EncoderBody::Stream(stream),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
if can_encode {
|
if can_encode {
|
||||||
|
@ -78,7 +75,8 @@ impl<B: MessageBody> Encoder<B> {
|
||||||
if let Some(enc) = ContentEncoder::encoder(encoding) {
|
if let Some(enc) = ContentEncoder::encoder(encoding) {
|
||||||
update_head(encoding, head);
|
update_head(encoding, head);
|
||||||
head.no_chunking(false);
|
head.no_chunking(false);
|
||||||
return ResponseBody::Body(Encoder {
|
|
||||||
|
return AnyBody::Body(Encoder {
|
||||||
body,
|
body,
|
||||||
eof: false,
|
eof: false,
|
||||||
fut: None,
|
fut: None,
|
||||||
|
@ -87,7 +85,7 @@ impl<B: MessageBody> Encoder<B> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ResponseBody::Body(Encoder {
|
AnyBody::Body(Encoder {
|
||||||
body,
|
body,
|
||||||
eof: false,
|
eof: false,
|
||||||
fut: None,
|
fut: None,
|
||||||
|
@ -100,7 +98,6 @@ impl<B: MessageBody> Encoder<B> {
|
||||||
enum EncoderBody<B> {
|
enum EncoderBody<B> {
|
||||||
Bytes(Bytes),
|
Bytes(Bytes),
|
||||||
Stream(#[pin] B),
|
Stream(#[pin] B),
|
||||||
BoxedStream(BoxBody),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<B> MessageBody for EncoderBody<B>
|
impl<B> MessageBody for EncoderBody<B>
|
||||||
|
@ -113,7 +110,6 @@ where
|
||||||
match self {
|
match self {
|
||||||
EncoderBody::Bytes(ref b) => b.size(),
|
EncoderBody::Bytes(ref b) => b.size(),
|
||||||
EncoderBody::Stream(ref b) => b.size(),
|
EncoderBody::Stream(ref b) => b.size(),
|
||||||
EncoderBody::BoxedStream(ref b) => b.size(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -130,9 +126,6 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
EncoderBodyProj::Stream(b) => b.poll_next(cx).map_err(EncoderError::Body),
|
EncoderBodyProj::Stream(b) => b.poll_next(cx).map_err(EncoderError::Body),
|
||||||
EncoderBodyProj::BoxedStream(ref mut b) => {
|
|
||||||
b.as_pin_mut().poll_next(cx).map_err(EncoderError::Boxed)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -348,9 +341,6 @@ pub enum EncoderError<E> {
|
||||||
#[display(fmt = "body")]
|
#[display(fmt = "body")]
|
||||||
Body(E),
|
Body(E),
|
||||||
|
|
||||||
#[display(fmt = "boxed")]
|
|
||||||
Boxed(Box<dyn StdError>),
|
|
||||||
|
|
||||||
#[display(fmt = "blocking")]
|
#[display(fmt = "blocking")]
|
||||||
Blocking(BlockingError),
|
Blocking(BlockingError),
|
||||||
|
|
||||||
|
@ -362,7 +352,6 @@ impl<E: StdError + 'static> StdError for EncoderError<E> {
|
||||||
fn source(&self) -> Option<&(dyn StdError + 'static)> {
|
fn source(&self) -> Option<&(dyn StdError + 'static)> {
|
||||||
match self {
|
match self {
|
||||||
EncoderError::Body(err) => Some(err),
|
EncoderError::Body(err) => Some(err),
|
||||||
EncoderError::Boxed(err) => Some(&**err),
|
|
||||||
EncoderError::Blocking(err) => Some(err),
|
EncoderError::Blocking(err) => Some(err),
|
||||||
EncoderError::Io(err) => Some(err),
|
EncoderError::Io(err) => Some(err),
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,13 +10,14 @@ use std::{
|
||||||
};
|
};
|
||||||
|
|
||||||
use actix_http::{
|
use actix_http::{
|
||||||
body::{MessageBody, ResponseBody},
|
body::{AnyBody, MessageBody},
|
||||||
encoding::Encoder,
|
encoding::Encoder,
|
||||||
http::header::{ContentEncoding, ACCEPT_ENCODING},
|
http::header::{ContentEncoding, ACCEPT_ENCODING},
|
||||||
StatusCode,
|
StatusCode,
|
||||||
};
|
};
|
||||||
use actix_service::{Service, Transform};
|
use actix_service::{Service, Transform};
|
||||||
use actix_utils::future::{ok, Either, Ready};
|
use actix_utils::future::{ok, Either, Ready};
|
||||||
|
use bytes::Bytes;
|
||||||
use futures_core::ready;
|
use futures_core::ready;
|
||||||
use once_cell::sync::Lazy;
|
use once_cell::sync::Lazy;
|
||||||
use pin_project::pin_project;
|
use pin_project::pin_project;
|
||||||
|
@ -61,7 +62,7 @@ where
|
||||||
B: MessageBody,
|
B: MessageBody,
|
||||||
S: Service<ServiceRequest, Response = ServiceResponse<B>, Error = Error>,
|
S: Service<ServiceRequest, Response = ServiceResponse<B>, Error = Error>,
|
||||||
{
|
{
|
||||||
type Response = ServiceResponse<ResponseBody<Encoder<B>>>;
|
type Response = ServiceResponse<AnyBody<Encoder<B>>>;
|
||||||
type Error = Error;
|
type Error = Error;
|
||||||
type Transform = CompressMiddleware<S>;
|
type Transform = CompressMiddleware<S>;
|
||||||
type InitError = ();
|
type InitError = ();
|
||||||
|
@ -110,7 +111,7 @@ where
|
||||||
S: Service<ServiceRequest, Response = ServiceResponse<B>, Error = Error>,
|
S: Service<ServiceRequest, Response = ServiceResponse<B>, Error = Error>,
|
||||||
B: MessageBody,
|
B: MessageBody,
|
||||||
{
|
{
|
||||||
type Response = ServiceResponse<ResponseBody<Encoder<B>>>;
|
type Response = ServiceResponse<AnyBody<Encoder<B>>>;
|
||||||
type Error = Error;
|
type Error = Error;
|
||||||
type Future = Either<CompressResponse<S, B>, Ready<Result<Self::Response, Self::Error>>>;
|
type Future = Either<CompressResponse<S, B>, Ready<Result<Self::Response, Self::Error>>>;
|
||||||
|
|
||||||
|
@ -142,15 +143,19 @@ where
|
||||||
|
|
||||||
// There is an HTTP header but we cannot match what client as asked for
|
// There is an HTTP header but we cannot match what client as asked for
|
||||||
Some(Err(_)) => {
|
Some(Err(_)) => {
|
||||||
let res = HttpResponse::with_body(
|
let res = HttpResponse::new(StatusCode::NOT_ACCEPTABLE);
|
||||||
StatusCode::NOT_ACCEPTABLE,
|
|
||||||
SUPPORTED_ALGORITHM_NAMES.as_str(),
|
|
||||||
);
|
|
||||||
let enc = ContentEncoding::Identity;
|
|
||||||
|
|
||||||
Either::right(ok(req.into_response(res.map_body(move |head, body| {
|
let res: HttpResponse<AnyBody<Encoder<B>>> = res.map_body(move |head, _| {
|
||||||
Encoder::response(enc, head, ResponseBody::Other(body.into()))
|
let body_bytes = Bytes::from(SUPPORTED_ALGORITHM_NAMES.as_bytes());
|
||||||
}))))
|
|
||||||
|
Encoder::response(
|
||||||
|
ContentEncoding::Identity,
|
||||||
|
head,
|
||||||
|
AnyBody::Bytes(body_bytes),
|
||||||
|
)
|
||||||
|
});
|
||||||
|
|
||||||
|
Either::right(ok(req.into_response(res)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -172,7 +177,7 @@ where
|
||||||
B: MessageBody,
|
B: MessageBody,
|
||||||
S: Service<ServiceRequest, Response = ServiceResponse<B>, Error = Error>,
|
S: Service<ServiceRequest, Response = ServiceResponse<B>, Error = Error>,
|
||||||
{
|
{
|
||||||
type Output = Result<ServiceResponse<ResponseBody<Encoder<B>>>, Error>;
|
type Output = Result<ServiceResponse<AnyBody<Encoder<B>>>, Error>;
|
||||||
|
|
||||||
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||||
let this = self.project();
|
let this = self.project();
|
||||||
|
@ -186,7 +191,7 @@ where
|
||||||
};
|
};
|
||||||
|
|
||||||
Poll::Ready(Ok(resp.map_body(move |head, body| {
|
Poll::Ready(Ok(resp.map_body(move |head, body| {
|
||||||
Encoder::response(enc, head, ResponseBody::Body(body))
|
Encoder::response(enc, head, AnyBody::Body(body))
|
||||||
})))
|
})))
|
||||||
}
|
}
|
||||||
Err(e) => Poll::Ready(Err(e)),
|
Err(e) => Poll::Ready(Err(e)),
|
||||||
|
|
|
@ -227,6 +227,9 @@ impl<B> HttpResponse<B> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: into_body equivalent
|
||||||
|
// TODO: into_boxed_body
|
||||||
|
|
||||||
/// Extract response body
|
/// Extract response body
|
||||||
pub fn into_body(self) -> B {
|
pub fn into_body(self) -> B {
|
||||||
self.res.into_body()
|
self.res.into_body()
|
||||||
|
|
Loading…
Reference in New Issue