remove MessageBody bound generic type from more types

This commit is contained in:
fakeshadow 2020-09-28 01:15:38 +08:00
parent f6106b69cf
commit 06322bd627
7 changed files with 60 additions and 74 deletions

View File

@ -2,9 +2,15 @@
## Unreleased - 2020-xx-xx ## Unreleased - 2020-xx-xx
### Changed ### Changed
* remove generic type `B` for `app::App` and it's not bound to `actix_http::body::MessageBody` trait anymore. [#1692] * Remove generic type `B` for `app::App`, `app_service::{AppInit, AppInitResult, AppInitService}`.
Change `middleware::{Compressed, Logger}` to return `ServiceResponse<Body>` directly. [#1692]
* Add `TrailingSlash::MergeOnly` behaviour to `NormalizePath`, which allow `NormalizePath`
to keep the trailing slash's existance as it is. [#1695]
* Fix `ResourceMap` recursive references when printing/debugging. [#1708]
[#1692]: https://github.com/actix/actix-web/pull/1692 [#1692]: https://github.com/actix/actix-web/pull/1692
[#1695]: https://github.com/actix/actix-web/pull/1695
[#1708]: https://github.com/actix/actix-web/pull/1708
## 3.0.2 - 2020-09-15 ## 3.0.2 - 2020-09-15

View File

@ -29,12 +29,12 @@ pub struct Encoder<B> {
fut: Option<CpuFuture<ContentEncoder, io::Error>>, fut: Option<CpuFuture<ContentEncoder, io::Error>>,
} }
impl<B: MessageBody> Encoder<B> { impl<B: MessageBody + Unpin + 'static> Encoder<B> {
pub fn response( pub fn response(
encoding: ContentEncoding, encoding: ContentEncoding,
head: &mut ResponseHead, head: &mut ResponseHead,
body: ResponseBody<B>, body: ResponseBody<B>,
) -> ResponseBody<Encoder<B>> { ) -> ResponseBody<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
@ -62,20 +62,20 @@ 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 ResponseBody::Other(Body::from_message(Encoder {
body, body,
eof: false, eof: false,
fut: None, fut: None,
encoder: Some(enc), encoder: Some(enc),
}); }));
} }
} }
ResponseBody::Body(Encoder { ResponseBody::Other(Body::from_message(Encoder {
body, body,
eof: false, eof: false,
fut: None, fut: None,
encoder: None, encoder: None,
}) }))
} }
} }

View File

@ -232,7 +232,10 @@ impl<B> Response<B> {
} }
/// Set a body and return previous body value /// Set a body and return previous body value
pub(crate) fn replace_body<B2>(self, body: B2) -> (Response<B2>, ResponseBody<B>) { pub(crate) fn replace_body<B2: Unpin>(
self,
body: B2,
) -> (Response<B2>, ResponseBody<B>) {
( (
Response { Response {
head: self.head, head: self.head,

View File

@ -3,7 +3,6 @@ use std::fmt;
use std::future::Future; use std::future::Future;
use std::rc::Rc; use std::rc::Rc;
use actix_http::body::MessageBody;
use actix_http::Extensions; use actix_http::Extensions;
use actix_service::boxed::{self, BoxServiceFactory}; use actix_service::boxed::{self, BoxServiceFactory};
use actix_service::{ use actix_service::{
@ -27,7 +26,7 @@ type HttpNewService = BoxServiceFactory<(), ServiceRequest, ServiceResponse, Err
/// Application builder - structure that follows the builder pattern /// Application builder - structure that follows the builder pattern
/// for building application instances. /// for building application instances.
pub struct App<T> { pub struct App<T = AppEntry> {
endpoint: T, endpoint: T,
services: Vec<Box<dyn AppServiceFactory>>, services: Vec<Box<dyn AppServiceFactory>>,
default: Option<Rc<HttpNewService>>, default: Option<Rc<HttpNewService>>,
@ -38,7 +37,7 @@ pub struct App<T> {
extensions: Extensions, extensions: Extensions,
} }
impl App<AppEntry> { impl App {
/// Create application builder. Application can be configured with a builder-like pattern. /// Create application builder. Application can be configured with a builder-like pattern.
#[allow(clippy::new_without_default)] #[allow(clippy::new_without_default)]
pub fn new() -> Self { pub fn new() -> Self {
@ -56,13 +55,12 @@ impl App<AppEntry> {
} }
} }
impl<T, B> App<T> impl<T> App<T>
where where
B: MessageBody,
T: ServiceFactory< T: ServiceFactory<
Config = (), Config = (),
Request = ServiceRequest, Request = ServiceRequest,
Response = ServiceResponse<B>, Response = ServiceResponse,
Error = Error, Error = Error,
InitError = (), InitError = (),
>, >,
@ -344,14 +342,14 @@ where
/// .route("/index.html", web::get().to(index)); /// .route("/index.html", web::get().to(index));
/// } /// }
/// ``` /// ```
pub fn wrap<M, B1>( pub fn wrap<M>(
self, self,
mw: M, mw: M,
) -> App< ) -> App<
impl ServiceFactory< impl ServiceFactory<
Config = (), Config = (),
Request = ServiceRequest, Request = ServiceRequest,
Response = ServiceResponse<B1>, Response = ServiceResponse,
Error = Error, Error = Error,
InitError = (), InitError = (),
>, >,
@ -360,11 +358,10 @@ where
M: Transform< M: Transform<
T::Service, T::Service,
Request = ServiceRequest, Request = ServiceRequest,
Response = ServiceResponse<B1>, Response = ServiceResponse,
Error = Error, Error = Error,
InitError = (), InitError = (),
>, >,
B1: MessageBody,
{ {
App { App {
endpoint: apply(mw, self.endpoint), endpoint: apply(mw, self.endpoint),
@ -409,22 +406,21 @@ where
/// .route("/index.html", web::get().to(index)); /// .route("/index.html", web::get().to(index));
/// } /// }
/// ``` /// ```
pub fn wrap_fn<B1, F, R>( pub fn wrap_fn<F, R>(
self, self,
mw: F, mw: F,
) -> App< ) -> App<
impl ServiceFactory< impl ServiceFactory<
Config = (), Config = (),
Request = ServiceRequest, Request = ServiceRequest,
Response = ServiceResponse<B1>, Response = ServiceResponse,
Error = Error, Error = Error,
InitError = (), InitError = (),
>, >,
> >
where where
B1: MessageBody,
F: FnMut(ServiceRequest, &mut T::Service) -> R + Clone, F: FnMut(ServiceRequest, &mut T::Service) -> R + Clone,
R: Future<Output = Result<ServiceResponse<B1>, Error>>, R: Future<Output = Result<ServiceResponse, Error>>,
{ {
App { App {
endpoint: apply_fn_factory(self.endpoint, mw), endpoint: apply_fn_factory(self.endpoint, mw),
@ -439,18 +435,17 @@ where
} }
} }
impl<T, B> IntoServiceFactory<AppInit<T, B>> for App<T> impl<T> IntoServiceFactory<AppInit<T>> for App<T>
where where
B: MessageBody,
T: ServiceFactory< T: ServiceFactory<
Config = (), Config = (),
Request = ServiceRequest, Request = ServiceRequest,
Response = ServiceResponse<B>, Response = ServiceResponse,
Error = Error, Error = Error,
InitError = (), InitError = (),
>, >,
{ {
fn into_factory(self) -> AppInit<T, B> { fn into_factory(self) -> AppInit<T> {
AppInit { AppInit {
data: Rc::new(self.data), data: Rc::new(self.data),
data_factories: Rc::new(self.data_factories), data_factories: Rc::new(self.data_factories),

View File

@ -1,6 +1,5 @@
use std::cell::RefCell; use std::cell::RefCell;
use std::future::Future; use std::future::Future;
use std::marker::PhantomData;
use std::pin::Pin; use std::pin::Pin;
use std::rc::Rc; use std::rc::Rc;
use std::task::{Context, Poll}; use std::task::{Context, Poll};
@ -27,16 +26,7 @@ type BoxResponse = LocalBoxFuture<'static, Result<ServiceResponse, Error>>;
/// Service factory to convert `Request` to a `ServiceRequest<S>`. /// Service factory to convert `Request` to a `ServiceRequest<S>`.
/// It also executes data factories. /// It also executes data factories.
pub struct AppInit<T, B> pub struct AppInit<T> {
where
T: ServiceFactory<
Config = (),
Request = ServiceRequest,
Response = ServiceResponse<B>,
Error = Error,
InitError = (),
>,
{
pub(crate) endpoint: T, pub(crate) endpoint: T,
pub(crate) extensions: RefCell<Option<Extensions>>, pub(crate) extensions: RefCell<Option<Extensions>>,
pub(crate) data: Rc<Vec<Box<dyn DataFactory>>>, pub(crate) data: Rc<Vec<Box<dyn DataFactory>>>,
@ -47,23 +37,23 @@ where
pub(crate) external: RefCell<Vec<ResourceDef>>, pub(crate) external: RefCell<Vec<ResourceDef>>,
} }
impl<T, B> ServiceFactory for AppInit<T, B> impl<T> ServiceFactory for AppInit<T>
where where
T: ServiceFactory< T: ServiceFactory<
Config = (), Config = (),
Request = ServiceRequest, Request = ServiceRequest,
Response = ServiceResponse<B>, Response = ServiceResponse,
Error = Error, Error = Error,
InitError = (), InitError = (),
>, >,
{ {
type Config = AppConfig; type Config = AppConfig;
type Request = Request; type Request = Request;
type Response = ServiceResponse<B>; type Response = ServiceResponse;
type Error = T::Error; type Error = T::Error;
type InitError = T::InitError; type InitError = T::InitError;
type Service = AppInitService<T::Service, B>; type Service = AppInitService<T::Service>;
type Future = AppInitResult<T, B>; type Future = AppInitResult<T>;
fn new_service(&self, config: AppConfig) -> Self::Future { fn new_service(&self, config: AppConfig) -> Self::Future {
// update resource default service // update resource default service
@ -125,13 +115,12 @@ where
), ),
config, config,
rmap, rmap,
_t: PhantomData,
} }
} }
} }
#[pin_project::pin_project] #[pin_project::pin_project]
pub struct AppInitResult<T, B> pub struct AppInitResult<T>
where where
T: ServiceFactory, T: ServiceFactory,
{ {
@ -149,21 +138,19 @@ where
config: AppConfig, config: AppConfig,
data: Rc<Vec<Box<dyn DataFactory>>>, data: Rc<Vec<Box<dyn DataFactory>>>,
extensions: Option<Extensions>, extensions: Option<Extensions>,
_t: PhantomData<B>,
} }
impl<T, B> Future for AppInitResult<T, B> impl<T> Future for AppInitResult<T>
where where
T: ServiceFactory< T: ServiceFactory<
Config = (), Config = (),
Request = ServiceRequest, Request = ServiceRequest,
Response = ServiceResponse<B>, Response = ServiceResponse,
Error = Error, Error = Error,
InitError = (), InitError = (),
>, >,
{ {
type Output = Result<AppInitService<T::Service, B>, ()>; type Output = Result<AppInitService<T::Service>, ()>;
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();
@ -213,10 +200,7 @@ where
} }
/// Service to convert `Request` to a `ServiceRequest<S>` /// Service to convert `Request` to a `ServiceRequest<S>`
pub struct AppInitService<T, B> pub struct AppInitService<T> {
where
T: Service<Request = ServiceRequest, Response = ServiceResponse<B>, Error = Error>,
{
service: T, service: T,
rmap: Rc<ResourceMap>, rmap: Rc<ResourceMap>,
config: AppConfig, config: AppConfig,
@ -224,12 +208,12 @@ where
pool: &'static HttpRequestPool, pool: &'static HttpRequestPool,
} }
impl<T, B> Service for AppInitService<T, B> impl<T> Service for AppInitService<T>
where where
T: Service<Request = ServiceRequest, Response = ServiceResponse<B>, Error = Error>, T: Service<Request = ServiceRequest, Response = ServiceResponse, Error = Error>,
{ {
type Request = Request; type Request = Request;
type Response = ServiceResponse<B>; type Response = ServiceResponse;
type Error = T::Error; type Error = T::Error;
type Future = T::Future; type Future = T::Future;
@ -263,10 +247,7 @@ where
} }
} }
impl<T, B> Drop for AppInitService<T, B> impl<T> Drop for AppInitService<T> {
where
T: Service<Request = ServiceRequest, Response = ServiceResponse<B>, Error = Error>,
{
fn drop(&mut self) { fn drop(&mut self) {
self.pool.clear(); self.pool.clear();
} }

View File

@ -53,11 +53,11 @@ impl Default for Compress {
impl<S, B> Transform<S> for Compress impl<S, B> Transform<S> for Compress
where where
B: MessageBody, B: MessageBody + Unpin + 'static,
S: Service<Request = ServiceRequest, Response = ServiceResponse<B>, Error = Error>, S: Service<Request = ServiceRequest, Response = ServiceResponse<B>, Error = Error>,
{ {
type Request = ServiceRequest; type Request = ServiceRequest;
type Response = ServiceResponse<Encoder<B>>; type Response = ServiceResponse<B>;
type Error = Error; type Error = Error;
type InitError = (); type InitError = ();
type Transform = CompressMiddleware<S>; type Transform = CompressMiddleware<S>;
@ -78,11 +78,11 @@ pub struct CompressMiddleware<S> {
impl<S, B> Service for CompressMiddleware<S> impl<S, B> Service for CompressMiddleware<S>
where where
B: MessageBody, B: MessageBody + Unpin + 'static,
S: Service<Request = ServiceRequest, Response = ServiceResponse<B>, Error = Error>, S: Service<Request = ServiceRequest, Response = ServiceResponse<B>, Error = Error>,
{ {
type Request = ServiceRequest; type Request = ServiceRequest;
type Response = ServiceResponse<Encoder<B>>; type Response = ServiceResponse<B>;
type Error = Error; type Error = Error;
type Future = CompressResponse<S, B>; type Future = CompressResponse<S, B>;
@ -126,10 +126,10 @@ where
impl<S, B> Future for CompressResponse<S, B> impl<S, B> Future for CompressResponse<S, B>
where where
B: MessageBody, B: MessageBody + Unpin + 'static,
S: Service<Request = ServiceRequest, Response = ServiceResponse<B>, Error = Error>, S: Service<Request = ServiceRequest, Response = ServiceResponse<B>, Error = Error>,
{ {
type Output = Result<ServiceResponse<Encoder<B>>, Error>; type Output = Result<ServiceResponse<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();

View File

@ -130,10 +130,10 @@ impl Default for Logger {
impl<S, B> Transform<S> for Logger impl<S, B> Transform<S> for Logger
where where
S: Service<Request = ServiceRequest, Response = ServiceResponse<B>, Error = Error>, S: Service<Request = ServiceRequest, Response = ServiceResponse<B>, Error = Error>,
B: MessageBody, B: MessageBody + Unpin + 'static,
{ {
type Request = ServiceRequest; type Request = ServiceRequest;
type Response = ServiceResponse<StreamLog<B>>; type Response = ServiceResponse<B>;
type Error = Error; type Error = Error;
type InitError = (); type InitError = ();
type Transform = LoggerMiddleware<S>; type Transform = LoggerMiddleware<S>;
@ -156,10 +156,10 @@ pub struct LoggerMiddleware<S> {
impl<S, B> Service for LoggerMiddleware<S> impl<S, B> Service for LoggerMiddleware<S>
where where
S: Service<Request = ServiceRequest, Response = ServiceResponse<B>, Error = Error>, S: Service<Request = ServiceRequest, Response = ServiceResponse<B>, Error = Error>,
B: MessageBody, B: MessageBody + Unpin + 'static,
{ {
type Request = ServiceRequest; type Request = ServiceRequest;
type Response = ServiceResponse<StreamLog<B>>; type Response = ServiceResponse<B>;
type Error = Error; type Error = Error;
type Future = LoggerResponse<S, B>; type Future = LoggerResponse<S, B>;
@ -208,10 +208,10 @@ where
impl<S, B> Future for LoggerResponse<S, B> impl<S, B> Future for LoggerResponse<S, B>
where where
B: MessageBody, B: MessageBody + Unpin + 'static,
S: Service<Request = ServiceRequest, Response = ServiceResponse<B>, Error = Error>, S: Service<Request = ServiceRequest, Response = ServiceResponse<B>, Error = Error>,
{ {
type Output = Result<ServiceResponse<StreamLog<B>>, Error>; type Output = Result<ServiceResponse<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();
@ -237,16 +237,17 @@ where
let format = this.format.take(); let format = this.format.take();
Poll::Ready(Ok(res.map_body(move |_, body| { Poll::Ready(Ok(res.map_body(move |_, body| {
ResponseBody::Body(StreamLog { ResponseBody::Other(Body::from_message(StreamLog {
body, body,
time, time,
format, format,
size: 0, size: 0,
}) }))
}))) })))
} }
} }
use actix_http::body::Body;
use pin_project::{pin_project, pinned_drop}; use pin_project::{pin_project, pinned_drop};
#[pin_project(PinnedDrop)] #[pin_project(PinnedDrop)]