mirror of
https://github.com/actix/actix-web.git
synced 2024-11-19 16:11:07 +00:00
rework Handler trait (#2549)
This commit is contained in:
parent
ac0c4eb684
commit
554ae7a868
4 changed files with 32 additions and 45 deletions
|
@ -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,)*)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
14
src/route.rs
14
src/route.rs
|
@ -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
|
||||||
|
|
15
src/web.rs
15
src/web.rs
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue