1
0
mirror of https://github.com/fafhrd91/actix-web synced 2024-12-18 01:43:58 +01:00

rework Handler trait (#2549)

This commit is contained in:
Ali MJ Al-Nasrawy 2021-12-27 03:44:30 +03:00 committed by GitHub
parent ac0c4eb684
commit 554ae7a868
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 32 additions and 45 deletions

View File

@ -3,9 +3,8 @@ use std::future::Future;
use actix_service::{boxed, fn_service}; use actix_service::{boxed, fn_service};
use crate::{ use crate::{
body::MessageBody,
service::{BoxedHttpServiceFactory, ServiceRequest, ServiceResponse}, service::{BoxedHttpServiceFactory, ServiceRequest, ServiceResponse},
BoxError, FromRequest, HttpResponse, Responder, FromRequest, HttpResponse, Responder,
}; };
/// The interface for request handlers. /// The interface for request handlers.
@ -18,7 +17,7 @@ use crate::{
/// [`HttpResponse`] (i.e., it implements the [`Responder`] trait). /// [`HttpResponse`] (i.e., it implements the [`Responder`] trait).
/// ///
/// # Compiler Errors /// # Compiler Errors
/// If you get the error `the trait Handler<_, _, _> is not implemented`, then your handler does not /// If you get the error `the trait Handler<_> is not implemented`, then your handler does not
/// fulfill one or more of the above requirements. /// fulfill one or more of the above requirements.
/// ///
/// Unfortunately we cannot provide a better compile error message (while keeping the trait's /// Unfortunately we cannot provide a better compile error message (while keeping the trait's
@ -78,22 +77,18 @@ use crate::{
/// [arity]: https://en.wikipedia.org/wiki/Arity /// [arity]: https://en.wikipedia.org/wiki/Arity
/// [`from_request`]: FromRequest::from_request /// [`from_request`]: FromRequest::from_request
/// [on_unimpl]: https://github.com/rust-lang/rust/issues/29628 /// [on_unimpl]: https://github.com/rust-lang/rust/issues/29628
pub trait Handler<Args, R>: Clone + 'static pub trait Handler<Args>: Clone + 'static {
where type Output;
R: Future, type Future: Future<Output = Self::Output>;
R::Output: Responder,
{ fn call(&self, args: Args) -> Self::Future;
fn call(&self, args: Args) -> R;
} }
pub(crate) fn handler_service<F, Args, R>(handler: F) -> BoxedHttpServiceFactory pub(crate) fn handler_service<F, Args>(handler: F) -> BoxedHttpServiceFactory
where where
F: Handler<Args, R>, F: Handler<Args>,
Args: FromRequest, Args: FromRequest,
R: Future, F::Output: Responder,
R::Output: Responder,
<R::Output as Responder>::Body: MessageBody,
<<R::Output as Responder>::Body as MessageBody>::Error: Into<BoxError>,
{ {
boxed::factory(fn_service(move |req: ServiceRequest| { boxed::factory(fn_service(move |req: ServiceRequest| {
let handler = handler.clone(); let handler = handler.clone();
@ -125,14 +120,16 @@ where
/// factory_tuple! { A B C } // implements Handler for types: fn(A, B, C) -> R /// factory_tuple! { A B C } // implements Handler for types: fn(A, B, C) -> R
/// ``` /// ```
macro_rules! factory_tuple ({ $($param:ident)* } => { macro_rules! factory_tuple ({ $($param:ident)* } => {
impl<Func, $($param,)* R> Handler<($($param,)*), R> for Func impl<Func, Fut, $($param,)*> Handler<($($param,)*)> for Func
where Func: Fn($($param),*) -> R + Clone + 'static, where Func: Fn($($param),*) -> Fut + Clone + 'static,
R: Future, Fut: Future,
R::Output: Responder,
{ {
type Output = Fut::Output;
type Future = Fut;
#[inline] #[inline]
#[allow(non_snake_case)] #[allow(non_snake_case)]
fn call(&self, ($($param,)*): ($($param,)*)) -> R { fn call(&self, ($($param,)*): ($($param,)*)) -> Self::Future {
(self)($($param,)*) (self)($($param,)*)
} }
} }

View File

@ -20,7 +20,7 @@ use crate::{
BoxedHttpService, BoxedHttpServiceFactory, HttpServiceFactory, ServiceRequest, BoxedHttpService, BoxedHttpServiceFactory, HttpServiceFactory, ServiceRequest,
ServiceResponse, ServiceResponse,
}, },
BoxError, Error, FromRequest, HttpResponse, Responder, Error, FromRequest, HttpResponse, Responder,
}; };
/// A collection of [`Route`]s that respond to the same path pattern. /// A collection of [`Route`]s that respond to the same path pattern.
@ -230,14 +230,11 @@ where
/// # fn index(req: HttpRequest) -> HttpResponse { unimplemented!() } /// # fn index(req: HttpRequest) -> HttpResponse { unimplemented!() }
/// App::new().service(web::resource("/").route(web::route().to(index))); /// App::new().service(web::resource("/").route(web::route().to(index)));
/// ``` /// ```
pub fn to<F, Args, R>(mut self, handler: F) -> Self pub fn to<F, Args>(mut self, handler: F) -> Self
where where
F: Handler<Args, R>, F: Handler<Args>,
Args: FromRequest + 'static, Args: FromRequest + 'static,
R: Future + 'static, F::Output: Responder + 'static,
R::Output: Responder + 'static,
<R::Output as Responder>::Body: MessageBody,
<<R::Output as Responder>::Body as MessageBody>::Error: Into<BoxError>,
{ {
self.routes.push(Route::new().to(handler)); self.routes.push(Route::new().to(handler));
self self

View File

@ -1,4 +1,4 @@
use std::{future::Future, mem, rc::Rc}; use std::{mem, rc::Rc};
use actix_http::Method; use actix_http::Method;
use actix_service::{ use actix_service::{
@ -8,11 +8,10 @@ use actix_service::{
use futures_core::future::LocalBoxFuture; use futures_core::future::LocalBoxFuture;
use crate::{ use crate::{
body::MessageBody,
guard::{self, Guard}, guard::{self, Guard},
handler::{handler_service, Handler}, handler::{handler_service, Handler},
service::{BoxedHttpServiceFactory, ServiceRequest, ServiceResponse}, service::{BoxedHttpServiceFactory, ServiceRequest, ServiceResponse},
BoxError, Error, FromRequest, HttpResponse, Responder, Error, FromRequest, HttpResponse, Responder,
}; };
/// A request handler with [guards](guard). /// A request handler with [guards](guard).
@ -176,14 +175,11 @@ impl Route {
/// ); /// );
/// } /// }
/// ``` /// ```
pub fn to<F, Args, R>(mut self, handler: F) -> Self pub fn to<F, Args>(mut self, handler: F) -> Self
where where
F: Handler<Args, R>, F: Handler<Args>,
Args: FromRequest + 'static, Args: FromRequest + 'static,
R: Future + 'static, F::Output: Responder + 'static,
R::Output: Responder + 'static,
<R::Output as Responder>::Body: MessageBody,
<<R::Output as Responder>::Body as MessageBody>::Error: Into<BoxError>,
{ {
self.service = handler_service(handler); self.service = handler_service(handler);
self self

View File

@ -1,14 +1,14 @@
//! Essentials helper functions and types for application registration. //! Essentials helper functions and types for application registration.
use std::{error::Error as StdError, future::Future}; use std::future::Future;
use actix_http::Method; use actix_http::Method;
use actix_router::IntoPatterns; use actix_router::IntoPatterns;
pub use bytes::{Buf, BufMut, Bytes, BytesMut}; pub use bytes::{Buf, BufMut, Bytes, BytesMut};
use crate::{ use crate::{
body::MessageBody, error::BlockingError, extract::FromRequest, handler::Handler, error::BlockingError, extract::FromRequest, handler::Handler, resource::Resource,
resource::Resource, route::Route, scope::Scope, service::WebService, Responder, route::Route, scope::Scope, service::WebService, Responder,
}; };
pub use crate::config::ServiceConfig; pub use crate::config::ServiceConfig;
@ -146,14 +146,11 @@ pub fn method(method: Method) -> Route {
/// web::to(index)) /// web::to(index))
/// ); /// );
/// ``` /// ```
pub fn to<F, Args, R>(handler: F) -> Route pub fn to<F, Args>(handler: F) -> Route
where where
F: Handler<Args, R>, F: Handler<Args>,
Args: FromRequest + 'static, Args: FromRequest + 'static,
R: Future + 'static, F::Output: Responder + 'static,
R::Output: Responder + 'static,
<R::Output as Responder>::Body: MessageBody + 'static,
<<R::Output as Responder>::Body as MessageBody>::Error: Into<Box<dyn StdError + 'static>>,
{ {
Route::new().to(handler) Route::new().to(handler)
} }