mirror of
https://github.com/actix/actix-web.git
synced 2024-11-27 12:01:15 +00:00
make async handler future more generic
This commit is contained in:
parent
c3a39e026d
commit
813b56ebe5
3 changed files with 45 additions and 22 deletions
|
@ -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();
|
||||
}
|
||||
```
|
||||
|
|
|
@ -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
|
||||
|
|
10
src/route.rs
10
src/route.rs
|
@ -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));
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue