1
0
Fork 0
mirror of https://github.com/actix/actix-web.git synced 2024-06-13 10:49:26 +00:00
actix-web/src/handler.rs

276 lines
7.4 KiB
Rust
Raw Normal View History

2019-05-12 15:34:51 +00:00
use std::convert::Infallible;
2019-11-20 17:33:22 +00:00
use std::future::Future;
2018-04-13 23:02:01 +00:00
use std::marker::PhantomData;
2019-11-20 17:33:22 +00:00
use std::pin::Pin;
use std::task::{Context, Poll};
2017-10-07 04:48:14 +00:00
2019-05-22 18:49:27 +00:00
use actix_http::{Error, Response};
2019-11-20 17:33:22 +00:00
use actix_service::{Service, ServiceFactory};
2020-05-18 02:47:20 +00:00
use futures_util::future::{ok, Ready};
use futures_util::ready;
2019-11-20 17:33:22 +00:00
use pin_project::pin_project;
2018-05-02 00:30:06 +00:00
use crate::extract::FromRequest;
2019-03-02 06:51:32 +00:00
use crate::request::HttpRequest;
use crate::responder::Responder;
2019-04-07 21:43:07 +00:00
use crate::service::{ServiceRequest, ServiceResponse};
2017-11-03 20:35:34 +00:00
2019-03-02 06:51:32 +00:00
/// Async handler converter factory
2019-11-21 15:34:04 +00:00
pub trait Factory<T, R, O>: Clone + 'static
2019-03-02 06:51:32 +00:00
where
R: Future<Output = O>,
2019-11-20 17:33:22 +00:00
O: Responder,
2019-03-02 06:51:32 +00:00
{
fn call(&self, param: T) -> R;
}
2018-05-02 00:19:15 +00:00
2019-11-21 15:34:04 +00:00
impl<F, R, O> Factory<(), R, O> for F
2019-03-02 06:51:32 +00:00
where
F: Fn() -> R + Clone + 'static,
R: Future<Output = O>,
2019-11-20 17:33:22 +00:00
O: Responder,
2019-03-02 06:51:32 +00:00
{
fn call(&self, _: ()) -> R {
(self)()
2017-11-29 03:49:17 +00:00
}
2019-03-02 06:51:32 +00:00
}
2017-12-09 21:25:06 +00:00
2019-03-02 06:51:32 +00:00
#[doc(hidden)]
2019-11-21 15:34:04 +00:00
pub struct Handler<F, T, R, O>
2019-03-02 06:51:32 +00:00
where
2019-11-21 15:34:04 +00:00
F: Factory<T, R, O>,
R: Future<Output = O>,
2019-11-20 17:33:22 +00:00
O: Responder,
2019-03-02 06:51:32 +00:00
{
hnd: F,
_t: PhantomData<(T, R, O)>,
2019-03-02 06:51:32 +00:00
}
2018-05-02 00:19:15 +00:00
2019-11-21 15:34:04 +00:00
impl<F, T, R, O> Handler<F, T, R, O>
2019-03-02 06:51:32 +00:00
where
2019-11-21 15:34:04 +00:00
F: Factory<T, R, O>,
R: Future<Output = O>,
2019-11-20 17:33:22 +00:00
O: Responder,
2019-03-02 06:51:32 +00:00
{
pub fn new(hnd: F) -> Self {
2019-11-21 15:34:04 +00:00
Handler {
2019-03-02 06:51:32 +00:00
hnd,
_t: PhantomData,
2017-12-09 21:25:06 +00:00
}
}
2017-11-29 03:49:17 +00:00
}
2019-11-21 15:34:04 +00:00
impl<F, T, R, O> Clone for Handler<F, T, R, O>
2019-03-02 06:51:32 +00:00
where
2019-11-21 15:34:04 +00:00
F: Factory<T, R, O>,
R: Future<Output = O>,
2019-11-20 17:33:22 +00:00
O: Responder,
2019-03-02 06:51:32 +00:00
{
fn clone(&self) -> Self {
2019-11-21 15:34:04 +00:00
Handler {
2019-03-02 06:51:32 +00:00
hnd: self.hnd.clone(),
_t: PhantomData,
}
}
}
2019-11-21 15:34:04 +00:00
impl<F, T, R, O> Service for Handler<F, T, R, O>
2019-03-02 06:51:32 +00:00
where
2019-11-21 15:34:04 +00:00
F: Factory<T, R, O>,
R: Future<Output = O>,
2019-11-20 17:33:22 +00:00
O: Responder,
2019-03-02 06:51:32 +00:00
{
type Request = (T, HttpRequest);
2019-03-02 06:51:32 +00:00
type Response = ServiceResponse;
2019-05-12 15:34:51 +00:00
type Error = Infallible;
2019-11-21 15:34:04 +00:00
type Future = HandlerServiceResponse<R, O>;
2017-12-02 05:29:22 +00:00
2019-12-07 18:46:51 +00:00
fn poll_ready(&mut self, _: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
2019-11-20 17:33:22 +00:00
Poll::Ready(Ok(()))
}
2019-03-02 06:51:32 +00:00
fn call(&mut self, (param, req): (T, HttpRequest)) -> Self::Future {
2020-12-19 16:33:34 +00:00
let fut = self.hnd.call(param);
HandlerServiceResponse::Future(fut, Some(req))
}
}
2019-03-02 06:51:32 +00:00
#[doc(hidden)]
2020-12-19 16:33:34 +00:00
#[pin_project(project = HandlerProj)]
pub enum HandlerServiceResponse<T, R>
where
T: Future<Output = R>,
2019-11-20 17:33:22 +00:00
R: Responder,
{
2020-12-19 16:33:34 +00:00
Future(#[pin] T, Option<HttpRequest>),
Responder(#[pin] R::Future, Option<HttpRequest>),
2018-05-02 00:19:15 +00:00
}
2019-11-21 15:34:04 +00:00
impl<T, R> Future for HandlerServiceResponse<T, R>
2018-08-23 16:48:01 +00:00
where
T: Future<Output = R>,
2019-11-20 17:33:22 +00:00
R: Responder,
2018-05-02 00:19:15 +00:00
{
2019-11-20 17:33:22 +00:00
type Output = Result<ServiceResponse, Infallible>;
2019-03-02 06:51:32 +00:00
2019-12-07 18:46:51 +00:00
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
2020-12-19 16:33:34 +00:00
loop {
match self.as_mut().project() {
HandlerProj::Future(fut, req) => {
let res = ready!(fut.poll(cx));
let fut = res.respond_to(req.as_ref().unwrap());
let state = HandlerServiceResponse::Responder(fut, req.take());
self.as_mut().set(state);
2019-11-20 17:33:22 +00:00
}
2020-12-19 16:33:34 +00:00
HandlerProj::Responder(fut, req) => {
let res = ready!(fut.poll(cx));
let req = req.take().unwrap();
return match res {
Ok(res) => Poll::Ready(Ok(ServiceResponse::new(req, res))),
Err(e) => {
let res: Response = e.into().into();
Poll::Ready(Ok(ServiceResponse::new(req, res)))
}
};
}
}
}
}
}
2019-03-02 06:51:32 +00:00
/// Extract arguments from request
pub struct Extract<T: FromRequest, S> {
service: S,
_t: PhantomData<T>,
}
impl<T: FromRequest, S> Extract<T, S> {
pub fn new(service: S) -> Self {
2019-03-03 08:57:48 +00:00
Extract {
service,
2019-03-03 08:57:48 +00:00
_t: PhantomData,
}
}
2019-03-02 06:51:32 +00:00
}
2019-11-20 17:33:22 +00:00
impl<T: FromRequest, S> ServiceFactory for Extract<T, S>
where
2019-05-12 15:34:51 +00:00
S: Service<
Request = (T, HttpRequest),
Response = ServiceResponse,
Error = Infallible,
> + Clone,
{
type Request = ServiceRequest;
type Response = ServiceResponse;
type Error = Error;
2020-12-19 16:33:34 +00:00
type Config = ();
type Service = ExtractService<T, S>;
2020-12-19 16:33:34 +00:00
type InitError = ();
2019-11-20 17:33:22 +00:00
type Future = Ready<Result<Self::Service, ()>>;
2018-07-15 09:12:21 +00:00
2019-12-02 15:37:13 +00:00
fn new_service(&self, _: ()) -> Self::Future {
2019-03-03 08:57:48 +00:00
ok(ExtractService {
_t: PhantomData,
service: self.service.clone(),
2019-03-03 08:57:48 +00:00
})
2019-03-02 06:51:32 +00:00
}
2017-11-29 21:26:55 +00:00
}
pub struct ExtractService<T: FromRequest, S> {
service: S,
_t: PhantomData<T>,
2017-11-29 21:26:55 +00:00
}
impl<T: FromRequest, S> Service for ExtractService<T, S>
where
2019-05-12 15:34:51 +00:00
S: Service<
Request = (T, HttpRequest),
Response = ServiceResponse,
Error = Infallible,
> + Clone,
{
type Request = ServiceRequest;
type Response = ServiceResponse;
type Error = Error;
type Future = ExtractResponse<T, S>;
2019-03-02 06:51:32 +00:00
2019-12-07 18:46:51 +00:00
fn poll_ready(&mut self, _: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
2019-11-20 17:33:22 +00:00
Poll::Ready(Ok(()))
2017-11-29 21:26:55 +00:00
}
fn call(&mut self, req: ServiceRequest) -> Self::Future {
let (req, mut payload) = req.into_parts();
2019-11-20 17:33:22 +00:00
let fut = T::from_request(&req, &mut payload);
2020-12-19 16:33:34 +00:00
ExtractResponse::Future(fut, Some(req), self.service.clone())
2017-11-29 21:26:55 +00:00
}
}
2020-12-19 16:33:34 +00:00
#[pin_project(project = ExtractProj)]
pub enum ExtractResponse<T: FromRequest, S: Service> {
Future(#[pin] T::Future, Option<HttpRequest>, S),
Response(#[pin] S::Future),
2017-11-29 21:26:55 +00:00
}
impl<T: FromRequest, S> Future for ExtractResponse<T, S>
where
2019-05-12 15:34:51 +00:00
S: Service<
Request = (T, HttpRequest),
Response = ServiceResponse,
Error = Infallible,
>,
{
type Output = Result<ServiceResponse, Error>;
2017-11-29 21:26:55 +00:00
2019-12-07 18:46:51 +00:00
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
2020-12-19 16:33:34 +00:00
loop {
match self.as_mut().project() {
ExtractProj::Future(fut, req, srv) => {
let res = ready!(fut.poll(cx));
let req = req.take().unwrap();
match res {
Err(e) => {
let req = ServiceRequest::new(req);
return Poll::Ready(Ok(req.error_response(e.into())));
2020-12-19 16:33:34 +00:00
}
Ok(item) => {
let fut = srv.call((item, req));
self.as_mut().set(ExtractResponse::Response(fut));
}
}
}
ExtractProj::Response(fut) => return fut.poll(cx).map_err(|_| panic!()),
2019-11-20 17:33:22 +00:00
}
}
2018-03-29 22:41:13 +00:00
}
}
2019-03-02 06:51:32 +00:00
/// FromRequest trait impl for tuples
macro_rules! factory_tuple ({ $(($n:tt, $T:ident)),+} => {
2019-11-21 15:34:04 +00:00
impl<Func, $($T,)+ Res, O> Factory<($($T,)+), Res, O> for Func
2019-03-02 06:51:32 +00:00
where Func: Fn($($T,)+) -> Res + Clone + 'static,
Res: Future<Output = O>,
2019-11-20 17:33:22 +00:00
O: Responder,
2019-03-02 06:51:32 +00:00
{
fn call(&self, param: ($($T,)+)) -> Res {
(self)($(param.$n,)+)
}
2018-03-29 22:41:13 +00:00
}
2019-03-02 06:51:32 +00:00
});
#[rustfmt::skip]
mod m {
use super::*;
factory_tuple!((0, A));
factory_tuple!((0, A), (1, B));
factory_tuple!((0, A), (1, B), (2, C));
factory_tuple!((0, A), (1, B), (2, C), (3, D));
factory_tuple!((0, A), (1, B), (2, C), (3, D), (4, E));
factory_tuple!((0, A), (1, B), (2, C), (3, D), (4, E), (5, F));
factory_tuple!((0, A), (1, B), (2, C), (3, D), (4, E), (5, F), (6, G));
factory_tuple!((0, A), (1, B), (2, C), (3, D), (4, E), (5, F), (6, G), (7, H));
factory_tuple!((0, A), (1, B), (2, C), (3, D), (4, E), (5, F), (6, G), (7, H), (8, I));
factory_tuple!((0, A), (1, B), (2, C), (3, D), (4, E), (5, F), (6, G), (7, H), (8, I), (9, J));
2018-03-29 22:41:13 +00:00
}