1
0
Fork 0
mirror of https://github.com/actix/actix-web.git synced 2024-10-21 17:33:59 +00: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.
Response object could be generated asynchronously. In this case handle must
return `Future` object that resolves to `HttpResponse`, i.e:
Response object could be generated asynchronously or more precisely, any type
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
# extern crate actix_web;
@ -114,9 +115,14 @@ fn index(req: HttpRequest) -> FutureResult<HttpResponse, Error> {
.map_err(|e| e.into()))
}
fn index2(req: HttpRequest) -> FutureResult<&'static str, Error> {
result(Ok("Welcome!"))
}
fn main() {
Application::new()
.resource("/async", |r| r.route().a(index))
.resource("/", |r| r.route().a(index2))
.finish();
}
```

View file

@ -1,7 +1,7 @@
use std::marker::PhantomData;
use actix::Actor;
use futures::Future;
use futures::future::{Future, ok, err};
use serde_json;
use serde::Serialize;
use regex::Regex;
@ -221,36 +221,53 @@ impl<S, H, R> RouteHandler<S> for WrapHandler<S, H, R>
/// Async route handler
pub(crate)
struct AsyncHandler<S, R, F>
where F: Fn(HttpRequest<S>) -> R + 'static,
R: Future<Item=HttpResponse, Error=Error> + 'static,
struct AsyncHandler<S, H, F, R, E>
where H: Fn(HttpRequest<S>) -> F + 'static,
F: Future<Item=R, Error=E> + 'static,
R: Responder + 'static,
E: Into<Error> + 'static,
S: 'static,
{
f: Box<F>,
h: Box<H>,
s: PhantomData<S>,
}
impl<S, R, F> AsyncHandler<S, R, F>
where F: Fn(HttpRequest<S>) -> R + 'static,
R: Future<Item=HttpResponse, Error=Error> + 'static,
impl<S, H, F, R, E> AsyncHandler<S, H, F, R, E>
where H: Fn(HttpRequest<S>) -> F + 'static,
F: Future<Item=R, Error=E> + 'static,
R: Responder + 'static,
E: Into<Error> + 'static,
S: 'static,
{
pub fn new(f: F) -> Self {
AsyncHandler{f: Box::new(f), s: PhantomData}
pub fn new(h: H) -> Self {
AsyncHandler{h: Box::new(h), s: PhantomData}
}
}
impl<S, R, F> RouteHandler<S> for AsyncHandler<S, R, F>
where F: Fn(HttpRequest<S>) -> R + 'static,
R: Future<Item=HttpResponse, Error=Error> + 'static,
impl<S, H, F, R, E> RouteHandler<S> for AsyncHandler<S, H, F, R, E>
where H: Fn(HttpRequest<S>) -> F + 'static,
F: Future<Item=R, Error=E> + 'static,
R: Responder + 'static,
E: Into<Error> + 'static,
S: 'static,
{
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
///
/// 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 httpcodes::HTTPNotFound;
use httprequest::HttpRequest;
use httpresponse::HttpResponse;
/// Resource route definition
///
@ -80,9 +78,11 @@ impl<S: 'static> Route<S> {
}
/// Set async handler function.
pub fn a<F, R>(&mut self, handler: F)
where F: Fn(HttpRequest<S>) -> R + 'static,
R: Future<Item=HttpResponse, Error=Error> + 'static,
pub fn a<H, R, F, E>(&mut self, handler: H)
where H: Fn(HttpRequest<S>) -> F + 'static,
F: Future<Item=R, Error=E> + 'static,
R: Responder + 'static,
E: Into<Error> + 'static
{
self.handler = Box::new(AsyncHandler::new(handler));
}