1
0
mirror of https://github.com/fafhrd91/actix-web synced 2024-11-24 00:21:08 +01:00

refactor Middleware trait, use Result

This commit is contained in:
Nikolay Kim 2018-01-09 22:48:35 -08:00
parent 16310a5ebd
commit ce78f17a79
9 changed files with 66 additions and 69 deletions

View File

@ -34,19 +34,19 @@ impl<S> Middleware<S> for Headers {
/// Method is called when request is ready. It may return /// Method is called when request is ready. It may return
/// future, which should resolve before next middleware get called. /// future, which should resolve before next middleware get called.
fn start(&self, req: &mut HttpRequest<S>) -> Started { fn start(&self, req: &mut HttpRequest<S>) -> Result<Started> {
req.headers_mut().insert( req.headers_mut().insert(
header::CONTENT_TYPE, header::HeaderValue::from_static("text/plain")); header::CONTENT_TYPE, header::HeaderValue::from_static("text/plain"));
Started::Done Ok(Started::Done)
} }
/// Method is called when handler returns response, /// Method is called when handler returns response,
/// but before sending http message to peer. /// but before sending http message to peer.
fn response(&self, req: &mut HttpRequest<S>, mut resp: HttpResponse) -> Response { fn response(&self, req: &mut HttpRequest<S>, mut resp: HttpResponse) -> Result<Response> {
resp.headers_mut().insert( resp.headers_mut().insert(
header::HeaderName::try_from("X-VERSION").unwrap(), header::HeaderName::try_from("X-VERSION").unwrap(),
header::HeaderValue::from_static("0.2")); header::HeaderValue::from_static("0.2"));
Response::Done(resp) Ok(Response::Done(resp))
} }
} }

View File

@ -5,7 +5,7 @@ use std::collections::HashSet;
use http::{self, Method, HttpTryFrom, Uri}; use http::{self, Method, HttpTryFrom, Uri};
use http::header::{self, HeaderName}; use http::header::{self, HeaderName};
use error::ResponseError; use error::{Result, ResponseError};
use httprequest::HttpRequest; use httprequest::HttpRequest;
use httpresponse::HttpResponse; use httpresponse::HttpResponse;
use middleware::{Middleware, Response, Started}; use middleware::{Middleware, Response, Started};
@ -152,17 +152,16 @@ impl Cors {
impl<S> Middleware<S> for Cors { impl<S> Middleware<S> for Cors {
fn start(&self, req: &mut HttpRequest<S>) -> Started { fn start(&self, req: &mut HttpRequest<S>) -> Result<Started> {
if Method::OPTIONS == *req.method() { if Method::OPTIONS == *req.method() {
if let Err(err) = self.validate_origin(req) { self.validate_origin(req)?;
return Started::Err(err.into()) self.validate_allowed_method(req)?;
}
} }
Started::Done Ok(Started::Done)
} }
fn response(&self, _: &mut HttpRequest<S>, mut resp: HttpResponse) -> Response { fn response(&self, _: &mut HttpRequest<S>, mut resp: HttpResponse) -> Result<Response> {
Response::Done(resp) Ok(Response::Done(resp))
} }
} }

View File

@ -2,6 +2,7 @@
use http::{HeaderMap, HttpTryFrom}; use http::{HeaderMap, HttpTryFrom};
use http::header::{HeaderName, HeaderValue, CONTENT_TYPE}; use http::header::{HeaderName, HeaderValue, CONTENT_TYPE};
use error::Result;
use httprequest::HttpRequest; use httprequest::HttpRequest;
use httpresponse::HttpResponse; use httpresponse::HttpResponse;
use middleware::{Response, Middleware}; use middleware::{Response, Middleware};
@ -40,7 +41,7 @@ impl DefaultHeaders {
impl<S> Middleware<S> for DefaultHeaders { impl<S> Middleware<S> for DefaultHeaders {
fn response(&self, _: &mut HttpRequest<S>, mut resp: HttpResponse) -> Response { fn response(&self, _: &mut HttpRequest<S>, mut resp: HttpResponse) -> Result<Response> {
for (key, value) in self.headers.iter() { for (key, value) in self.headers.iter() {
if !resp.headers().contains_key(key) { if !resp.headers().contains_key(key) {
resp.headers_mut().insert(key, value.clone()); resp.headers_mut().insert(key, value.clone());
@ -51,7 +52,7 @@ impl<S> Middleware<S> for DefaultHeaders {
resp.headers_mut().insert( resp.headers_mut().insert(
CONTENT_TYPE, HeaderValue::from_static("application/octet-stream")); CONTENT_TYPE, HeaderValue::from_static("application/octet-stream"));
} }
Response::Done(resp) Ok(Response::Done(resp))
} }
} }
@ -113,14 +114,14 @@ mod tests {
let resp = HttpResponse::Ok().finish().unwrap(); let resp = HttpResponse::Ok().finish().unwrap();
let resp = match mw.response(&mut req, resp) { let resp = match mw.response(&mut req, resp) {
Response::Done(resp) => resp, Ok(Response::Done(resp)) => resp,
_ => panic!(), _ => panic!(),
}; };
assert_eq!(resp.headers().get(CONTENT_TYPE).unwrap(), "0001"); assert_eq!(resp.headers().get(CONTENT_TYPE).unwrap(), "0001");
let resp = HttpResponse::Ok().header(CONTENT_TYPE, "0002").finish().unwrap(); let resp = HttpResponse::Ok().header(CONTENT_TYPE, "0002").finish().unwrap();
let resp = match mw.response(&mut req, resp) { let resp = match mw.response(&mut req, resp) {
Response::Done(resp) => resp, Ok(Response::Done(resp)) => resp,
_ => panic!(), _ => panic!(),
}; };
assert_eq!(resp.headers().get(CONTENT_TYPE).unwrap(), "0002"); assert_eq!(resp.headers().get(CONTENT_TYPE).unwrap(), "0002");

View File

@ -7,6 +7,7 @@ use libc;
use time; use time;
use regex::Regex; use regex::Regex;
use error::Result;
use httprequest::HttpRequest; use httprequest::HttpRequest;
use httpresponse::HttpResponse; use httpresponse::HttpResponse;
use middleware::{Middleware, Started, Finished}; use middleware::{Middleware, Started, Finished};
@ -101,9 +102,9 @@ impl Logger {
impl<S> Middleware<S> for Logger { impl<S> Middleware<S> for Logger {
fn start(&self, req: &mut HttpRequest<S>) -> Started { fn start(&self, req: &mut HttpRequest<S>) -> Result<Started> {
req.extensions().insert(StartTime(time::now())); req.extensions().insert(StartTime(time::now()));
Started::Done Ok(Started::Done)
} }
fn finish(&self, req: &mut HttpRequest<S>, resp: &HttpResponse) -> Finished { fn finish(&self, req: &mut HttpRequest<S>, resp: &HttpResponse) -> Finished {
@ -305,7 +306,7 @@ mod tests {
.force_close().body(Body::Empty).unwrap(); .force_close().body(Body::Empty).unwrap();
match logger.start(&mut req) { match logger.start(&mut req) {
Started::Done => (), Ok(Started::Done) => (),
_ => panic!(), _ => panic!(),
}; };
match logger.finish(&mut req, &resp) { match logger.finish(&mut req, &resp) {

View File

@ -1,7 +1,7 @@
//! Middlewares //! Middlewares
use futures::Future; use futures::Future;
use error::Error; use error::{Error, Result};
use httprequest::HttpRequest; use httprequest::HttpRequest;
use httpresponse::HttpResponse; use httpresponse::HttpResponse;
@ -18,8 +18,6 @@ pub use self::session::{RequestSession, Session, SessionImpl, SessionBackend, Se
pub enum Started { pub enum Started {
/// Execution completed /// Execution completed
Done, Done,
/// Moddleware error
Err(Error),
/// New http response got generated. If middleware generates response /// New http response got generated. If middleware generates response
/// handler execution halts. /// handler execution halts.
Response(HttpResponse), Response(HttpResponse),
@ -29,8 +27,6 @@ pub enum Started {
/// Middleware execution result /// Middleware execution result
pub enum Response { pub enum Response {
/// Moddleware error
Err(Error),
/// New http response got generated /// New http response got generated
Done(HttpResponse), Done(HttpResponse),
/// Result is a future that resolves to a new http response /// Result is a future that resolves to a new http response
@ -51,14 +47,14 @@ pub trait Middleware<S>: 'static {
/// Method is called when request is ready. It may return /// Method is called when request is ready. It may return
/// future, which should resolve before next middleware get called. /// future, which should resolve before next middleware get called.
fn start(&self, req: &mut HttpRequest<S>) -> Started { fn start(&self, req: &mut HttpRequest<S>) -> Result<Started> {
Started::Done Ok(Started::Done)
} }
/// Method is called when handler returns response, /// Method is called when handler returns response,
/// but before sending http message to peer. /// but before sending http message to peer.
fn response(&self, req: &mut HttpRequest<S>, resp: HttpResponse) -> Response { fn response(&self, req: &mut HttpRequest<S>, resp: HttpResponse) -> Result<Response> {
Response::Done(resp) Ok(Response::Done(resp))
} }
/// Method is called after body stream get sent to peer. /// Method is called after body stream get sent to peer.

View File

@ -141,7 +141,7 @@ impl<S, T: SessionBackend<S>> SessionStorage<T, S> {
impl<S: 'static, T: SessionBackend<S>> Middleware<S> for SessionStorage<T, S> { impl<S: 'static, T: SessionBackend<S>> Middleware<S> for SessionStorage<T, S> {
fn start(&self, req: &mut HttpRequest<S>) -> Started { fn start(&self, req: &mut HttpRequest<S>) -> Result<Started> {
let mut req = req.clone(); let mut req = req.clone();
let fut = self.0.from_request(&mut req) let fut = self.0.from_request(&mut req)
@ -154,14 +154,14 @@ impl<S: 'static, T: SessionBackend<S>> Middleware<S> for SessionStorage<T, S> {
Err(err) => FutErr(err) Err(err) => FutErr(err)
} }
}); });
Started::Future(Box::new(fut)) Ok(Started::Future(Box::new(fut)))
} }
fn response(&self, req: &mut HttpRequest<S>, resp: HttpResponse) -> Response { fn response(&self, req: &mut HttpRequest<S>, resp: HttpResponse) -> Result<Response> {
if let Some(s_box) = req.extensions().remove::<Arc<SessionImplBox>>() { if let Some(s_box) = req.extensions().remove::<Arc<SessionImplBox>>() {
s_box.0.write(resp) s_box.0.write(resp)
} else { } else {
Response::Done(resp) Ok(Response::Done(resp))
} }
} }
} }
@ -179,7 +179,7 @@ pub trait SessionImpl: 'static {
fn clear(&mut self); fn clear(&mut self);
/// Write session to storage backend. /// Write session to storage backend.
fn write(&self, resp: HttpResponse) -> Response; fn write(&self, resp: HttpResponse) -> Result<Response>;
} }
/// Session's storage backend trait definition. /// Session's storage backend trait definition.
@ -205,8 +205,8 @@ impl SessionImpl for DummySessionImpl {
fn set(&mut self, key: &str, value: String) {} fn set(&mut self, key: &str, value: String) {}
fn remove(&mut self, key: &str) {} fn remove(&mut self, key: &str) {}
fn clear(&mut self) {} fn clear(&mut self) {}
fn write(&self, resp: HttpResponse) -> Response { fn write(&self, resp: HttpResponse) -> Result<Response> {
Response::Done(resp) Ok(Response::Done(resp))
} }
} }
@ -255,11 +255,11 @@ impl SessionImpl for CookieSession {
self.state.clear() self.state.clear()
} }
fn write(&self, mut resp: HttpResponse) -> Response { fn write(&self, mut resp: HttpResponse) -> Result<Response> {
if self.changed { if self.changed {
let _ = self.inner.set_cookie(&mut resp, &self.state); let _ = self.inner.set_cookie(&mut resp, &self.state);
} }
Response::Done(resp) Ok(Response::Done(resp))
} }
} }

View File

@ -290,11 +290,11 @@ impl<S: 'static, H: PipelineHandler<S>> StartMiddlewares<S, H> {
return WaitingResponse::init(info, reply) return WaitingResponse::init(info, reply)
} else { } else {
match info.mws[info.count].start(&mut info.req) { match info.mws[info.count].start(&mut info.req) {
Started::Done => Ok(Started::Done) =>
info.count += 1, info.count += 1,
Started::Response(resp) => Ok(Started::Response(resp)) =>
return RunMiddlewares::init(info, resp), return RunMiddlewares::init(info, resp),
Started::Future(mut fut) => Ok(Started::Future(mut fut)) =>
match fut.poll() { match fut.poll() {
Ok(Async::NotReady) => Ok(Async::NotReady) =>
return PipelineState::Starting(StartMiddlewares { return PipelineState::Starting(StartMiddlewares {
@ -310,7 +310,7 @@ impl<S: 'static, H: PipelineHandler<S>> StartMiddlewares<S, H> {
Err(err) => Err(err) =>
return ProcessResponse::init(err.into()), return ProcessResponse::init(err.into()),
}, },
Started::Err(err) => Err(err) =>
return ProcessResponse::init(err.into()), return ProcessResponse::init(err.into()),
} }
} }
@ -335,16 +335,16 @@ impl<S: 'static, H: PipelineHandler<S>> StartMiddlewares<S, H> {
} else { } else {
loop { loop {
match info.mws[info.count].start(info.req_mut()) { match info.mws[info.count].start(info.req_mut()) {
Started::Done => Ok(Started::Done) =>
info.count += 1, info.count += 1,
Started::Response(resp) => { Ok(Started::Response(resp)) => {
return Ok(RunMiddlewares::init(info, resp)); return Ok(RunMiddlewares::init(info, resp));
}, },
Started::Future(fut) => { Ok(Started::Future(fut)) => {
self.fut = Some(fut); self.fut = Some(fut);
continue 'outer continue 'outer
}, },
Started::Err(err) => Err(err) =>
return Ok(ProcessResponse::init(err.into())) return Ok(ProcessResponse::init(err.into()))
} }
} }
@ -411,11 +411,11 @@ impl<S: 'static, H> RunMiddlewares<S, H> {
loop { loop {
resp = match info.mws[curr].response(info.req_mut(), resp) { resp = match info.mws[curr].response(info.req_mut(), resp) {
Response::Err(err) => { Err(err) => {
info.count = curr + 1; info.count = curr + 1;
return ProcessResponse::init(err.into()) return ProcessResponse::init(err.into())
} }
Response::Done(r) => { Ok(Response::Done(r)) => {
curr += 1; curr += 1;
if curr == len { if curr == len {
return ProcessResponse::init(r) return ProcessResponse::init(r)
@ -423,7 +423,7 @@ impl<S: 'static, H> RunMiddlewares<S, H> {
r r
} }
}, },
Response::Future(fut) => { Ok(Response::Future(fut)) => {
return PipelineState::RunMiddlewares( return PipelineState::RunMiddlewares(
RunMiddlewares { curr: curr, fut: Some(fut), RunMiddlewares { curr: curr, fut: Some(fut),
_s: PhantomData, _h: PhantomData }) _s: PhantomData, _h: PhantomData })
@ -455,13 +455,13 @@ impl<S: 'static, H> RunMiddlewares<S, H> {
return Ok(ProcessResponse::init(resp)); return Ok(ProcessResponse::init(resp));
} else { } else {
match info.mws[self.curr].response(info.req_mut(), resp) { match info.mws[self.curr].response(info.req_mut(), resp) {
Response::Err(err) => Err(err) =>
return Ok(ProcessResponse::init(err.into())), return Ok(ProcessResponse::init(err.into())),
Response::Done(r) => { Ok(Response::Done(r)) => {
self.curr += 1; self.curr += 1;
resp = r resp = r
}, },
Response::Future(fut) => { Ok(Response::Future(fut)) => {
self.fut = Some(fut); self.fut = Some(fut);
break break
}, },

View File

@ -227,11 +227,11 @@ impl<S: 'static> StartMiddlewares<S> {
return WaitingResponse::init(info, reply) return WaitingResponse::init(info, reply)
} else { } else {
match info.mws[info.count].start(&mut info.req) { match info.mws[info.count].start(&mut info.req) {
MiddlewareStarted::Done => Ok(MiddlewareStarted::Done) =>
info.count += 1, info.count += 1,
MiddlewareStarted::Response(resp) => Ok(MiddlewareStarted::Response(resp)) =>
return RunMiddlewares::init(info, resp), return RunMiddlewares::init(info, resp),
MiddlewareStarted::Future(mut fut) => Ok(MiddlewareStarted::Future(mut fut)) =>
match fut.poll() { match fut.poll() {
Ok(Async::NotReady) => Ok(Async::NotReady) =>
return ComposeState::Starting(StartMiddlewares { return ComposeState::Starting(StartMiddlewares {
@ -246,7 +246,7 @@ impl<S: 'static> StartMiddlewares<S> {
Err(err) => Err(err) =>
return Response::init(err.into()), return Response::init(err.into()),
}, },
MiddlewareStarted::Err(err) => Err(err) =>
return Response::init(err.into()), return Response::init(err.into()),
} }
} }
@ -271,16 +271,16 @@ impl<S: 'static> StartMiddlewares<S> {
} else { } else {
loop { loop {
match info.mws[info.count].start(&mut info.req) { match info.mws[info.count].start(&mut info.req) {
MiddlewareStarted::Done => Ok(MiddlewareStarted::Done) =>
info.count += 1, info.count += 1,
MiddlewareStarted::Response(resp) => { Ok(MiddlewareStarted::Response(resp)) => {
return Some(RunMiddlewares::init(info, resp)); return Some(RunMiddlewares::init(info, resp));
}, },
MiddlewareStarted::Future(fut) => { Ok(MiddlewareStarted::Future(fut)) => {
self.fut = Some(fut); self.fut = Some(fut);
continue 'outer continue 'outer
}, },
MiddlewareStarted::Err(err) => Err(err) =>
return Some(Response::init(err.into())) return Some(Response::init(err.into()))
} }
} }
@ -339,11 +339,11 @@ impl<S: 'static> RunMiddlewares<S> {
loop { loop {
resp = match info.mws[curr].response(&mut info.req, resp) { resp = match info.mws[curr].response(&mut info.req, resp) {
MiddlewareResponse::Err(err) => { Err(err) => {
info.count = curr + 1; info.count = curr + 1;
return Response::init(err.into()) return Response::init(err.into())
}, },
MiddlewareResponse::Done(r) => { Ok(MiddlewareResponse::Done(r)) => {
curr += 1; curr += 1;
if curr == len { if curr == len {
return Response::init(r) return Response::init(r)
@ -351,7 +351,7 @@ impl<S: 'static> RunMiddlewares<S> {
r r
} }
}, },
MiddlewareResponse::Future(fut) => { Ok(MiddlewareResponse::Future(fut)) => {
return ComposeState::RunMiddlewares( return ComposeState::RunMiddlewares(
RunMiddlewares { curr: curr, fut: Some(fut), _s: PhantomData }) RunMiddlewares { curr: curr, fut: Some(fut), _s: PhantomData })
}, },
@ -382,13 +382,13 @@ impl<S: 'static> RunMiddlewares<S> {
return Some(Response::init(resp)); return Some(Response::init(resp));
} else { } else {
match info.mws[self.curr].response(&mut info.req, resp) { match info.mws[self.curr].response(&mut info.req, resp) {
MiddlewareResponse::Err(err) => Err(err) =>
return Some(Response::init(err.into())), return Some(Response::init(err.into())),
MiddlewareResponse::Done(r) => { Ok(MiddlewareResponse::Done(r)) => {
self.curr += 1; self.curr += 1;
resp = r resp = r
}, },
MiddlewareResponse::Future(fut) => { Ok(MiddlewareResponse::Future(fut)) => {
self.fut = Some(fut); self.fut = Some(fut);
break break
}, },

View File

@ -97,14 +97,14 @@ struct MiddlewareTest {
} }
impl<S> middleware::Middleware<S> for MiddlewareTest { impl<S> middleware::Middleware<S> for MiddlewareTest {
fn start(&self, _: &mut HttpRequest<S>) -> middleware::Started { fn start(&self, _: &mut HttpRequest<S>) -> Result<middleware::Started> {
self.start.store(self.start.load(Ordering::Relaxed) + 1, Ordering::Relaxed); self.start.store(self.start.load(Ordering::Relaxed) + 1, Ordering::Relaxed);
middleware::Started::Done Ok(middleware::Started::Done)
} }
fn response(&self, _: &mut HttpRequest<S>, resp: HttpResponse) -> middleware::Response { fn response(&self, _: &mut HttpRequest<S>, resp: HttpResponse) -> Result<middleware::Response> {
self.response.store(self.response.load(Ordering::Relaxed) + 1, Ordering::Relaxed); self.response.store(self.response.load(Ordering::Relaxed) + 1, Ordering::Relaxed);
middleware::Response::Done(resp) Ok(middleware::Response::Done(resp))
} }
fn finish(&self, _: &mut HttpRequest<S>, _: &HttpResponse) -> middleware::Finished { fn finish(&self, _: &mut HttpRequest<S>, _: &HttpResponse) -> middleware::Finished {