1
0
Fork 0
mirror of https://github.com/actix/actix-web.git synced 2024-06-02 13:29:24 +00:00
actix-web/src/route.rs

667 lines
20 KiB
Rust
Raw Normal View History

2018-04-13 23:02:01 +00:00
use std::marker::PhantomData;
2018-01-10 04:00:18 +00:00
use std::rc::Rc;
2017-12-05 00:09:22 +00:00
2018-04-30 02:35:50 +00:00
use futures::{Async, Future, Poll};
2017-12-05 00:09:22 +00:00
use error::Error;
use handler::{
AsyncHandler, AsyncResult, AsyncResultItem, FromRequest, Handler, Responder,
RouteHandler, WrapHandler,
};
use http::StatusCode;
2017-12-05 00:09:22 +00:00
use httprequest::HttpRequest;
2018-01-10 04:00:18 +00:00
use httpresponse::HttpResponse;
use middleware::{
Finished as MiddlewareFinished, Middleware, Response as MiddlewareResponse,
Started as MiddlewareStarted,
};
2018-04-13 23:02:01 +00:00
use pred::Predicate;
use with::{WithAsyncFactory, WithFactory};
2017-12-05 00:09:22 +00:00
/// 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>>>,
2018-01-10 04:00:18 +00:00
handler: InnerHandler<S>,
2017-12-05 00:09:22 +00:00
}
impl<S: 'static> Default for Route<S> {
fn default() -> Route<S> {
Route {
preds: Vec::new(),
2018-06-25 04:58:04 +00:00
handler: InnerHandler::new(|_: &_| HttpResponse::new(StatusCode::NOT_FOUND)),
2017-12-05 00:09:22 +00:00
}
}
}
impl<S: 'static> Route<S> {
2018-01-10 04:00:18 +00:00
#[inline]
2018-06-25 04:58:04 +00:00
pub(crate) fn check(&self, req: &HttpRequest<S>) -> bool {
let state = req.state();
2017-12-05 00:09:22 +00:00
for pred in &self.preds {
2018-06-25 04:58:04 +00:00
if !pred.check(req, state) {
2018-04-13 23:02:01 +00:00
return false;
2017-12-05 00:09:22 +00:00
}
}
true
}
2018-01-10 04:00:18 +00:00
#[inline]
2018-06-25 04:58:04 +00:00
pub(crate) fn handle(&self, req: &HttpRequest<S>) -> AsyncResult<HttpResponse> {
2017-12-05 00:09:22 +00:00
self.handler.handle(req)
}
2018-01-10 04:00:18 +00:00
#[inline]
2018-04-13 23:02:01 +00:00
pub(crate) fn compose(
2018-06-21 17:06:23 +00:00
&self, req: HttpRequest<S>, mws: Rc<Vec<Box<Middleware<S>>>>,
2018-05-03 23:22:08 +00:00
) -> AsyncResult<HttpResponse> {
AsyncResult::future(Box::new(Compose::new(req, mws, self.handler.clone())))
2018-01-10 04:00:18 +00:00
}
2017-12-05 00:32:31 +00:00
/// Add match predicate to route.
2017-12-20 06:36:06 +00:00
///
/// ```rust
/// # extern crate actix_web;
/// # use actix_web::*;
/// # fn main() {
2018-06-01 16:37:14 +00:00
/// App::new().resource("/path", |r| {
/// r.route()
/// .filter(pred::Get())
/// .filter(pred::Header("content-type", "text/plain"))
/// .f(|req| HttpResponse::Ok())
/// })
2017-12-20 06:36:06 +00:00
/// # .finish();
/// # }
/// ```
2018-03-02 02:32:31 +00:00
pub fn filter<T: Predicate<S> + 'static>(&mut self, p: T) -> &mut Self {
2017-12-20 21:23:50 +00:00
self.preds.push(Box::new(p));
2017-12-05 00:09:22 +00:00
self
}
/// Set handler object. Usually call to this method is last call
2018-03-07 22:56:53 +00:00
/// during route configuration, so it does not return reference to self.
2017-12-05 00:09:22 +00:00
pub fn h<H: Handler<S>>(&mut self, handler: H) {
2018-01-10 04:00:18 +00:00
self.handler = InnerHandler::new(handler);
2017-12-05 00:09:22 +00:00
}
/// Set handler function. Usually call to this method is last call
2018-03-07 22:56:53 +00:00
/// during route configuration, so it does not return reference to self.
2017-12-05 00:09:22 +00:00
pub fn f<F, R>(&mut self, handler: F)
2018-04-13 23:02:01 +00:00
where
2018-06-25 04:58:04 +00:00
F: Fn(&HttpRequest<S>) -> R + 'static,
2018-04-13 23:02:01 +00:00
R: Responder + 'static,
2017-12-05 00:09:22 +00:00
{
2018-01-10 04:00:18 +00:00
self.handler = InnerHandler::new(handler);
2017-12-05 00:09:22 +00:00
}
/// Set async handler function.
2017-12-20 20:51:39 +00:00
pub fn a<H, R, F, E>(&mut self, handler: H)
2018-04-13 23:02:01 +00:00
where
2018-06-25 04:58:04 +00:00
H: Fn(&HttpRequest<S>) -> F + 'static,
2018-04-13 23:02:01 +00:00
F: Future<Item = R, Error = E> + 'static,
R: Responder + 'static,
E: Into<Error> + 'static,
2017-12-05 00:09:22 +00:00
{
2018-01-10 04:00:18 +00:00
self.handler = InnerHandler::async(handler);
}
2018-03-27 06:10:31 +00:00
2018-05-06 16:07:30 +00:00
/// Set handler function, use request extractor for parameters.
2018-03-27 06:10:31 +00:00
///
/// ```rust
/// # extern crate bytes;
/// # extern crate actix_web;
/// # extern crate futures;
/// #[macro_use] extern crate serde_derive;
2018-06-01 16:37:14 +00:00
/// use actix_web::{http, App, Path, Result};
2018-03-27 06:10:31 +00:00
///
/// #[derive(Deserialize)]
/// struct Info {
/// username: String,
/// }
///
/// /// extract path info using serde
2018-03-28 03:33:24 +00:00
/// fn index(info: Path<Info>) -> Result<String> {
2018-03-27 06:10:31 +00:00
/// Ok(format!("Welcome {}!", info.username))
/// }
///
/// fn main() {
2018-03-31 07:16:55 +00:00
/// let app = App::new().resource(
2018-06-01 16:37:14 +00:00
/// "/{username}/index.html", // <- define path parameters
/// |r| r.method(http::Method::GET).with(index),
/// ); // <- use `with` extractor
2018-03-27 06:10:31 +00:00
/// }
/// ```
///
2018-10-02 04:16:56 +00:00
/// It is possible to use multiple extractors for one handler function.
///
/// ```rust
/// # extern crate bytes;
/// # extern crate actix_web;
/// # extern crate futures;
/// #[macro_use] extern crate serde_derive;
/// # use std::collections::HashMap;
2018-06-01 16:37:14 +00:00
/// use actix_web::{http, App, Json, Path, Query, Result};
///
/// #[derive(Deserialize)]
/// struct Info {
/// username: String,
/// }
///
/// /// extract path info using serde
2018-06-01 16:37:14 +00:00
/// fn index(
2018-10-02 04:16:56 +00:00
/// path: Path<Info>, query: Query<HashMap<String, String>>, body: Json<Info>,
2018-06-01 16:37:14 +00:00
/// ) -> Result<String> {
2018-10-02 04:16:56 +00:00
/// Ok(format!("Welcome {}!", path.username))
/// }
///
/// fn main() {
/// let app = App::new().resource(
2018-06-01 16:37:14 +00:00
/// "/{username}/index.html", // <- define path parameters
/// |r| r.method(http::Method::GET).with(index),
/// ); // <- use `with` extractor
/// }
/// ```
2018-06-21 05:47:01 +00:00
pub fn with<T, F, R>(&mut self, handler: F)
2018-04-13 23:02:01 +00:00
where
F: WithFactory<T, S, R> + 'static,
2018-04-13 23:02:01 +00:00
R: Responder + 'static,
T: FromRequest<S> + 'static,
2018-03-27 06:10:31 +00:00
{
self.h(handler.create());
2018-06-21 05:47:01 +00:00
}
/// Set handler function. Same as `.with()` but it allows to configure
/// extractor. Configuration closure accepts config objects as tuple.
2018-06-21 05:47:01 +00:00
///
/// ```rust
/// # extern crate bytes;
/// # extern crate actix_web;
/// # extern crate futures;
/// #[macro_use] extern crate serde_derive;
/// use actix_web::{http, App, Path, Result};
///
/// /// extract text data from request
/// fn index(body: String) -> Result<String> {
/// Ok(format!("Body {}!", body))
/// }
///
/// fn main() {
/// let app = App::new().resource("/index.html", |r| {
/// r.method(http::Method::GET)
/// .with_config(index, |cfg| { // <- register handler
/// cfg.0.limit(4096); // <- limit size of the payload
2018-06-21 05:47:01 +00:00
/// })
/// });
/// }
/// ```
pub fn with_config<T, F, R, C>(&mut self, handler: F, cfg_f: C)
where
F: WithFactory<T, S, R>,
2018-06-21 05:47:01 +00:00
R: Responder + 'static,
T: FromRequest<S> + 'static,
C: FnOnce(&mut T::Config),
{
let mut cfg = <T::Config as Default>::default();
cfg_f(&mut cfg);
self.h(handler.create_with_config(cfg));
2018-03-27 06:10:31 +00:00
}
2018-03-28 21:24:32 +00:00
/// Set async handler function, use request extractor for parameters.
2018-05-10 20:04:56 +00:00
/// Also this method needs to be used if your handler function returns
/// `impl Future<>`
///
/// ```rust
/// # extern crate bytes;
/// # extern crate actix_web;
/// # extern crate futures;
/// #[macro_use] extern crate serde_derive;
2018-06-01 16:37:14 +00:00
/// use actix_web::{http, App, Error, Path};
/// use futures::Future;
///
/// #[derive(Deserialize)]
/// struct Info {
/// username: String,
/// }
///
/// /// extract path info using serde
2018-06-01 16:37:14 +00:00
/// fn index(info: Path<Info>) -> Box<Future<Item = &'static str, Error = Error>> {
/// unimplemented!()
/// }
///
/// fn main() {
/// let app = App::new().resource(
2018-06-01 16:37:14 +00:00
/// "/{username}/index.html", // <- define path parameters
/// |r| r.method(http::Method::GET).with_async(index),
/// ); // <- use `with` extractor
/// }
/// ```
2018-06-21 05:47:01 +00:00
pub fn with_async<T, F, R, I, E>(&mut self, handler: F)
where
F: WithAsyncFactory<T, S, R, I, E>,
2018-06-21 05:47:01 +00:00
R: Future<Item = I, Error = E> + 'static,
I: Responder + 'static,
E: Into<Error> + 'static,
T: FromRequest<S> + 'static,
{
self.h(handler.create());
2018-06-21 05:47:01 +00:00
}
/// Set async handler function, use request extractor for parameters.
/// This method allows to configure extractor. Configuration closure
/// accepts config objects as tuple.
2018-06-21 05:47:01 +00:00
///
/// ```rust
/// # extern crate bytes;
/// # extern crate actix_web;
/// # extern crate futures;
/// #[macro_use] extern crate serde_derive;
2018-06-21 06:04:00 +00:00
/// use actix_web::{http, App, Error, Form};
2018-06-21 05:47:01 +00:00
/// use futures::Future;
///
/// #[derive(Deserialize)]
/// struct Info {
/// username: String,
/// }
///
/// /// extract path info using serde
/// fn index(info: Form<Info>) -> Box<Future<Item = &'static str, Error = Error>> {
/// unimplemented!()
/// }
///
/// fn main() {
/// let app = App::new().resource(
/// "/{username}/index.html", // <- define path parameters
/// |r| r.method(http::Method::GET)
/// .with_async_config(index, |cfg| {
/// cfg.0.limit(4096);
2018-06-21 05:47:01 +00:00
/// }),
/// ); // <- use `with` extractor
/// }
/// ```
pub fn with_async_config<T, F, R, I, E, C>(&mut self, handler: F, cfg: C)
where
F: WithAsyncFactory<T, S, R, I, E>,
R: Future<Item = I, Error = E> + 'static,
I: Responder + 'static,
E: Into<Error> + 'static,
T: FromRequest<S> + 'static,
2018-06-21 05:47:01 +00:00
C: FnOnce(&mut T::Config),
{
2018-06-21 05:47:01 +00:00
let mut extractor_cfg = <T::Config as Default>::default();
cfg(&mut extractor_cfg);
self.h(handler.create_with_config(extractor_cfg));
}
2018-01-10 04:00:18 +00:00
}
2018-04-13 23:02:01 +00:00
/// `RouteHandler` wrapper. This struct is required because it needs to be
/// shared for resource level middlewares.
2018-06-21 17:21:28 +00:00
struct InnerHandler<S>(Rc<Box<RouteHandler<S>>>);
2018-01-10 04:00:18 +00:00
impl<S: 'static> InnerHandler<S> {
#[inline]
fn new<H: Handler<S>>(h: H) -> Self {
2018-06-21 17:21:28 +00:00
InnerHandler(Rc::new(Box::new(WrapHandler::new(h))))
2018-01-10 04:00:18 +00:00
}
#[inline]
fn async<H, R, F, E>(h: H) -> Self
2018-04-13 23:02:01 +00:00
where
2018-06-25 04:58:04 +00:00
H: Fn(&HttpRequest<S>) -> F + 'static,
2018-04-13 23:02:01 +00:00
F: Future<Item = R, Error = E> + 'static,
R: Responder + 'static,
E: Into<Error> + 'static,
2018-01-10 04:00:18 +00:00
{
2018-06-21 17:21:28 +00:00
InnerHandler(Rc::new(Box::new(AsyncHandler::new(h))))
2018-01-10 04:00:18 +00:00
}
#[inline]
2018-06-25 04:58:04 +00:00
pub fn handle(&self, req: &HttpRequest<S>) -> AsyncResult<HttpResponse> {
2018-06-21 17:21:28 +00:00
self.0.handle(req)
2018-01-10 04:00:18 +00:00
}
}
impl<S> Clone for InnerHandler<S> {
#[inline]
fn clone(&self) -> Self {
InnerHandler(Rc::clone(&self.0))
}
}
/// Compose resource level middlewares with route handler.
struct Compose<S: 'static> {
info: ComposeInfo<S>,
state: ComposeState<S>,
}
struct ComposeInfo<S: 'static> {
count: usize,
req: HttpRequest<S>,
2018-06-21 17:06:23 +00:00
mws: Rc<Vec<Box<Middleware<S>>>>,
2018-01-10 04:00:18 +00:00
handler: InnerHandler<S>,
}
enum ComposeState<S: 'static> {
Starting(StartMiddlewares<S>),
Handler(WaitingResponse<S>),
RunMiddlewares(RunMiddlewares<S>),
Finishing(FinishingMiddlewares<S>),
Completed(Response<S>),
2018-01-10 04:00:18 +00:00
}
impl<S: 'static> ComposeState<S> {
fn poll(&mut self, info: &mut ComposeInfo<S>) -> Option<ComposeState<S>> {
match *self {
ComposeState::Starting(ref mut state) => state.poll(info),
ComposeState::Handler(ref mut state) => state.poll(info),
ComposeState::RunMiddlewares(ref mut state) => state.poll(info),
ComposeState::Finishing(ref mut state) => state.poll(info),
ComposeState::Completed(_) => None,
2018-01-10 04:00:18 +00:00
}
}
}
impl<S: 'static> Compose<S> {
2018-04-13 23:02:01 +00:00
fn new(
2018-06-21 17:06:23 +00:00
req: HttpRequest<S>, mws: Rc<Vec<Box<Middleware<S>>>>, handler: InnerHandler<S>,
2018-04-13 23:02:01 +00:00
) -> Self {
let mut info = ComposeInfo {
count: 0,
req,
mws,
handler,
};
2018-01-10 04:00:18 +00:00
let state = StartMiddlewares::init(&mut info);
2018-04-29 16:09:08 +00:00
Compose { state, info }
2018-01-10 04:00:18 +00:00
}
}
impl<S> Future for Compose<S> {
type Item = HttpResponse;
type Error = Error;
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
loop {
if let ComposeState::Completed(ref mut resp) = self.state {
2018-01-10 04:00:18 +00:00
let resp = resp.resp.take().unwrap();
2018-04-13 23:02:01 +00:00
return Ok(Async::Ready(resp));
2018-01-10 04:00:18 +00:00
}
if let Some(state) = self.state.poll(&mut self.info) {
self.state = state;
} else {
2018-04-13 23:02:01 +00:00
return Ok(Async::NotReady);
2018-01-10 04:00:18 +00:00
}
}
}
}
/// Middlewares start executor
struct StartMiddlewares<S> {
fut: Option<Fut>,
_s: PhantomData<S>,
}
2018-04-13 23:02:01 +00:00
type Fut = Box<Future<Item = Option<HttpResponse>, Error = Error>>;
2018-01-10 04:00:18 +00:00
impl<S: 'static> StartMiddlewares<S> {
fn init(info: &mut ComposeInfo<S>) -> ComposeState<S> {
2018-06-21 17:06:23 +00:00
let len = info.mws.len();
2018-06-25 04:58:04 +00:00
2018-01-10 04:00:18 +00:00
loop {
if info.count == len {
2018-06-25 04:58:04 +00:00
let reply = info.handler.handle(&info.req);
2018-04-13 23:02:01 +00:00
return WaitingResponse::init(info, reply);
2018-01-10 04:00:18 +00:00
} else {
2018-06-25 04:58:04 +00:00
let result = info.mws[info.count].start(&info.req);
match result {
2018-04-13 23:02:01 +00:00
Ok(MiddlewareStarted::Done) => info.count += 1,
Ok(MiddlewareStarted::Response(resp)) => {
2018-06-25 04:58:04 +00:00
return RunMiddlewares::init(info, resp);
2018-04-13 23:02:01 +00:00
}
2018-05-07 23:09:41 +00:00
Ok(MiddlewareStarted::Future(fut)) => {
return ComposeState::Starting(StartMiddlewares {
fut: Some(fut),
_s: PhantomData,
2018-06-25 04:58:04 +00:00
});
}
Err(err) => {
return RunMiddlewares::init(info, err.into());
2018-05-07 23:09:41 +00:00
}
2018-01-10 04:00:18 +00:00
}
}
}
}
2018-04-13 23:02:01 +00:00
fn poll(&mut self, info: &mut ComposeInfo<S>) -> Option<ComposeState<S>> {
2018-06-21 17:06:23 +00:00
let len = info.mws.len();
2018-06-25 04:58:04 +00:00
2018-01-10 04:00:18 +00:00
'outer: loop {
match self.fut.as_mut().unwrap().poll() {
2018-06-25 04:58:04 +00:00
Ok(Async::NotReady) => {
return None;
}
2018-01-10 04:00:18 +00:00
Ok(Async::Ready(resp)) => {
info.count += 1;
if let Some(resp) = resp {
return Some(RunMiddlewares::init(info, resp));
}
loop {
if info.count == len {
2018-06-25 04:58:04 +00:00
let reply = info.handler.handle(&info.req);
return Some(WaitingResponse::init(info, reply));
} else {
2018-06-25 04:58:04 +00:00
let result = info.mws[info.count].start(&info.req);
match result {
2018-04-13 23:02:01 +00:00
Ok(MiddlewareStarted::Done) => info.count += 1,
2018-01-10 06:48:35 +00:00
Ok(MiddlewareStarted::Response(resp)) => {
2018-01-10 04:00:18 +00:00
return Some(RunMiddlewares::init(info, resp));
2018-04-13 23:02:01 +00:00
}
2018-01-10 06:48:35 +00:00
Ok(MiddlewareStarted::Future(fut)) => {
2018-01-10 04:00:18 +00:00
self.fut = Some(fut);
2018-04-13 23:02:01 +00:00
continue 'outer;
}
Err(err) => {
2018-06-25 04:58:04 +00:00
return Some(RunMiddlewares::init(info, err.into()));
}
2018-01-10 04:00:18 +00:00
}
}
}
}
2018-06-25 04:58:04 +00:00
Err(err) => {
return Some(RunMiddlewares::init(info, err.into()));
}
2018-01-10 04:00:18 +00:00
}
}
}
}
2018-06-25 04:58:04 +00:00
type HandlerFuture = Future<Item = HttpResponse, Error = Error>;
2018-01-10 04:00:18 +00:00
// waiting for response
struct WaitingResponse<S> {
2018-06-25 04:58:04 +00:00
fut: Box<HandlerFuture>,
2018-01-10 04:00:18 +00:00
_s: PhantomData<S>,
}
impl<S: 'static> WaitingResponse<S> {
#[inline]
2018-05-03 23:22:08 +00:00
fn init(
2018-05-17 19:20:20 +00:00
info: &mut ComposeInfo<S>, reply: AsyncResult<HttpResponse>,
2018-05-03 23:22:08 +00:00
) -> ComposeState<S> {
2018-01-10 04:00:18 +00:00
match reply.into() {
2018-05-03 23:22:08 +00:00
AsyncResultItem::Ok(resp) => RunMiddlewares::init(info, resp),
2018-06-25 04:58:04 +00:00
AsyncResultItem::Err(err) => RunMiddlewares::init(info, err.into()),
2018-05-03 23:22:08 +00:00
AsyncResultItem::Future(fut) => ComposeState::Handler(WaitingResponse {
2018-04-13 23:02:01 +00:00
fut,
_s: PhantomData,
}),
2018-01-10 04:00:18 +00:00
}
}
fn poll(&mut self, info: &mut ComposeInfo<S>) -> Option<ComposeState<S>> {
match self.fut.poll() {
Ok(Async::NotReady) => None,
2018-06-25 04:58:04 +00:00
Ok(Async::Ready(resp)) => Some(RunMiddlewares::init(info, resp)),
Err(err) => Some(RunMiddlewares::init(info, err.into())),
2018-01-10 04:00:18 +00:00
}
}
}
/// Middlewares response executor
struct RunMiddlewares<S> {
curr: usize,
2018-04-13 23:02:01 +00:00
fut: Option<Box<Future<Item = HttpResponse, Error = Error>>>,
2018-01-10 04:00:18 +00:00
_s: PhantomData<S>,
}
impl<S: 'static> RunMiddlewares<S> {
fn init(info: &mut ComposeInfo<S>, mut resp: HttpResponse) -> ComposeState<S> {
let mut curr = 0;
2018-06-21 17:06:23 +00:00
let len = info.mws.len();
2018-01-10 04:00:18 +00:00
loop {
2018-06-25 04:58:04 +00:00
let state = info.mws[curr].response(&info.req, resp);
resp = match state {
2018-01-10 06:48:35 +00:00
Err(err) => {
2018-01-10 04:00:18 +00:00
info.count = curr + 1;
return FinishingMiddlewares::init(info, err.into());
2018-04-13 23:02:01 +00:00
}
2018-01-10 06:48:35 +00:00
Ok(MiddlewareResponse::Done(r)) => {
2018-01-10 04:00:18 +00:00
curr += 1;
if curr == len {
return FinishingMiddlewares::init(info, r);
2018-01-10 04:00:18 +00:00
} else {
r
}
2018-04-13 23:02:01 +00:00
}
2018-01-10 06:48:35 +00:00
Ok(MiddlewareResponse::Future(fut)) => {
2018-04-13 23:02:01 +00:00
return ComposeState::RunMiddlewares(RunMiddlewares {
curr,
fut: Some(fut),
_s: PhantomData,
2018-06-25 04:58:04 +00:00
});
2018-04-13 23:02:01 +00:00
}
2018-01-10 04:00:18 +00:00
};
}
}
2018-04-13 23:02:01 +00:00
fn poll(&mut self, info: &mut ComposeInfo<S>) -> Option<ComposeState<S>> {
2018-06-21 17:06:23 +00:00
let len = info.mws.len();
2018-01-10 04:00:18 +00:00
loop {
// poll latest fut
let mut resp = match self.fut.as_mut().unwrap().poll() {
2018-04-13 23:02:01 +00:00
Ok(Async::NotReady) => return None,
2018-01-10 04:00:18 +00:00
Ok(Async::Ready(resp)) => {
self.curr += 1;
resp
}
Err(err) => return Some(FinishingMiddlewares::init(info, err.into())),
2018-01-10 04:00:18 +00:00
};
loop {
if self.curr == len {
return Some(FinishingMiddlewares::init(info, resp));
2018-01-10 04:00:18 +00:00
} else {
2018-06-25 04:58:04 +00:00
let state = info.mws[self.curr].response(&info.req, resp);
match state {
Err(err) => {
return Some(FinishingMiddlewares::init(info, err.into()))
}
2018-01-10 06:48:35 +00:00
Ok(MiddlewareResponse::Done(r)) => {
2018-01-10 04:00:18 +00:00
self.curr += 1;
resp = r
2018-04-13 23:02:01 +00:00
}
2018-01-10 06:48:35 +00:00
Ok(MiddlewareResponse::Future(fut)) => {
2018-01-10 04:00:18 +00:00
self.fut = Some(fut);
2018-04-13 23:02:01 +00:00
break;
}
2018-01-10 04:00:18 +00:00
}
}
}
}
}
}
/// Middlewares start executor
struct FinishingMiddlewares<S> {
resp: Option<HttpResponse>,
fut: Option<Box<Future<Item = (), Error = Error>>>,
_s: PhantomData<S>,
}
impl<S: 'static> FinishingMiddlewares<S> {
fn init(info: &mut ComposeInfo<S>, resp: HttpResponse) -> ComposeState<S> {
if info.count == 0 {
Response::init(resp)
} else {
let mut state = FinishingMiddlewares {
resp: Some(resp),
fut: None,
_s: PhantomData,
};
if let Some(st) = state.poll(info) {
st
} else {
ComposeState::Finishing(state)
}
}
}
fn poll(&mut self, info: &mut ComposeInfo<S>) -> Option<ComposeState<S>> {
loop {
// poll latest fut
let not_ready = if let Some(ref mut fut) = self.fut {
match fut.poll() {
Ok(Async::NotReady) => true,
Ok(Async::Ready(())) => false,
Err(err) => {
error!("Middleware finish error: {}", err);
false
}
}
} else {
false
};
if not_ready {
return None;
}
self.fut = None;
if info.count == 0 {
return Some(Response::init(self.resp.take().unwrap()));
}
info.count -= 1;
2018-06-21 17:06:23 +00:00
let state = info.mws[info.count as usize]
2018-06-25 04:58:04 +00:00
.finish(&info.req, self.resp.as_ref().unwrap());
match state {
MiddlewareFinished::Done => {
if info.count == 0 {
return Some(Response::init(self.resp.take().unwrap()));
}
}
MiddlewareFinished::Future(fut) => {
self.fut = Some(fut);
}
}
}
}
}
2018-01-10 04:00:18 +00:00
struct Response<S> {
resp: Option<HttpResponse>,
_s: PhantomData<S>,
}
impl<S: 'static> Response<S> {
fn init(resp: HttpResponse) -> ComposeState<S> {
ComposeState::Completed(Response {
2018-04-13 23:02:01 +00:00
resp: Some(resp),
_s: PhantomData,
})
2017-12-05 00:09:22 +00:00
}
}