1
0
mirror of https://github.com/actix/actix-extras.git synced 2024-11-25 00:12:59 +01:00
actix-extras/src/pipeline.rs

860 lines
29 KiB
Rust
Raw Normal View History

2017-12-09 14:54:04 +01:00
use std::marker::PhantomData;
2018-04-14 01:02:01 +02:00
use std::rc::Rc;
use std::{io, mem};
2017-11-25 07:15:52 +01:00
use futures::sync::oneshot;
2018-04-14 01:02:01 +02:00
use futures::{Async, Future, Poll, Stream};
use log::Level::Debug;
2017-11-25 07:15:52 +01:00
2018-04-14 01:02:01 +02:00
use application::Inner;
2017-12-02 00:45:15 +01:00
use body::{Body, BodyStream};
2018-04-14 01:02:01 +02:00
use context::{ActorHttpContext, Frame};
2018-01-01 02:26:32 +01:00
use error::Error;
2018-05-04 01:22:08 +02:00
use handler::{AsyncResult, AsyncResultItem};
2018-04-14 01:02:01 +02:00
use header::ContentEncoding;
2017-11-25 07:15:52 +01:00
use httprequest::HttpRequest;
2018-06-25 06:10:02 +02:00
use httpresponse::HttpResponse;
2018-04-14 01:02:01 +02:00
use middleware::{Finished, Middleware, Response, Started};
use server::{HttpHandlerTask, Writer, WriterState};
2017-11-25 07:15:52 +01:00
2018-06-18 01:45:54 +02:00
#[doc(hidden)]
#[derive(Debug, Clone, Copy)]
2018-06-18 01:45:54 +02:00
pub enum HandlerType {
Normal(usize),
Handler(usize),
Default,
}
2018-06-18 01:45:54 +02:00
#[doc(hidden)]
pub trait PipelineHandler<S> {
fn encoding(&self) -> ContentEncoding;
2018-05-04 01:22:08 +02:00
fn handle(
2018-06-21 19:06:23 +02:00
&self, req: HttpRequest<S>, htype: HandlerType,
2018-05-04 01:22:08 +02:00
) -> AsyncResult<HttpResponse>;
2017-12-29 10:01:31 +01:00
}
2017-11-25 07:15:52 +01:00
2018-06-18 01:45:54 +02:00
#[doc(hidden)]
2018-06-21 19:51:25 +02:00
pub struct Pipeline<S, H>(
PipelineInfo<S>,
PipelineState<S, H>,
Rc<Vec<Box<Middleware<S>>>>,
);
2017-11-25 07:15:52 +01:00
2017-12-29 10:01:31 +01:00
enum PipelineState<S, H> {
2017-11-25 07:15:52 +01:00
None,
2017-12-02 00:45:15 +01:00
Error,
2017-12-29 10:01:31 +01:00
Starting(StartMiddlewares<S, H>),
Handler(WaitingResponse<S, H>),
RunMiddlewares(RunMiddlewares<S, H>),
Response(ProcessResponse<S, H>),
Finishing(FinishingMiddlewares<S, H>),
Completed(Completed<S, H>),
2017-11-25 07:15:52 +01:00
}
2018-01-11 01:45:57 +01:00
impl<S: 'static, H: PipelineHandler<S>> PipelineState<S, H> {
fn is_response(&self) -> bool {
match *self {
PipelineState::Response(_) => true,
_ => false,
}
}
2018-06-21 19:51:25 +02:00
fn poll(
&mut self, info: &mut PipelineInfo<S>, mws: &[Box<Middleware<S>>],
) -> Option<PipelineState<S, H>> {
2018-01-11 01:45:57 +01:00
match *self {
2018-06-21 19:51:25 +02:00
PipelineState::Starting(ref mut state) => state.poll(info, mws),
PipelineState::Handler(ref mut state) => state.poll(info, mws),
PipelineState::RunMiddlewares(ref mut state) => state.poll(info, mws),
PipelineState::Finishing(ref mut state) => state.poll(info, mws),
2018-01-11 01:45:57 +01:00
PipelineState::Completed(ref mut state) => state.poll(info),
2018-04-14 01:02:01 +02:00
PipelineState::Response(_) | PipelineState::None | PipelineState::Error => {
None
}
2018-01-11 01:45:57 +01:00
}
}
2018-04-14 01:02:01 +02:00
}
2018-01-11 01:45:57 +01:00
2017-12-09 13:33:40 +01:00
struct PipelineInfo<S> {
2018-06-21 19:51:25 +02:00
req: HttpRequest<S>,
2018-01-21 05:12:24 +01:00
count: u16,
2018-01-01 02:26:32 +01:00
context: Option<Box<ActorHttpContext>>,
2017-12-02 00:45:15 +01:00
error: Option<Error>,
disconnected: Option<bool>,
encoding: ContentEncoding,
2017-12-02 00:45:15 +01:00
}
2017-12-09 13:33:40 +01:00
impl<S> PipelineInfo<S> {
fn new(req: HttpRequest<S>) -> PipelineInfo<S> {
2017-12-02 00:45:15 +01:00
PipelineInfo {
2018-06-21 19:51:25 +02:00
req,
2017-12-02 00:45:15 +01:00
count: 0,
error: None,
context: None,
disconnected: None,
encoding: ContentEncoding::Auto,
2017-12-02 00:45:15 +01:00
}
}
fn poll_context(&mut self) -> Poll<(), Error> {
if let Some(ref mut context) = self.context {
match context.poll() {
Err(err) => Err(err),
Ok(Async::NotReady) => Ok(Async::NotReady),
Ok(Async::Ready(_)) => Ok(Async::Ready(())),
2017-11-25 07:15:52 +01:00
}
2017-12-02 00:45:15 +01:00
} else {
Ok(Async::Ready(()))
2017-11-25 07:15:52 +01:00
}
}
2017-12-02 00:45:15 +01:00
}
2017-11-25 07:15:52 +01:00
2018-01-10 05:00:18 +01:00
impl<S: 'static, H: PipelineHandler<S>> Pipeline<S, H> {
2018-04-14 01:02:01 +02:00
pub fn new(
2018-06-21 19:06:23 +02:00
req: HttpRequest<S>, mws: Rc<Vec<Box<Middleware<S>>>>, handler: Rc<H>,
htype: HandlerType,
2018-04-14 01:02:01 +02:00
) -> Pipeline<S, H> {
2017-12-09 14:54:04 +01:00
let mut info = PipelineInfo {
2018-06-21 19:51:25 +02:00
req,
2017-12-09 14:54:04 +01:00
count: 0,
error: None,
context: None,
disconnected: None,
2018-06-21 19:06:23 +02:00
encoding: handler.encoding(),
2017-12-09 14:54:04 +01:00
};
2018-06-21 19:51:25 +02:00
let state = StartMiddlewares::init(&mut info, &mws, handler, htype);
2017-12-09 14:54:04 +01:00
2018-06-21 19:51:25 +02:00
Pipeline(info, state, mws)
2017-12-02 00:45:15 +01:00
}
2017-12-09 13:33:40 +01:00
}
2017-12-02 00:45:15 +01:00
2017-12-29 10:01:31 +01:00
impl Pipeline<(), Inner<()>> {
2017-12-09 13:33:40 +01:00
pub fn error<R: Into<HttpResponse>>(err: R) -> Box<HttpHandlerTask> {
2017-12-29 10:01:31 +01:00
Box::new(Pipeline::<(), Inner<()>>(
2018-04-14 01:02:01 +02:00
PipelineInfo::new(HttpRequest::default()),
ProcessResponse::init(err.into()),
2018-06-21 19:51:25 +02:00
Rc::new(Vec::new()),
2018-04-14 01:02:01 +02:00
))
2017-12-09 14:54:04 +01:00
}
}
2018-01-10 05:00:18 +01:00
impl<S: 'static, H> Pipeline<S, H> {
2018-05-16 01:41:46 +02:00
#[inline]
2017-12-09 14:54:04 +01:00
fn is_done(&self) -> bool {
match self.1 {
2018-04-14 01:02:01 +02:00
PipelineState::None
| PipelineState::Error
| PipelineState::Starting(_)
| PipelineState::Handler(_)
| PipelineState::RunMiddlewares(_)
| PipelineState::Response(_) => true,
2018-01-11 01:45:57 +01:00
PipelineState::Finishing(_) | PipelineState::Completed(_) => false,
2017-12-09 14:54:04 +01:00
}
2017-12-02 00:45:15 +01:00
}
2017-12-09 13:33:40 +01:00
}
2018-01-10 05:00:18 +01:00
impl<S: 'static, H: PipelineHandler<S>> HttpHandlerTask for Pipeline<S, H> {
2017-12-09 13:33:40 +01:00
fn disconnected(&mut self) {
self.0.disconnected = Some(true);
2017-12-02 00:45:15 +01:00
}
2017-11-25 07:15:52 +01:00
2017-12-09 13:33:40 +01:00
fn poll_io(&mut self, io: &mut Writer) -> Poll<bool, Error> {
2018-06-19 21:27:41 +02:00
let mut state = mem::replace(&mut self.1, PipelineState::None);
2018-01-11 01:45:57 +01:00
2017-11-25 07:15:52 +01:00
loop {
2018-06-19 21:27:41 +02:00
if state.is_response() {
2018-01-11 01:45:57 +01:00
if let PipelineState::Response(st) = state {
2018-06-21 19:51:25 +02:00
match st.poll_io(io, &mut self.0, &self.2) {
2017-12-02 00:45:15 +01:00
Ok(state) => {
2017-12-09 14:54:04 +01:00
self.1 = state;
if let Some(error) = self.0.error.take() {
2018-04-14 01:02:01 +02:00
return Err(error);
2017-12-02 00:45:15 +01:00
} else {
2018-04-14 01:02:01 +02:00
return Ok(Async::Ready(self.is_done()));
2017-12-02 00:45:15 +01:00
}
}
Err(state) => {
2017-12-09 14:54:04 +01:00
self.1 = state;
2018-01-11 01:45:57 +01:00
return Ok(Async::NotReady);
2017-12-02 00:45:15 +01:00
}
}
2017-11-25 07:15:52 +01:00
}
}
2018-06-19 21:27:41 +02:00
match state {
2018-04-14 01:02:01 +02:00
PipelineState::None => return Ok(Async::Ready(true)),
PipelineState::Error => {
2018-05-16 01:41:46 +02:00
return Err(
io::Error::new(io::ErrorKind::Other, "Internal error").into()
)
2018-04-14 01:02:01 +02:00
}
2018-01-11 01:45:57 +01:00
_ => (),
}
2018-06-21 19:51:25 +02:00
match state.poll(&mut self.0, &self.2) {
2018-06-19 21:27:41 +02:00
Some(st) => state = st,
None => {
return {
self.1 = state;
Ok(Async::NotReady)
}
}
2018-01-11 01:45:57 +01:00
}
2017-11-25 07:15:52 +01:00
}
}
2018-06-18 01:45:54 +02:00
fn poll_completed(&mut self) -> Poll<(), Error> {
2018-06-19 21:27:41 +02:00
let mut state = mem::replace(&mut self.1, PipelineState::None);
2017-11-25 07:15:52 +01:00
loop {
2018-06-19 21:27:41 +02:00
match state {
2017-12-02 00:45:15 +01:00
PipelineState::None | PipelineState::Error => {
return Ok(Async::Ready(()))
}
2018-01-11 01:45:57 +01:00
_ => (),
}
2018-06-21 19:51:25 +02:00
if let Some(st) = state.poll(&mut self.0, &self.2) {
2018-06-19 21:27:41 +02:00
state = st;
2018-01-11 01:45:57 +01:00
} else {
2018-06-19 21:27:41 +02:00
self.1 = state;
2018-01-11 01:45:57 +01:00
return Ok(Async::NotReady);
2017-11-25 07:15:52 +01:00
}
}
}
}
2018-04-14 01:02:01 +02:00
type Fut = Box<Future<Item = Option<HttpResponse>, Error = Error>>;
2017-11-25 07:15:52 +01:00
/// Middlewares start executor
2017-12-29 10:01:31 +01:00
struct StartMiddlewares<S, H> {
2018-06-21 19:06:23 +02:00
hnd: Rc<H>,
htype: HandlerType,
2017-11-25 07:15:52 +01:00
fut: Option<Fut>,
2017-12-29 10:01:31 +01:00
_s: PhantomData<S>,
2017-11-25 07:15:52 +01:00
}
2018-01-10 05:00:18 +01:00
impl<S: 'static, H: PipelineHandler<S>> StartMiddlewares<S, H> {
2018-04-14 01:02:01 +02:00
fn init(
2018-06-21 19:51:25 +02:00
info: &mut PipelineInfo<S>, mws: &[Box<Middleware<S>>], hnd: Rc<H>,
htype: HandlerType,
2018-04-14 01:02:01 +02:00
) -> PipelineState<S, H> {
// execute middlewares, we need this stage because middlewares could be
// non-async and we can move to next state immediately
2018-06-21 19:51:25 +02:00
let len = mws.len() as u16;
2017-11-25 07:15:52 +01:00
loop {
2017-12-02 00:45:15 +01:00
if info.count == len {
2018-06-21 19:51:25 +02:00
let reply = hnd.handle(info.req.clone(), htype);
return WaitingResponse::init(info, mws, reply);
2017-11-25 07:15:52 +01:00
} else {
2018-06-21 19:51:25 +02:00
let state = mws[info.count as usize].start(&mut info.req);
match state {
2018-04-14 01:02:01 +02:00
Ok(Started::Done) => info.count += 1,
Ok(Started::Response(resp)) => {
2018-06-21 19:51:25 +02:00
return RunMiddlewares::init(info, mws, resp)
2018-04-14 01:02:01 +02:00
}
2018-05-08 01:09:41 +02:00
Ok(Started::Future(fut)) => {
return PipelineState::Starting(StartMiddlewares {
hnd,
htype,
fut: Some(fut),
_s: PhantomData,
})
}
2018-06-21 19:51:25 +02:00
Err(err) => return RunMiddlewares::init(info, mws, err.into()),
2017-11-25 07:15:52 +01:00
}
}
}
}
2018-06-21 19:51:25 +02:00
fn poll(
&mut self, info: &mut PipelineInfo<S>, mws: &[Box<Middleware<S>>],
) -> Option<PipelineState<S, H>> {
let len = mws.len() as u16;
2017-11-25 07:15:52 +01:00
'outer: loop {
match self.fut.as_mut().unwrap().poll() {
2018-01-11 01:45:57 +01:00
Ok(Async::NotReady) => return None,
2017-11-27 06:47:33 +01:00
Ok(Async::Ready(resp)) => {
2017-12-09 14:54:04 +01:00
info.count += 1;
2017-11-25 07:15:52 +01:00
if let Some(resp) = resp {
2018-06-21 19:51:25 +02:00
return Some(RunMiddlewares::init(info, mws, resp));
2017-11-25 07:15:52 +01:00
}
loop {
if info.count == len {
2018-06-21 19:51:25 +02:00
let reply = self.hnd.handle(info.req.clone(), self.htype);
return Some(WaitingResponse::init(info, mws, reply));
} else {
2018-06-21 19:51:25 +02:00
let state = mws[info.count as usize].start(&mut info.req);
match state {
2018-04-14 01:02:01 +02:00
Ok(Started::Done) => info.count += 1,
2018-01-10 07:48:35 +01:00
Ok(Started::Response(resp)) => {
2018-06-21 19:51:25 +02:00
return Some(RunMiddlewares::init(info, mws, resp));
2018-04-14 01:02:01 +02:00
}
2018-01-10 07:48:35 +01:00
Ok(Started::Future(fut)) => {
2017-11-25 07:15:52 +01:00
self.fut = Some(fut);
2018-04-14 01:02:01 +02:00
continue 'outer;
}
Err(err) => {
2018-06-21 19:51:25 +02:00
return Some(RunMiddlewares::init(
info,
mws,
err.into(),
))
2018-04-14 01:02:01 +02:00
}
2017-11-25 07:15:52 +01:00
}
}
}
}
2018-06-21 19:51:25 +02:00
Err(err) => return Some(RunMiddlewares::init(info, mws, err.into())),
2017-11-25 07:15:52 +01:00
}
}
}
}
2017-12-02 00:45:15 +01:00
// waiting for response
2017-12-29 10:01:31 +01:00
struct WaitingResponse<S, H> {
2018-04-14 01:02:01 +02:00
fut: Box<Future<Item = HttpResponse, Error = Error>>,
2017-12-09 14:54:04 +01:00
_s: PhantomData<S>,
2017-12-29 10:01:31 +01:00
_h: PhantomData<H>,
2017-11-25 21:05:27 +01:00
}
2018-01-10 05:00:18 +01:00
impl<S: 'static, H> WaitingResponse<S, H> {
2017-12-16 05:00:12 +01:00
#[inline]
2018-05-02 02:19:15 +02:00
fn init(
2018-06-21 19:51:25 +02:00
info: &mut PipelineInfo<S>, mws: &[Box<Middleware<S>>],
reply: AsyncResult<HttpResponse>,
2018-05-02 02:19:15 +02:00
) -> PipelineState<S, H> {
2017-12-16 05:00:12 +01:00
match reply.into() {
2018-06-21 19:51:25 +02:00
AsyncResultItem::Err(err) => RunMiddlewares::init(info, mws, err.into()),
AsyncResultItem::Ok(resp) => RunMiddlewares::init(info, mws, resp),
2018-05-04 01:22:08 +02:00
AsyncResultItem::Future(fut) => PipelineState::Handler(WaitingResponse {
2018-04-14 01:02:01 +02:00
fut,
_s: PhantomData,
_h: PhantomData,
}),
2017-12-16 05:00:12 +01:00
}
2017-11-25 21:05:27 +01:00
}
2018-06-21 19:51:25 +02:00
fn poll(
&mut self, info: &mut PipelineInfo<S>, mws: &[Box<Middleware<S>>],
) -> Option<PipelineState<S, H>> {
2018-01-01 02:26:32 +01:00
match self.fut.poll() {
2018-01-11 01:45:57 +01:00
Ok(Async::NotReady) => None,
2018-06-21 19:51:25 +02:00
Ok(Async::Ready(response)) => {
Some(RunMiddlewares::init(info, mws, response))
}
Err(err) => Some(RunMiddlewares::init(info, mws, err.into())),
2017-11-25 21:05:27 +01:00
}
}
}
2017-11-25 07:15:52 +01:00
/// Middlewares response executor
2017-12-29 10:01:31 +01:00
struct RunMiddlewares<S, H> {
2017-12-02 00:45:15 +01:00
curr: usize,
2018-04-14 01:02:01 +02:00
fut: Option<Box<Future<Item = HttpResponse, Error = Error>>>,
2017-12-09 14:54:04 +01:00
_s: PhantomData<S>,
2017-12-29 10:01:31 +01:00
_h: PhantomData<H>,
2017-11-25 07:15:52 +01:00
}
2018-01-10 05:00:18 +01:00
impl<S: 'static, H> RunMiddlewares<S, H> {
2018-05-16 01:41:46 +02:00
#[inline]
2018-06-21 19:51:25 +02:00
fn init(
info: &mut PipelineInfo<S>, mws: &[Box<Middleware<S>>], mut resp: HttpResponse,
) -> PipelineState<S, H> {
2017-12-02 00:45:15 +01:00
if info.count == 0 {
2017-12-09 14:54:04 +01:00
return ProcessResponse::init(resp);
2017-12-02 00:45:15 +01:00
}
let mut curr = 0;
2018-06-21 19:51:25 +02:00
let len = mws.len();
2017-12-02 00:45:15 +01:00
2017-11-25 07:15:52 +01:00
loop {
2018-06-21 19:51:25 +02:00
let state = mws[curr].response(&mut info.req, resp);
resp = match state {
2018-01-10 07:48:35 +01:00
Err(err) => {
2018-01-21 05:12:24 +01:00
info.count = (curr + 1) as u16;
2018-04-14 01:02:01 +02:00
return ProcessResponse::init(err.into());
2017-12-02 00:45:15 +01:00
}
2018-01-10 07:48:35 +01:00
Ok(Response::Done(r)) => {
2017-12-02 00:45:15 +01:00
curr += 1;
if curr == len {
2018-04-14 01:02:01 +02:00
return ProcessResponse::init(r);
2017-11-25 07:15:52 +01:00
} else {
r
}
2018-04-14 01:02:01 +02:00
}
2018-01-10 07:48:35 +01:00
Ok(Response::Future(fut)) => {
2018-04-14 01:02:01 +02:00
return PipelineState::RunMiddlewares(RunMiddlewares {
curr,
fut: Some(fut),
_s: PhantomData,
_h: PhantomData,
})
}
2017-11-25 07:15:52 +01:00
};
}
}
2018-06-21 19:51:25 +02:00
fn poll(
&mut self, info: &mut PipelineInfo<S>, mws: &[Box<Middleware<S>>],
) -> Option<PipelineState<S, H>> {
let len = mws.len();
2017-12-02 00:45:15 +01:00
2017-11-25 07:15:52 +01:00
loop {
// poll latest fut
let mut resp = match self.fut.as_mut().unwrap().poll() {
2018-04-14 01:02:01 +02:00
Ok(Async::NotReady) => return None,
2017-11-25 18:28:25 +01:00
Ok(Async::Ready(resp)) => {
2017-12-02 00:45:15 +01:00
self.curr += 1;
2017-12-16 01:24:15 +01:00
resp
2017-11-25 07:15:52 +01:00
}
2018-04-14 01:02:01 +02:00
Err(err) => return Some(ProcessResponse::init(err.into())),
2017-11-25 07:15:52 +01:00
};
loop {
2017-12-02 00:45:15 +01:00
if self.curr == len {
2018-01-11 01:45:57 +01:00
return Some(ProcessResponse::init(resp));
2017-11-25 07:15:52 +01:00
} else {
2018-06-21 19:51:25 +02:00
let state = mws[self.curr].response(&mut info.req, resp);
match state {
2018-04-14 01:02:01 +02:00
Err(err) => return Some(ProcessResponse::init(err.into())),
2018-01-10 07:48:35 +01:00
Ok(Response::Done(r)) => {
2017-12-02 00:45:15 +01:00
self.curr += 1;
2017-11-25 07:15:52 +01:00
resp = r
2018-04-14 01:02:01 +02:00
}
2018-01-10 07:48:35 +01:00
Ok(Response::Future(fut)) => {
2017-11-25 07:15:52 +01:00
self.fut = Some(fut);
2018-04-14 01:02:01 +02:00
break;
}
2017-11-25 07:15:52 +01:00
}
}
}
}
}
}
2017-12-02 00:45:15 +01:00
2017-12-29 10:01:31 +01:00
struct ProcessResponse<S, H> {
2017-12-16 01:24:15 +01:00
resp: HttpResponse,
2017-12-02 00:45:15 +01:00
iostate: IOState,
running: RunningState,
2017-12-24 20:58:09 +01:00
drain: Option<oneshot::Sender<()>>,
2017-12-09 14:54:04 +01:00
_s: PhantomData<S>,
2017-12-29 10:01:31 +01:00
_h: PhantomData<H>,
2017-12-02 00:45:15 +01:00
}
#[derive(PartialEq)]
enum RunningState {
Running,
Paused,
Done,
}
impl RunningState {
#[inline]
fn pause(&mut self) {
if *self != RunningState::Done {
*self = RunningState::Paused
}
}
#[inline]
fn resume(&mut self) {
if *self != RunningState::Done {
*self = RunningState::Running
}
}
}
enum IOState {
Response,
Payload(BodyStream),
2018-01-01 02:26:32 +01:00
Actor(Box<ActorHttpContext>),
2017-12-02 00:45:15 +01:00
Done,
}
2018-01-10 05:00:18 +01:00
impl<S: 'static, H> ProcessResponse<S, H> {
2017-12-16 05:00:12 +01:00
#[inline]
2018-01-11 05:08:13 +01:00
fn init(resp: HttpResponse) -> PipelineState<S, H> {
2018-04-14 01:02:01 +02:00
PipelineState::Response(ProcessResponse {
resp,
iostate: IOState::Response,
running: RunningState::Running,
drain: None,
_s: PhantomData,
_h: PhantomData,
})
2017-12-02 00:45:15 +01:00
}
2018-04-14 01:02:01 +02:00
fn poll_io(
2018-05-17 21:20:20 +02:00
mut self, io: &mut Writer, info: &mut PipelineInfo<S>,
2018-06-21 19:51:25 +02:00
mws: &[Box<Middleware<S>>],
2018-04-14 01:02:01 +02:00
) -> Result<PipelineState<S, H>, PipelineState<S, H>> {
loop {
if self.drain.is_none() && self.running != RunningState::Paused {
// if task is paused, write buffer is probably full
'inner: loop {
let result = match mem::replace(&mut self.iostate, IOState::Done) {
IOState::Response => {
2018-04-14 01:02:01 +02:00
let encoding =
self.resp.content_encoding().unwrap_or(info.encoding);
let result = match io.start(
2018-06-21 19:51:25 +02:00
info.req.as_mut(),
2018-04-14 01:02:01 +02:00
&mut self.resp,
encoding,
) {
Ok(res) => res,
Err(err) => {
info.error = Some(err.into());
2018-04-14 01:02:01 +02:00
return Ok(FinishingMiddlewares::init(
2018-06-21 19:51:25 +02:00
info, mws, self.resp,
2018-04-14 01:02:01 +02:00
));
}
};
2017-12-02 00:45:15 +01:00
if let Some(err) = self.resp.error() {
if self.resp.status().is_server_error() {
2018-04-14 01:02:01 +02:00
error!(
2018-05-09 00:44:50 +02:00
"Error occured during request handling, status: {} {}",
self.resp.status(), err
2018-04-14 01:02:01 +02:00
);
} else {
2018-04-14 01:02:01 +02:00
warn!(
"Error occured during request handling: {}",
err
);
}
if log_enabled!(Debug) {
debug!("{:?}", err);
}
2018-01-21 05:12:24 +01:00
}
// always poll stream or actor for the first time
match self.resp.replace_body(Body::Empty) {
Body::Streaming(stream) => {
self.iostate = IOState::Payload(stream);
2018-04-14 01:02:01 +02:00
continue 'inner;
}
Body::Actor(ctx) => {
self.iostate = IOState::Actor(ctx);
continue 'inner;
}
_ => (),
}
2017-12-02 00:45:15 +01:00
result
2018-04-14 01:02:01 +02:00
}
IOState::Payload(mut body) => match body.poll() {
Ok(Async::Ready(None)) => {
if let Err(err) = io.write_eof() {
info.error = Some(err.into());
return Ok(FinishingMiddlewares::init(
2018-06-21 19:51:25 +02:00
info, mws, self.resp,
2018-04-14 01:02:01 +02:00
));
}
break;
}
Ok(Async::Ready(Some(chunk))) => {
self.iostate = IOState::Payload(body);
2018-06-19 03:44:01 +02:00
match io.write(&chunk.into()) {
2018-04-14 01:02:01 +02:00
Err(err) => {
2017-12-09 14:54:04 +01:00
info.error = Some(err.into());
2018-04-14 01:02:01 +02:00
return Ok(FinishingMiddlewares::init(
2018-06-21 19:51:25 +02:00
info, mws, self.resp,
2018-04-14 01:02:01 +02:00
));
}
2018-04-14 01:02:01 +02:00
Ok(result) => result,
2017-12-02 00:45:15 +01:00
}
2018-04-14 01:02:01 +02:00
}
Ok(Async::NotReady) => {
self.iostate = IOState::Payload(body);
break;
}
Err(err) => {
info.error = Some(err);
2018-06-21 19:51:25 +02:00
return Ok(FinishingMiddlewares::init(
info, mws, self.resp,
));
}
},
IOState::Actor(mut ctx) => {
if info.disconnected.take().is_some() {
ctx.disconnected();
}
match ctx.poll() {
Ok(Async::Ready(Some(vec))) => {
if vec.is_empty() {
self.iostate = IOState::Actor(ctx);
2018-04-14 01:02:01 +02:00
break;
}
let mut res = None;
for frame in vec {
match frame {
Frame::Chunk(None) => {
info.context = Some(ctx);
if let Err(err) = io.write_eof() {
info.error = Some(err.into());
return Ok(
2018-04-14 01:02:01 +02:00
FinishingMiddlewares::init(
2018-06-21 19:51:25 +02:00
info, mws, self.resp,
2018-04-14 01:02:01 +02:00
),
);
}
2018-04-14 01:02:01 +02:00
break 'inner;
}
Frame::Chunk(Some(chunk)) => {
2018-06-19 03:44:01 +02:00
match io.write(&chunk) {
Err(err) => {
info.error = Some(err.into());
return Ok(
2018-04-14 01:02:01 +02:00
FinishingMiddlewares::init(
2018-06-21 19:51:25 +02:00
info, mws, self.resp,
2018-04-14 01:02:01 +02:00
),
);
}
Ok(result) => res = Some(result),
}
2018-04-14 01:02:01 +02:00
}
Frame::Drain(fut) => self.drain = Some(fut),
}
}
self.iostate = IOState::Actor(ctx);
if self.drain.is_some() {
self.running.resume();
2018-04-14 01:02:01 +02:00
break 'inner;
2017-12-02 00:45:15 +01:00
}
res.unwrap()
2017-12-02 00:45:15 +01:00
}
2018-04-14 01:02:01 +02:00
Ok(Async::Ready(None)) => break,
Ok(Async::NotReady) => {
self.iostate = IOState::Actor(ctx);
2018-04-14 01:02:01 +02:00
break;
}
Err(err) => {
info.error = Some(err);
2018-04-14 01:02:01 +02:00
return Ok(FinishingMiddlewares::init(
2018-06-21 19:51:25 +02:00
info, mws, self.resp,
2018-04-14 01:02:01 +02:00
));
}
2017-12-02 00:45:15 +01:00
}
}
IOState::Done => break,
};
2017-12-02 00:45:15 +01:00
match result {
WriterState::Pause => {
self.running.pause();
2018-04-14 01:02:01 +02:00
break;
}
2018-04-14 01:02:01 +02:00
WriterState::Done => self.running.resume(),
2017-12-02 00:45:15 +01:00
}
}
}
// flush io but only if we need to
if self.running == RunningState::Paused || self.drain.is_some() {
match io.poll_completed(false) {
Ok(Async::Ready(_)) => {
self.running.resume();
// resolve drain futures
if let Some(tx) = self.drain.take() {
let _ = tx.send(());
}
// restart io processing
2018-04-14 01:02:01 +02:00
continue;
}
Ok(Async::NotReady) => return Err(PipelineState::Response(self)),
Err(err) => {
info.error = Some(err.into());
2018-06-21 19:51:25 +02:00
return Ok(FinishingMiddlewares::init(info, mws, self.resp));
}
2017-12-15 04:34:31 +01:00
}
2017-12-02 00:45:15 +01:00
}
2018-04-14 01:02:01 +02:00
break;
2017-12-02 00:45:15 +01:00
}
// response is completed
2017-12-16 05:00:12 +01:00
match self.iostate {
IOState::Done => {
match io.write_eof() {
Ok(_) => (),
Err(err) => {
info.error = Some(err.into());
2018-06-21 19:51:25 +02:00
return Ok(FinishingMiddlewares::init(info, mws, self.resp));
}
}
2017-12-16 05:00:12 +01:00
self.resp.set_response_size(io.written());
2018-06-21 19:51:25 +02:00
Ok(FinishingMiddlewares::init(info, mws, self.resp))
2017-12-16 05:00:12 +01:00
}
2018-01-11 01:45:57 +01:00
_ => Err(PipelineState::Response(self)),
2017-12-02 00:45:15 +01:00
}
}
}
/// Middlewares start executor
2017-12-29 10:01:31 +01:00
struct FinishingMiddlewares<S, H> {
2018-06-25 05:08:28 +02:00
resp: Option<HttpResponse>,
2018-04-14 01:02:01 +02:00
fut: Option<Box<Future<Item = (), Error = Error>>>,
2017-12-09 14:54:04 +01:00
_s: PhantomData<S>,
2017-12-29 10:01:31 +01:00
_h: PhantomData<H>,
2017-12-02 00:45:15 +01:00
}
2018-01-10 05:00:18 +01:00
impl<S: 'static, H> FinishingMiddlewares<S, H> {
2018-05-16 01:41:46 +02:00
#[inline]
2018-06-21 19:51:25 +02:00
fn init(
info: &mut PipelineInfo<S>, mws: &[Box<Middleware<S>>], resp: HttpResponse,
) -> PipelineState<S, H> {
2017-12-02 00:45:15 +01:00
if info.count == 0 {
2018-06-25 06:10:02 +02:00
resp.release();
Completed::init(info)
2017-12-02 00:45:15 +01:00
} else {
2018-04-14 01:02:01 +02:00
let mut state = FinishingMiddlewares {
2018-06-25 05:08:28 +02:00
resp: Some(resp),
2018-04-14 01:02:01 +02:00
fut: None,
_s: PhantomData,
_h: PhantomData,
};
2018-06-21 19:51:25 +02:00
if let Some(st) = state.poll(info, mws) {
2018-01-11 01:45:57 +01:00
st
} else {
PipelineState::Finishing(state)
2017-12-02 00:45:15 +01:00
}
}
}
2018-06-21 19:51:25 +02:00
fn poll(
&mut self, info: &mut PipelineInfo<S>, mws: &[Box<Middleware<S>>],
) -> Option<PipelineState<S, H>> {
2017-12-02 00:45:15 +01:00
loop {
// poll latest fut
let not_ready = if let Some(ref mut fut) = self.fut {
match fut.poll() {
2018-04-14 01:02:01 +02:00
Ok(Async::NotReady) => true,
Ok(Async::Ready(())) => false,
2017-12-02 00:45:15 +01:00
Err(err) => {
error!("Middleware finish error: {}", err);
false
}
}
} else {
false
};
if not_ready {
2018-01-11 01:45:57 +01:00
return None;
2017-12-02 00:45:15 +01:00
}
self.fut = None;
if info.count == 0 {
2018-06-25 06:10:02 +02:00
self.resp.take().unwrap().release();
return Some(Completed::init(info));
}
2017-12-02 00:45:15 +01:00
info.count -= 1;
2018-06-25 05:08:28 +02:00
let state = mws[info.count as usize]
.finish(&mut info.req, self.resp.as_ref().unwrap());
match state {
2017-12-02 00:45:15 +01:00
Finished::Done => {
2017-12-09 14:54:04 +01:00
if info.count == 0 {
2018-06-25 06:10:02 +02:00
self.resp.take().unwrap().release();
return Some(Completed::init(info));
2017-12-02 00:45:15 +01:00
}
}
Finished::Future(fut) => {
self.fut = Some(fut);
2018-04-14 01:02:01 +02:00
}
2017-12-02 00:45:15 +01:00
}
}
}
}
#[derive(Debug)]
2018-06-25 06:10:02 +02:00
struct Completed<S, H>(PhantomData<S>, PhantomData<H>);
2017-12-02 00:45:15 +01:00
2017-12-29 10:01:31 +01:00
impl<S, H> Completed<S, H> {
2017-12-16 05:00:12 +01:00
#[inline]
2018-06-25 06:10:02 +02:00
fn init(info: &mut PipelineInfo<S>) -> PipelineState<S, H> {
2018-01-21 05:12:24 +01:00
if let Some(ref err) = info.error {
2018-01-31 18:28:53 +01:00
error!("Error occurred during request handling: {}", err);
2018-01-21 05:12:24 +01:00
}
2017-12-02 00:45:15 +01:00
if info.context.is_none() {
PipelineState::None
} else {
2018-06-25 06:10:02 +02:00
PipelineState::Completed(Completed(PhantomData, PhantomData))
2017-12-02 00:45:15 +01:00
}
}
2017-12-16 05:00:12 +01:00
#[inline]
2018-01-11 01:45:57 +01:00
fn poll(&mut self, info: &mut PipelineInfo<S>) -> Option<PipelineState<S, H>> {
2017-12-09 14:54:04 +01:00
match info.poll_context() {
2018-01-11 01:45:57 +01:00
Ok(Async::NotReady) => None,
2018-06-25 06:10:02 +02:00
Ok(Async::Ready(())) => Some(PipelineState::None),
Err(_) => Some(PipelineState::Error),
2017-12-02 00:45:15 +01:00
}
}
}
2017-12-02 01:10:01 +01:00
#[cfg(test)]
mod tests {
use super::*;
use actix::*;
use context::HttpContext;
2017-12-02 04:57:34 +01:00
use futures::future::{lazy, result};
2018-06-25 05:08:28 +02:00
use http::StatusCode;
2018-05-25 06:03:16 +02:00
use tokio::runtime::current_thread::Runtime;
2017-12-02 01:10:01 +01:00
2017-12-29 10:01:31 +01:00
impl<S, H> PipelineState<S, H> {
2017-12-02 01:10:01 +01:00
fn is_none(&self) -> Option<bool> {
2018-04-14 01:02:01 +02:00
if let PipelineState::None = *self {
Some(true)
} else {
None
}
2017-12-02 01:10:01 +01:00
}
2017-12-29 10:01:31 +01:00
fn completed(self) -> Option<Completed<S, H>> {
2018-04-14 01:02:01 +02:00
if let PipelineState::Completed(c) = self {
Some(c)
} else {
None
}
2017-12-02 01:10:01 +01:00
}
}
struct MyActor;
impl Actor for MyActor {
type Context = HttpContext<MyActor>;
}
#[test]
fn test_completed() {
2018-05-25 06:03:16 +02:00
Runtime::new()
2018-04-14 01:02:01 +02:00
.unwrap()
2018-05-25 06:03:16 +02:00
.block_on(lazy(|| {
2018-04-14 01:02:01 +02:00
let mut info = PipelineInfo::new(HttpRequest::default());
2018-06-25 06:10:02 +02:00
Completed::<(), Inner<()>>::init(&mut info)
2018-04-29 18:09:08 +02:00
.is_none()
.unwrap();
2018-04-14 01:02:01 +02:00
let req = HttpRequest::default();
2018-05-29 19:31:37 +02:00
let ctx = HttpContext::new(req.clone(), MyActor);
let addr = ctx.address();
2018-04-14 01:02:01 +02:00
let mut info = PipelineInfo::new(req);
info.context = Some(Box::new(ctx));
2018-06-25 06:10:02 +02:00
let mut state = Completed::<(), Inner<()>>::init(&mut info)
2018-04-29 18:09:08 +02:00
.completed()
.unwrap();
2018-04-14 01:02:01 +02:00
assert!(state.poll(&mut info).is_none());
2018-06-21 19:51:25 +02:00
let pp =
Pipeline(info, PipelineState::Completed(state), Rc::new(Vec::new()));
2018-04-14 01:02:01 +02:00
assert!(!pp.is_done());
2018-06-23 13:59:45 +02:00
let Pipeline(mut info, st, _) = pp;
2018-04-14 01:02:01 +02:00
let mut st = st.completed().unwrap();
drop(addr);
assert!(st.poll(&mut info).unwrap().is_none().unwrap());
result(Ok::<_, ()>(()))
}))
.unwrap();
2017-12-02 01:10:01 +01:00
}
}