diff --git a/src/app.rs b/src/app.rs index 3fddc055b..2b15933da 100644 --- a/src/app.rs +++ b/src/app.rs @@ -51,7 +51,10 @@ impl App { } } -impl App { +impl App +where + T: ServiceFactory, +{ /// Set application (root level) data. /// /// Application data stored with `App::app_data()` method is available through the @@ -347,35 +350,27 @@ impl App { /// .route("/index.html", web::get().to(index)); /// } /// ``` - pub fn wrap( + pub fn wrap( self, mw: M, ) -> App< impl ServiceFactory< ServiceRequest, Config = (), - Response = ServiceResponse, + Response = ServiceResponse, Error = Error, InitError = (), >, > where - T: ServiceFactory< - ServiceRequest, - Response = ServiceResponse, - Error = Error, - Config = (), - InitError = (), - >, - B: MessageBody, M: Transform< - T::Service, - ServiceRequest, - Response = ServiceResponse, - Error = Error, - InitError = (), - >, - B1: MessageBody, + T::Service, + ServiceRequest, + Response = ServiceResponse, + Error = Error, + InitError = (), + > + 'static, + B: MessageBody, { App { endpoint: apply(mw, self.endpoint), @@ -395,6 +390,9 @@ impl App { /// /// Use middleware when you need to read or modify *every* request or response in some way. /// + /// See [`App::wrap`] for details on how middlewares compose with each other. + /// + /// # Examples /// ``` /// use actix_service::Service; /// use actix_web::{web, App}; @@ -419,30 +417,22 @@ impl App { /// .route("/index.html", web::get().to(index)); /// } /// ``` - pub fn wrap_fn( + pub fn wrap_fn( self, mw: F, ) -> App< impl ServiceFactory< ServiceRequest, Config = (), - Response = ServiceResponse, + Response = ServiceResponse, Error = Error, InitError = (), >, > where - T: ServiceFactory< - ServiceRequest, - Response = ServiceResponse, - Error = Error, - Config = (), - InitError = (), - >, + F: Fn(ServiceRequest, &T::Service) -> R + Clone + 'static, + R: Future, Error>>, B: MessageBody, - F: Fn(ServiceRequest, &T::Service) -> R + Clone, - R: Future, Error>>, - B1: MessageBody, { App { endpoint: apply_fn_factory(self.endpoint, mw), @@ -458,15 +448,14 @@ impl App { impl IntoServiceFactory, Request> for App where - B: MessageBody, T: ServiceFactory< - ServiceRequest, - Config = (), - Response = ServiceResponse, - Error = Error, - InitError = (), - >, - T::Future: 'static, + ServiceRequest, + Config = (), + Response = ServiceResponse, + Error = Error, + InitError = (), + > + 'static, + B: MessageBody, { fn into_factory(self) -> AppInit { AppInit { diff --git a/src/resource.rs b/src/resource.rs index 8da0a8a85..b06f744ca 100644 --- a/src/resource.rs +++ b/src/resource.rs @@ -1,6 +1,6 @@ -use std::{cell::RefCell, fmt, future::Future, marker::PhantomData, rc::Rc}; +use std::{cell::RefCell, fmt, future::Future, rc::Rc}; -use actix_http::{body::BoxBody, Extensions}; +use actix_http::Extensions; use actix_router::{IntoPatterns, Patterns}; use actix_service::{ apply, apply_fn_factory, boxed, fn_service, IntoServiceFactory, Service, ServiceFactory, @@ -42,7 +42,7 @@ use crate::{ /// /// If no matching route could be found, *405* response code get returned. Default behavior could be /// overridden with `default_resource()` method. -pub struct Resource { +pub struct Resource { endpoint: T, rdef: Patterns, name: Option, @@ -51,7 +51,6 @@ pub struct Resource { guards: Vec>, default: BoxedHttpServiceFactory, factory_ref: Rc>>, - _phantom: PhantomData, } impl Resource { @@ -69,21 +68,13 @@ impl Resource { default: boxed::factory(fn_service(|req: ServiceRequest| async { Ok(req.into_response(HttpResponse::MethodNotAllowed())) })), - _phantom: PhantomData, } } } -impl Resource +impl Resource where - T: ServiceFactory< - ServiceRequest, - Config = (), - Response = ServiceResponse, - Error = Error, - InitError = (), - >, - B: MessageBody, + T: ServiceFactory, { /// Set resource name. /// @@ -241,35 +232,31 @@ where self } - /// Register a resource middleware. + /// Registers middleware, in the form of a middleware component (type), + /// that can modify the request and response across all routes managed by this `Resource`. /// - /// This is similar to `App's` middlewares, but middleware get invoked on resource level. - /// Resource level middlewares are not allowed to change response - /// type (i.e modify response's body). - /// - /// **Note**: middlewares get called in opposite order of middlewares registration. - pub fn wrap( + /// See [`App::wrap`](crate::App::wrap) for details. + pub fn wrap( self, mw: M, ) -> Resource< impl ServiceFactory< ServiceRequest, Config = (), - Response = ServiceResponse, + Response = ServiceResponse, Error = Error, InitError = (), >, - B1, > where M: Transform< - T::Service, - ServiceRequest, - Response = ServiceResponse, - Error = Error, - InitError = (), - >, - B1: MessageBody, + T::Service, + ServiceRequest, + Response = ServiceResponse, + Error = Error, + InitError = (), + > + 'static, + B: MessageBody, { Resource { endpoint: apply(mw, self.endpoint), @@ -280,19 +267,15 @@ where default: self.default, app_data: self.app_data, factory_ref: self.factory_ref, - _phantom: PhantomData, } } - /// Register a resource middleware function. + /// Registers middleware, in the form of a closure, + /// that can modify the request and response across all routes managed by this `Resource`. /// - /// This function accepts instance of `ServiceRequest` type and - /// mutable reference to the next middleware in chain. - /// - /// This is similar to `App's` middlewares, but middleware get invoked on resource level. - /// Resource level middlewares are not allowed to change response - /// type (i.e modify response's body). + /// See [`App::wrap_fn`](crate::App::wrap_fn) for details. /// + /// # Examples /// ``` /// use actix_service::Service; /// use actix_web::{web, App}; @@ -318,23 +301,22 @@ where /// .route(web::get().to(index))); /// } /// ``` - pub fn wrap_fn( + pub fn wrap_fn( self, mw: F, ) -> Resource< impl ServiceFactory< ServiceRequest, Config = (), - Response = ServiceResponse, + Response = ServiceResponse, Error = Error, InitError = (), >, - B1, > where - F: Fn(ServiceRequest, &T::Service) -> R + Clone, - R: Future, Error>>, - B1: MessageBody, + F: Fn(ServiceRequest, &T::Service) -> R + Clone + 'static, + R: Future, Error>>, + B: MessageBody, { Resource { endpoint: apply_fn_factory(self.endpoint, mw), @@ -345,7 +327,6 @@ where default: self.default, app_data: self.app_data, factory_ref: self.factory_ref, - _phantom: PhantomData, } } @@ -373,7 +354,7 @@ where } } -impl HttpServiceFactory for Resource +impl HttpServiceFactory for Resource where T: ServiceFactory< ServiceRequest, @@ -533,7 +514,7 @@ mod tests { impl ServiceFactory< ServiceRequest, Config = (), - Response = ServiceResponse, + Response = ServiceResponse, Error = Error, InitError = (), >, diff --git a/src/scope.rs b/src/scope.rs index fa9807f42..83286440a 100644 --- a/src/scope.rs +++ b/src/scope.rs @@ -1,9 +1,6 @@ -use std::{cell::RefCell, fmt, future::Future, marker::PhantomData, mem, rc::Rc}; +use std::{cell::RefCell, fmt, future::Future, mem, rc::Rc}; -use actix_http::{ - body::{BoxBody, MessageBody}, - Extensions, -}; +use actix_http::{body::MessageBody, Extensions}; use actix_router::{ResourceDef, Router}; use actix_service::{ apply, apply_fn_factory, boxed, IntoServiceFactory, Service, ServiceFactory, @@ -57,7 +54,7 @@ type Guards = Vec>; /// /// [pat]: crate::dev::ResourceDef#prefix-resources /// [dynamic segments]: crate::dev::ResourceDef#dynamic-segments -pub struct Scope { +pub struct Scope { endpoint: T, rdef: String, app_data: Option, @@ -66,7 +63,6 @@ pub struct Scope { default: Option>, external: Vec, factory_ref: Rc>>, - _phantom: PhantomData, } impl Scope { @@ -83,21 +79,13 @@ impl Scope { default: None, external: Vec::new(), factory_ref, - _phantom: Default::default(), } } } -impl Scope +impl Scope where - T: ServiceFactory< - ServiceRequest, - Config = (), - Response = ServiceResponse, - Error = Error, - InitError = (), - >, - B: 'static, + T: ServiceFactory, { /// Add match guard to a scope. /// @@ -296,32 +284,31 @@ where self } - /// Registers middleware, in the form of a middleware component (type), that runs during inbound - /// processing in the request life-cycle (request -> response), modifying request as necessary, - /// across all requests managed by the *Scope*. + /// Registers middleware, in the form of a middleware component (type), + /// that can modify the request and response across all routes managed by this `Scope`. /// - /// Use middleware when you need to read or modify *every* request in some way. - pub fn wrap( + /// See [`App::wrap`](crate::App::wrap) for details. + pub fn wrap( self, mw: M, ) -> Scope< impl ServiceFactory< ServiceRequest, Config = (), - Response = ServiceResponse, + Response = ServiceResponse, Error = Error, InitError = (), >, - B1, > where M: Transform< - T::Service, - ServiceRequest, - Response = ServiceResponse, - Error = Error, - InitError = (), - >, + T::Service, + ServiceRequest, + Response = ServiceResponse, + Error = Error, + InitError = (), + > + 'static, + B: MessageBody, { Scope { endpoint: apply(mw, self.endpoint), @@ -332,13 +319,13 @@ where default: self.default, external: self.external, factory_ref: self.factory_ref, - _phantom: PhantomData, } } - /// Registers middleware, in the form of a closure, that runs during inbound processing in the - /// request life-cycle (request -> response), modifying request as necessary, across all - /// requests managed by the *Scope*. + /// Registers middleware, in the form of a closure, + /// that can modify the request and response across all routes managed by this `Scope`. + /// + /// See [`App::wrap_fn`](crate::App::wrap_fn) for details. /// /// # Examples /// ``` @@ -364,22 +351,22 @@ where /// }) /// .route("/index.html", web::get().to(index))); /// ``` - pub fn wrap_fn( + pub fn wrap_fn( self, mw: F, ) -> Scope< impl ServiceFactory< ServiceRequest, Config = (), - Response = ServiceResponse, + Response = ServiceResponse, Error = Error, InitError = (), >, - B1, > where - F: Fn(ServiceRequest, &T::Service) -> R + Clone, - R: Future, Error>>, + F: Fn(ServiceRequest, &T::Service) -> R + Clone + 'static, + R: Future, Error>>, + B: MessageBody, { Scope { endpoint: apply_fn_factory(self.endpoint, mw), @@ -390,12 +377,11 @@ where default: self.default, external: self.external, factory_ref: self.factory_ref, - _phantom: PhantomData, } } } -impl HttpServiceFactory for Scope +impl HttpServiceFactory for Scope where T: ServiceFactory< ServiceRequest, @@ -596,7 +582,7 @@ mod tests { header::{self, HeaderValue}, Method, StatusCode, }, - middleware::{Compat, DefaultHeaders}, + middleware::DefaultHeaders, service::{ServiceRequest, ServiceResponse}, test::{assert_body_eq, call_service, init_service, read_body, TestRequest}, web, App, HttpMessage, HttpRequest, HttpResponse, @@ -604,16 +590,16 @@ mod tests { #[test] fn can_be_returned_from_fn() { - fn my_scope() -> Scope { + fn my_scope_1() -> Scope { web::scope("/test") .service(web::resource("").route(web::get().to(|| async { "hello" }))) } - fn my_compat_scope() -> Scope< + fn my_scope_2() -> Scope< impl ServiceFactory< ServiceRequest, Config = (), - Response = ServiceResponse, + Response = ServiceResponse, Error = Error, InitError = (), >, @@ -623,11 +609,17 @@ mod tests { let fut = srv.call(req); async { Ok(fut.await?.map_into_right_body::<()>()) } }) - .wrap(Compat::noop()) .service(web::resource("").route(web::get().to(|| async { "hello" }))) } - App::new().service(my_scope()).service(my_compat_scope()); + fn my_scope_3() -> impl HttpServiceFactory { + my_scope_2() + } + + App::new() + .service(my_scope_1()) + .service(my_scope_2()) + .service(my_scope_3()); } #[actix_rt::test]