1
0
mirror of https://github.com/actix/actix-extras.git synced 2024-11-24 07:53:00 +01:00

make async handler future more generic

This commit is contained in:
Nikolay Kim 2017-12-20 12:51:39 -08:00
parent c3a39e026d
commit 813b56ebe5
3 changed files with 45 additions and 22 deletions

View File

@ -95,8 +95,9 @@ fn main() {
There are two different types of async handlers. There are two different types of async handlers.
Response object could be generated asynchronously. In this case handle must Response object could be generated asynchronously or more precisely, any type
return `Future` object that resolves to `HttpResponse`, i.e: that implements [*Responder*](../actix_web/trait.Responder.html) trait. In this case handle must
return `Future` object that resolves to *Responder* type, i.e:
```rust ```rust
# extern crate actix_web; # extern crate actix_web;
@ -114,9 +115,14 @@ fn index(req: HttpRequest) -> FutureResult<HttpResponse, Error> {
.map_err(|e| e.into())) .map_err(|e| e.into()))
} }
fn index2(req: HttpRequest) -> FutureResult<&'static str, Error> {
result(Ok("Welcome!"))
}
fn main() { fn main() {
Application::new() Application::new()
.resource("/async", |r| r.route().a(index)) .resource("/async", |r| r.route().a(index))
.resource("/", |r| r.route().a(index2))
.finish(); .finish();
} }
``` ```

View File

@ -1,7 +1,7 @@
use std::marker::PhantomData; use std::marker::PhantomData;
use actix::Actor; use actix::Actor;
use futures::Future; use futures::future::{Future, ok, err};
use serde_json; use serde_json;
use serde::Serialize; use serde::Serialize;
use regex::Regex; use regex::Regex;
@ -221,36 +221,53 @@ impl<S, H, R> RouteHandler<S> for WrapHandler<S, H, R>
/// Async route handler /// Async route handler
pub(crate) pub(crate)
struct AsyncHandler<S, R, F> struct AsyncHandler<S, H, F, R, E>
where F: Fn(HttpRequest<S>) -> R + 'static, where H: Fn(HttpRequest<S>) -> F + 'static,
R: Future<Item=HttpResponse, Error=Error> + 'static, F: Future<Item=R, Error=E> + 'static,
R: Responder + 'static,
E: Into<Error> + 'static,
S: 'static, S: 'static,
{ {
f: Box<F>, h: Box<H>,
s: PhantomData<S>, s: PhantomData<S>,
} }
impl<S, R, F> AsyncHandler<S, R, F> impl<S, H, F, R, E> AsyncHandler<S, H, F, R, E>
where F: Fn(HttpRequest<S>) -> R + 'static, where H: Fn(HttpRequest<S>) -> F + 'static,
R: Future<Item=HttpResponse, Error=Error> + 'static, F: Future<Item=R, Error=E> + 'static,
R: Responder + 'static,
E: Into<Error> + 'static,
S: 'static, S: 'static,
{ {
pub fn new(f: F) -> Self { pub fn new(h: H) -> Self {
AsyncHandler{f: Box::new(f), s: PhantomData} AsyncHandler{h: Box::new(h), s: PhantomData}
} }
} }
impl<S, R, F> RouteHandler<S> for AsyncHandler<S, R, F> impl<S, H, F, R, E> RouteHandler<S> for AsyncHandler<S, H, F, R, E>
where F: Fn(HttpRequest<S>) -> R + 'static, where H: Fn(HttpRequest<S>) -> F + 'static,
R: Future<Item=HttpResponse, Error=Error> + 'static, F: Future<Item=R, Error=E> + 'static,
R: Responder + 'static,
E: Into<Error> + 'static,
S: 'static, S: 'static,
{ {
fn handle(&self, req: HttpRequest<S>) -> Reply { fn handle(&self, req: HttpRequest<S>) -> Reply {
Reply::async((self.f)(req)) let req2 = req.clone_without_state();
let fut = (self.h)(req)
.map_err(|e| e.into())
.then(move |r| {
match r.respond_to(req2) {
Ok(reply) => match reply.into().0 {
ReplyItem::Message(resp) => ok(resp),
_ => panic!("Nested async replies are not supported"),
}
Err(e) => err(e),
}
});
Reply::async(fut)
} }
} }
/// Json response helper /// Json response helper
/// ///
/// The `Json` type allows you to respond with well-formed JSON data: simply return a value of /// The `Json` type allows you to respond with well-formed JSON data: simply return a value of

View File

@ -5,8 +5,6 @@ use pred::Predicate;
use handler::{Reply, Handler, Responder, RouteHandler, AsyncHandler, WrapHandler}; use handler::{Reply, Handler, Responder, RouteHandler, AsyncHandler, WrapHandler};
use httpcodes::HTTPNotFound; use httpcodes::HTTPNotFound;
use httprequest::HttpRequest; use httprequest::HttpRequest;
use httpresponse::HttpResponse;
/// Resource route definition /// Resource route definition
/// ///
@ -80,9 +78,11 @@ impl<S: 'static> Route<S> {
} }
/// Set async handler function. /// Set async handler function.
pub fn a<F, R>(&mut self, handler: F) pub fn a<H, R, F, E>(&mut self, handler: H)
where F: Fn(HttpRequest<S>) -> R + 'static, where H: Fn(HttpRequest<S>) -> F + 'static,
R: Future<Item=HttpResponse, Error=Error> + 'static, F: Future<Item=R, Error=E> + 'static,
R: Responder + 'static,
E: Into<Error> + 'static
{ {
self.handler = Box::new(AsyncHandler::new(handler)); self.handler = Box::new(AsyncHandler::new(handler));
} }