mirror of
https://github.com/actix/actix-extras.git
synced 2024-11-28 01:32:57 +01:00
better middleware error handling
This commit is contained in:
parent
1fc64bc83d
commit
f4972150cc
@ -16,7 +16,7 @@ pub enum Started {
|
|||||||
/// handler execution halts.
|
/// handler execution halts.
|
||||||
Response(HttpRequest, HttpResponse),
|
Response(HttpRequest, HttpResponse),
|
||||||
/// Execution completed, runs future to completion.
|
/// Execution completed, runs future to completion.
|
||||||
Future(Box<Future<Item=(HttpRequest, Option<HttpResponse>), Error=(HttpRequest, HttpResponse)>>),
|
Future(Box<Future<Item=(HttpRequest, Option<HttpResponse>), Error=Error>>),
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Middleware execution result
|
/// Middleware execution result
|
||||||
@ -24,7 +24,7 @@ pub enum Response {
|
|||||||
/// New http response got generated
|
/// New http response got generated
|
||||||
Response(HttpResponse),
|
Response(HttpResponse),
|
||||||
/// Result is a future that resolves to a new http response
|
/// Result is a future that resolves to a new http response
|
||||||
Future(Box<Future<Item=HttpResponse, Error=HttpResponse>>),
|
Future(Box<Future<Item=HttpResponse, Error=Error>>),
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Middleware finish result
|
/// Middleware finish result
|
||||||
|
@ -34,12 +34,13 @@ impl Pipeline {
|
|||||||
Pipeline(PipelineState::Task(Box::new((task, req))))
|
Pipeline(PipelineState::Task(Box::new((task, req))))
|
||||||
} else {
|
} else {
|
||||||
match Start::init(mw, req, handler, payload) {
|
match Start::init(mw, req, handler, payload) {
|
||||||
StartResult::Ready(res) => {
|
Ok(StartResult::Ready(res)) =>
|
||||||
Pipeline(PipelineState::Handle(res))
|
Pipeline(PipelineState::Handle(res)),
|
||||||
},
|
Ok(StartResult::NotReady(res)) =>
|
||||||
StartResult::NotReady(res) => {
|
Pipeline(PipelineState::Starting(res)),
|
||||||
Pipeline(PipelineState::Starting(res))
|
Err(err) =>
|
||||||
},
|
Pipeline(PipelineState::Error(
|
||||||
|
Box::new((Task::reply(err), HttpRequest::for_error()))))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -70,12 +71,15 @@ impl Pipeline {
|
|||||||
}
|
}
|
||||||
PipelineState::Starting(mut st) => {
|
PipelineState::Starting(mut st) => {
|
||||||
match st.poll() {
|
match st.poll() {
|
||||||
Async::NotReady => {
|
Ok(Async::NotReady) => {
|
||||||
self.0 = PipelineState::Starting(st);
|
self.0 = PipelineState::Starting(st);
|
||||||
return Ok(Async::NotReady)
|
return Ok(Async::NotReady)
|
||||||
}
|
}
|
||||||
Async::Ready(h) =>
|
Ok(Async::Ready(h)) =>
|
||||||
self.0 = PipelineState::Handle(h),
|
self.0 = PipelineState::Handle(h),
|
||||||
|
Err(err) =>
|
||||||
|
self.0 = PipelineState::Error(
|
||||||
|
Box::new((Task::reply(err), HttpRequest::for_error())))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
PipelineState::Handle(mut st) => {
|
PipelineState::Handle(mut st) => {
|
||||||
@ -222,7 +226,7 @@ impl Finish {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type Fut = Box<Future<Item=(HttpRequest, Option<HttpResponse>), Error=(HttpRequest, HttpResponse)>>;
|
type Fut = Box<Future<Item=(HttpRequest, Option<HttpResponse>), Error=Error>>;
|
||||||
|
|
||||||
/// Middlewares start executor
|
/// Middlewares start executor
|
||||||
struct Start {
|
struct Start {
|
||||||
@ -242,8 +246,9 @@ enum StartResult {
|
|||||||
impl Start {
|
impl Start {
|
||||||
|
|
||||||
fn init(mw: Rc<Vec<Box<Middleware>>>,
|
fn init(mw: Rc<Vec<Box<Middleware>>>,
|
||||||
req: HttpRequest, handler: PipelineHandler, payload: Payload) -> StartResult
|
req: HttpRequest,
|
||||||
{
|
handler: PipelineHandler,
|
||||||
|
payload: Payload) -> Result<StartResult, Error> {
|
||||||
Start {
|
Start {
|
||||||
idx: 0,
|
idx: 0,
|
||||||
fut: None,
|
fut: None,
|
||||||
@ -266,13 +271,13 @@ impl Start {
|
|||||||
task
|
task
|
||||||
}
|
}
|
||||||
|
|
||||||
fn start(mut self, mut req: HttpRequest) -> StartResult {
|
fn start(mut self, mut req: HttpRequest) -> Result<StartResult, Error> {
|
||||||
loop {
|
loop {
|
||||||
if self.idx >= self.middlewares.len() {
|
if self.idx >= self.middlewares.len() {
|
||||||
let task = (unsafe{&*self.hnd})(
|
let task = (unsafe{&*self.hnd})(
|
||||||
&mut req, self.payload.take().expect("Something is completlywrong"));
|
&mut req, self.payload.take().expect("Something is completlywrong"));
|
||||||
return StartResult::Ready(
|
return Ok(StartResult::Ready(
|
||||||
Box::new(Handle::new(self.idx-1, req, self.prepare(task), self.middlewares)))
|
Box::new(Handle::new(self.idx-1, req, self.prepare(task), self.middlewares))))
|
||||||
} else {
|
} else {
|
||||||
req = match self.middlewares[self.idx].start(req) {
|
req = match self.middlewares[self.idx].start(req) {
|
||||||
Started::Done(req) => {
|
Started::Done(req) => {
|
||||||
@ -280,31 +285,27 @@ impl Start {
|
|||||||
req
|
req
|
||||||
}
|
}
|
||||||
Started::Response(req, resp) => {
|
Started::Response(req, resp) => {
|
||||||
return StartResult::Ready(
|
return Ok(StartResult::Ready(
|
||||||
Box::new(Handle::new(
|
Box::new(Handle::new(
|
||||||
self.idx, req, self.prepare(Task::reply(resp)), self.middlewares)))
|
self.idx, req, self.prepare(Task::reply(resp)), self.middlewares))))
|
||||||
},
|
},
|
||||||
Started::Future(mut fut) => {
|
Started::Future(mut fut) => {
|
||||||
match fut.poll() {
|
match fut.poll() {
|
||||||
Ok(Async::NotReady) => {
|
Ok(Async::NotReady) => {
|
||||||
self.fut = Some(fut);
|
self.fut = Some(fut);
|
||||||
return StartResult::NotReady(self)
|
return Ok(StartResult::NotReady(self))
|
||||||
}
|
}
|
||||||
Ok(Async::Ready((req, resp))) => {
|
Ok(Async::Ready((req, resp))) => {
|
||||||
self.idx += 1;
|
self.idx += 1;
|
||||||
if let Some(resp) = resp {
|
if let Some(resp) = resp {
|
||||||
return StartResult::Ready(
|
return Ok(StartResult::Ready(
|
||||||
Box::new(Handle::new(
|
Box::new(Handle::new(
|
||||||
self.idx, req,
|
self.idx, req,
|
||||||
self.prepare(Task::reply(resp)), self.middlewares)))
|
self.prepare(Task::reply(resp)), self.middlewares))))
|
||||||
}
|
}
|
||||||
req
|
req
|
||||||
}
|
}
|
||||||
Err((req, resp)) => {
|
Err(err) => return Err(err)
|
||||||
return StartResult::Ready(Box::new(Handle::new(
|
|
||||||
self.idx, req,
|
|
||||||
self.prepare(Task::reply(resp)), self.middlewares)))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@ -312,23 +313,23 @@ impl Start {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn poll(&mut self) -> Async<Box<Handle>> {
|
fn poll(&mut self) -> Poll<Box<Handle>, Error> {
|
||||||
'outer: loop {
|
'outer: loop {
|
||||||
match self.fut.as_mut().unwrap().poll() {
|
match self.fut.as_mut().unwrap().poll() {
|
||||||
Ok(Async::NotReady) => return Async::NotReady,
|
Ok(Async::NotReady) => return Ok(Async::NotReady),
|
||||||
Ok(Async::Ready((mut req, resp))) => {
|
Ok(Async::Ready((mut req, resp))) => {
|
||||||
self.idx += 1;
|
self.idx += 1;
|
||||||
if let Some(resp) = resp {
|
if let Some(resp) = resp {
|
||||||
return Async::Ready(Box::new(Handle::new(
|
return Ok(Async::Ready(Box::new(Handle::new(
|
||||||
self.idx, req,
|
self.idx, req,
|
||||||
self.prepare(Task::reply(resp)), Rc::clone(&self.middlewares))))
|
self.prepare(Task::reply(resp)), Rc::clone(&self.middlewares)))))
|
||||||
}
|
}
|
||||||
if self.idx >= self.middlewares.len() {
|
if self.idx >= self.middlewares.len() {
|
||||||
let task = (unsafe{&*self.hnd})(
|
let task = (unsafe{&*self.hnd})(
|
||||||
&mut req, self.payload.take().expect("Something is completlywrong"));
|
&mut req, self.payload.take().expect("Something is completlywrong"));
|
||||||
return Async::Ready(Box::new(Handle::new(
|
return Ok(Async::Ready(Box::new(Handle::new(
|
||||||
self.idx-1, req,
|
self.idx-1, req,
|
||||||
self.prepare(task), Rc::clone(&self.middlewares))))
|
self.prepare(task), Rc::clone(&self.middlewares)))))
|
||||||
} else {
|
} else {
|
||||||
loop {
|
loop {
|
||||||
req = match self.middlewares[self.idx].start(req) {
|
req = match self.middlewares[self.idx].start(req) {
|
||||||
@ -337,10 +338,10 @@ impl Start {
|
|||||||
req
|
req
|
||||||
}
|
}
|
||||||
Started::Response(req, resp) => {
|
Started::Response(req, resp) => {
|
||||||
return Async::Ready(Box::new(Handle::new(
|
return Ok(Async::Ready(Box::new(Handle::new(
|
||||||
self.idx, req,
|
self.idx, req,
|
||||||
self.prepare(Task::reply(resp)),
|
self.prepare(Task::reply(resp)),
|
||||||
Rc::clone(&self.middlewares))))
|
Rc::clone(&self.middlewares)))))
|
||||||
},
|
},
|
||||||
Started::Future(mut fut) => {
|
Started::Future(mut fut) => {
|
||||||
self.fut = Some(fut);
|
self.fut = Some(fut);
|
||||||
@ -350,18 +351,12 @@ impl Start {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err((req, resp)) => {
|
Err(err) => return Err(err)
|
||||||
return Async::Ready(Box::new(Handle::new(
|
|
||||||
self.idx, req,
|
|
||||||
self.prepare(Task::reply(resp)),
|
|
||||||
Rc::clone(&self.middlewares))))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// Middlewares response executor
|
/// Middlewares response executor
|
||||||
pub(crate) struct MiddlewaresResponse {
|
pub(crate) struct MiddlewaresResponse {
|
||||||
idx: usize,
|
idx: usize,
|
||||||
|
Loading…
Reference in New Issue
Block a user