1
0
mirror of https://github.com/actix/actix-extras.git synced 2024-11-28 01:32:57 +01:00

rename async to a

This commit is contained in:
Nikolay Kim 2017-12-04 16:09:22 -08:00
parent e98972e93b
commit f4e9fc7b6a
7 changed files with 137 additions and 110 deletions

View File

@ -50,7 +50,7 @@ after_success:
- | - |
if [[ "$TRAVIS_OS_NAME" == "linux" && "$TRAVIS_RUST_VERSION" == "stable" ]]; then if [[ "$TRAVIS_OS_NAME" == "linux" && "$TRAVIS_RUST_VERSION" == "stable" ]]; then
bash <(curl https://raw.githubusercontent.com/xd009642/tarpaulin/master/travis-install.sh) bash <(curl https://raw.githubusercontent.com/xd009642/tarpaulin/master/travis-install.sh)
cargo tarpaulin --exclude examples --out Xml cargo tarpaulin --exclude ./examples/* --out Xml
bash <(curl -s https://codecov.io/bash) bash <(curl -s https://codecov.io/bash)
echo "Uploaded code coverage" echo "Uploaded code coverage"
fi fi

View File

@ -71,7 +71,7 @@ fn main() {
// with path parameters // with path parameters
.resource("/user/{name}/", |r| r.route().method(Method::GET).f(with_param)) .resource("/user/{name}/", |r| r.route().method(Method::GET).f(with_param))
// async handler // async handler
.resource("/async/{name}", |r| r.route().method(Method::GET).async(index_async)) .resource("/async/{name}", |r| r.route().method(Method::GET).a(index_async))
// redirect // redirect
.resource("/", |r| r.route().method(Method::GET).f(|req| { .resource("/", |r| r.route().method(Method::GET).f(|req| {
println!("{:?}", req); println!("{:?}", req);

View File

@ -96,31 +96,50 @@ 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. In this case handle must
return `Future` object that resolves to `HttpResponse`, i.e: return `Future` object that resolves to `HttpResponse`, i.e:
```rust,ignore ```rust
fn index(req: HttpRequest) -> Box<Future<HttpResponse, Error>> { # extern crate actix_web;
... # extern crate futures;
} # extern crate bytes;
``` # use actix_web::*;
# use bytes::Bytes;
# use futures::stream::once;
# use futures::future::{FutureResult, result};
fn index(req: HttpRequest) -> FutureResult<HttpResponse, Error> {
This handler can be registered with `ApplicationBuilder::async()` and result(HttpResponse::Ok()
`Resource::async()` methods. .content_type("text/html")
.body(format!("Hello!"))
Or response body can be generated asynchronously. In this case body .map_err(|e| e.into()))
must implement stream trait `Stream<Item=Bytes, Error=Error>`, i.e:
```rust,ignore
fn index(req: HttpRequest) -> HttpResponse {
let body: Box<Stream<Item=Bytes, Error=Error>> = Box::new(SomeStream::new());
HttpResponse::Ok().
.content_type("application/json")
.body(Body::Streaming(body)).unwrap()
} }
fn main() { fn main() {
Application::default("/") Application::default("/")
.async("/async", index) .route("/async", |r| r.a(index))
.finish();
}
```
Or response body can be generated asynchronously. In this case body
must implement stream trait `Stream<Item=Bytes, Error=Error>`, i.e:
```rust
# extern crate actix_web;
# extern crate futures;
# extern crate bytes;
# use actix_web::*;
# use bytes::Bytes;
# use futures::stream::once;
fn index(req: HttpRequest) -> HttpResponse {
let body = once(Ok(Bytes::from_static(b"test")));
HttpResponse::Ok()
.content_type("application/json")
.body(Body::Streaming(Box::new(body))).unwrap()
}
fn main() {
Application::default("/")
.route("/async", |r| r.f(index))
.finish(); .finish();
} }
``` ```

View File

@ -2,7 +2,8 @@ use std::rc::Rc;
use std::collections::HashMap; use std::collections::HashMap;
use handler::{Reply, RouteHandler}; use handler::{Reply, RouteHandler};
use resource::{Route, Resource}; use route::Route;
use resource::Resource;
use recognizer::{RouteRecognizer, check_pattern}; use recognizer::{RouteRecognizer, check_pattern};
use httprequest::HttpRequest; use httprequest::HttpRequest;
use channel::HttpHandler; use channel::HttpHandler;

View File

@ -55,6 +55,7 @@ mod encoding;
mod httprequest; mod httprequest;
mod httpresponse; mod httpresponse;
mod payload; mod payload;
mod route;
mod resource; mod resource;
mod recognizer; mod recognizer;
mod handler; mod handler;
@ -84,7 +85,8 @@ pub use httprequest::{HttpRequest, UrlEncoded};
pub use httpresponse::HttpResponse; pub use httpresponse::HttpResponse;
pub use payload::{Payload, PayloadItem}; pub use payload::{Payload, PayloadItem};
pub use handler::{Reply, Json, FromRequest}; pub use handler::{Reply, Json, FromRequest};
pub use resource::{Route, Resource}; pub use route::Route;
pub use resource::Resource;
pub use recognizer::Params; pub use recognizer::Params;
pub use server::HttpServer; pub use server::HttpServer;
pub use context::HttpContext; pub use context::HttpContext;

View File

@ -1,96 +1,13 @@
use std::marker::PhantomData; use std::marker::PhantomData;
use http::Method; use http::Method;
use futures::Future;
use error::Error; use route::Route;
use pred::{self, Predicate}; use handler::{Reply, Handler, RouteHandler, WrapHandler};
use handler::{Reply, Handler, FromRequest, RouteHandler, AsyncHandler, WrapHandler};
use httpcodes::HTTPNotFound; use httpcodes::HTTPNotFound;
use httprequest::HttpRequest; use httprequest::HttpRequest;
use httpresponse::HttpResponse;
/// Resource route definition /// *Resource* is an entry in route table which corresponds to requested URL.
///
/// Route uses builder-like pattern for configuration.
/// If handler is not explicitly set, default *404 Not Found* handler is used.
pub struct Route<S> {
preds: Vec<Box<Predicate<S>>>,
handler: Box<RouteHandler<S>>,
}
impl<S: 'static> Default for Route<S> {
fn default() -> Route<S> {
Route {
preds: Vec::new(),
handler: Box::new(WrapHandler::new(|_| HTTPNotFound)),
}
}
}
impl<S: 'static> Route<S> {
pub(crate) fn check(&self, req: &mut HttpRequest<S>) -> bool {
for pred in &self.preds {
if !pred.check(req) {
return false
}
}
true
}
pub(crate) fn handle(&self, req: HttpRequest<S>) -> Reply {
self.handler.handle(req)
}
/// Add match predicate to route.
pub fn p(&mut self, p: Box<Predicate<S>>) -> &mut Self {
self.preds.push(p);
self
}
/// Add predicates to route.
pub fn predicates<P>(&mut self, preds: P) -> &mut Self
where P: IntoIterator<Item=Box<Predicate<S>>>
{
self.preds.extend(preds.into_iter());
self
}
/// Add method check to route. This method could be called multiple times.
pub fn method(&mut self, method: Method) -> &mut Self {
self.preds.push(pred::Method(method));
self
}
/// Set handler object. Usually call to this method is last call
/// during route configuration, because it does not return reference to self.
pub fn h<H: Handler<S>>(&mut self, handler: H) {
self.handler = Box::new(WrapHandler::new(handler));
}
/// Set handler function. Usually call to this method is last call
/// during route configuration, because it does not return reference to self.
pub fn f<F, R>(&mut self, handler: F)
where F: Fn(HttpRequest<S>) -> R + 'static,
R: FromRequest + 'static,
{
self.handler = Box::new(WrapHandler::new(handler));
}
/// Set handler function.
pub fn async<F, R>(&mut self, handler: F)
where F: Fn(HttpRequest<S>) -> R + 'static,
R: Future<Item=HttpResponse, Error=Error> + 'static,
{
self.handler = Box::new(AsyncHandler::new(handler));
}
}
/// Http resource
///
/// `Resource` is an entry in route table which corresponds to requested URL.
/// ///
/// Resource in turn has at least one route. /// Resource in turn has at least one route.
/// Route consists of an object that implements `Handler` trait (handler) /// Route consists of an object that implements `Handler` trait (handler)

88
src/route.rs Normal file
View File

@ -0,0 +1,88 @@
use http::Method;
use futures::Future;
use error::Error;
use pred::{self, Predicate};
use handler::{Reply, Handler, FromRequest, RouteHandler, AsyncHandler, WrapHandler};
use httpcodes::HTTPNotFound;
use httprequest::HttpRequest;
use httpresponse::HttpResponse;
/// Resource route definition
///
/// Route uses builder-like pattern for configuration.
/// If handler is not explicitly set, default *404 Not Found* handler is used.
pub struct Route<S> {
preds: Vec<Box<Predicate<S>>>,
handler: Box<RouteHandler<S>>,
}
impl<S: 'static> Default for Route<S> {
fn default() -> Route<S> {
Route {
preds: Vec::new(),
handler: Box::new(WrapHandler::new(|_| HTTPNotFound)),
}
}
}
impl<S: 'static> Route<S> {
pub(crate) fn check(&self, req: &mut HttpRequest<S>) -> bool {
for pred in &self.preds {
if !pred.check(req) {
return false
}
}
true
}
pub(crate) fn handle(&self, req: HttpRequest<S>) -> Reply {
self.handler.handle(req)
}
/// Add match predicate to route.
pub fn p(&mut self, p: Box<Predicate<S>>) -> &mut Self {
self.preds.push(p);
self
}
/// Add predicates to route.
pub fn predicates<P>(&mut self, preds: P) -> &mut Self
where P: IntoIterator<Item=Box<Predicate<S>>>
{
self.preds.extend(preds.into_iter());
self
}
/// Add method check to route. This method could be called multiple times.
pub fn method(&mut self, method: Method) -> &mut Self {
self.preds.push(pred::Method(method));
self
}
/// Set handler object. Usually call to this method is last call
/// during route configuration, because it does not return reference to self.
pub fn h<H: Handler<S>>(&mut self, handler: H) {
self.handler = Box::new(WrapHandler::new(handler));
}
/// Set handler function. Usually call to this method is last call
/// during route configuration, because it does not return reference to self.
pub fn f<F, R>(&mut self, handler: F)
where F: Fn(HttpRequest<S>) -> R + 'static,
R: FromRequest + 'static,
{
self.handler = Box::new(WrapHandler::new(handler));
}
/// 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,
{
self.handler = Box::new(AsyncHandler::new(handler));
}
}