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:
parent
c3a39e026d
commit
813b56ebe5
@ -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();
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
@ -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
|
||||||
|
10
src/route.rs
10
src/route.rs
@ -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));
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user