Skip to content

Commit

Permalink
migrade rest of middlewares
Browse files Browse the repository at this point in the history
  • Loading branch information
fafhrd91 committed Nov 21, 2019
1 parent 471f82f commit 55698f2
Show file tree
Hide file tree
Showing 4 changed files with 173 additions and 137 deletions.
98 changes: 56 additions & 42 deletions src/middleware/condition.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
//! `Middleware` for conditionally enables another middleware.
use std::task::{Context, Poll};

use actix_service::{Service, Transform};
use futures::future::{ok, Either, FutureResult, Map};
use futures::{Future, Poll};
use futures::future::{ok, Either, FutureExt, LocalBoxFuture, Ready};

/// `Middleware` for conditionally enables another middleware.
/// The controled middleware must not change the `Service` interfaces.
Expand All @@ -13,11 +14,11 @@ use futures::{Future, Poll};
/// use actix_web::middleware::{Condition, NormalizePath};
/// use actix_web::App;
///
/// fn main() {
/// let enable_normalize = std::env::var("NORMALIZE_PATH") == Ok("true".into());
/// let app = App::new()
/// .wrap(Condition::new(enable_normalize, NormalizePath));
/// }
/// # fn main() {
/// let enable_normalize = std::env::var("NORMALIZE_PATH") == Ok("true".into());
/// let app = App::new()
/// .wrap(Condition::new(enable_normalize, NormalizePath));
/// # }
/// ```
pub struct Condition<T> {
trans: T,
Expand All @@ -32,29 +33,31 @@ impl<T> Condition<T> {

impl<S, T> Transform<S> for Condition<T>
where
S: Service,
S: Service + 'static,
T: Transform<S, Request = S::Request, Response = S::Response, Error = S::Error>,
T::Future: 'static,
T::InitError: 'static,
T::Transform: 'static,
{
type Request = S::Request;
type Response = S::Response;
type Error = S::Error;
type InitError = T::InitError;
type Transform = ConditionMiddleware<T::Transform, S>;
type Future = Either<
Map<T::Future, fn(T::Transform) -> Self::Transform>,
FutureResult<Self::Transform, Self::InitError>,
>;
type Future = LocalBoxFuture<'static, Result<Self::Transform, Self::InitError>>;

fn new_transform(&self, service: S) -> Self::Future {
if self.enable {
let f = self
.trans
.new_transform(service)
.map(ConditionMiddleware::Enable as fn(T::Transform) -> Self::Transform);
Either::A(f)
let f = self.trans.new_transform(service).map(|res| {
res.map(
ConditionMiddleware::Enable as fn(T::Transform) -> Self::Transform,
)
});
Either::Left(f)
} else {
Either::B(ok(ConditionMiddleware::Disable(service)))
Either::Right(ok(ConditionMiddleware::Disable(service)))
}
.boxed_local()
}
}

Expand All @@ -73,19 +76,19 @@ where
type Error = E::Error;
type Future = Either<E::Future, D::Future>;

fn poll_ready(&mut self) -> Poll<(), Self::Error> {
fn poll_ready(&mut self, cx: &mut Context) -> Poll<Result<(), Self::Error>> {
use ConditionMiddleware::*;
match self {
Enable(service) => service.poll_ready(),
Disable(service) => service.poll_ready(),
Enable(service) => service.poll_ready(cx),
Disable(service) => service.poll_ready(cx),
}
}

fn call(&mut self, req: E::Request) -> Self::Future {
use ConditionMiddleware::*;
match self {
Enable(service) => Either::A(service.call(req)),
Disable(service) => Either::B(service.call(req)),
Enable(service) => Either::Left(service.call(req)),
Disable(service) => Either::Right(service.call(req)),
}
}
}
Expand All @@ -99,7 +102,7 @@ mod tests {
use crate::error::Result;
use crate::http::{header::CONTENT_TYPE, HeaderValue, StatusCode};
use crate::middleware::errhandlers::*;
use crate::test::{self, TestRequest};
use crate::test::{self, block_on, TestRequest};
use crate::HttpResponse;

fn render_500<B>(mut res: ServiceResponse<B>) -> Result<ErrorHandlerResponse<B>> {
Expand All @@ -111,33 +114,44 @@ mod tests {

#[test]
fn test_handler_enabled() {
let srv = |req: ServiceRequest| {
req.into_response(HttpResponse::InternalServerError().finish())
};
block_on(async {
let srv = |req: ServiceRequest| {
ok(req.into_response(HttpResponse::InternalServerError().finish()))
};

let mw =
ErrorHandlers::new().handler(StatusCode::INTERNAL_SERVER_ERROR, render_500);
let mw = ErrorHandlers::new()
.handler(StatusCode::INTERNAL_SERVER_ERROR, render_500);

let mut mw =
test::block_on(Condition::new(true, mw).new_transform(srv.into_service()))
let mut mw = Condition::new(true, mw)
.new_transform(srv.into_service())
.await
.unwrap();
let resp = test::call_service(&mut mw, TestRequest::default().to_srv_request());
assert_eq!(resp.headers().get(CONTENT_TYPE).unwrap(), "0001");
let resp =
test::call_service(&mut mw, TestRequest::default().to_srv_request())
.await;
assert_eq!(resp.headers().get(CONTENT_TYPE).unwrap(), "0001");
})
}

#[test]
fn test_handler_disabled() {
let srv = |req: ServiceRequest| {
req.into_response(HttpResponse::InternalServerError().finish())
};
block_on(async {
let srv = |req: ServiceRequest| {
ok(req.into_response(HttpResponse::InternalServerError().finish()))
};

let mw =
ErrorHandlers::new().handler(StatusCode::INTERNAL_SERVER_ERROR, render_500);
let mw = ErrorHandlers::new()
.handler(StatusCode::INTERNAL_SERVER_ERROR, render_500);

let mut mw =
test::block_on(Condition::new(false, mw).new_transform(srv.into_service()))
let mut mw = Condition::new(false, mw)
.new_transform(srv.into_service())
.await
.unwrap();

let resp = test::call_service(&mut mw, TestRequest::default().to_srv_request());
assert_eq!(resp.headers().get(CONTENT_TYPE), None);
let resp =
test::call_service(&mut mw, TestRequest::default().to_srv_request())
.await;
assert_eq!(resp.headers().get(CONTENT_TYPE), None);
})
}
}
106 changes: 58 additions & 48 deletions src/middleware/errhandlers.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
//! Custom handlers service for responses.
use std::rc::Rc;
use std::task::{Context, Poll};

use actix_service::{Service, Transform};
use futures::future::{err, ok, Either, Future, FutureResult};
use futures::Poll;
use futures::future::{err, ok, Either, Future, FutureExt, LocalBoxFuture, Ready};
use hashbrown::HashMap;

use crate::dev::{ServiceRequest, ServiceResponse};
Expand All @@ -15,7 +15,7 @@ pub enum ErrorHandlerResponse<B> {
/// New http response got generated
Response(ServiceResponse<B>),
/// Result is a future that resolves to a new http response
Future(Box<dyn Future<Item = ServiceResponse<B>, Error = Error>>),
Future(LocalBoxFuture<'static, Result<ServiceResponse<B>, Error>>),
}

type ErrorHandler<B> = dyn Fn(ServiceResponse<B>) -> Result<ErrorHandlerResponse<B>>;
Expand All @@ -39,17 +39,17 @@ type ErrorHandler<B> = dyn Fn(ServiceResponse<B>) -> Result<ErrorHandlerResponse
/// Ok(ErrorHandlerResponse::Response(res))
/// }
///
/// fn main() {
/// let app = App::new()
/// .wrap(
/// ErrorHandlers::new()
/// .handler(http::StatusCode::INTERNAL_SERVER_ERROR, render_500),
/// )
/// .service(web::resource("/test")
/// .route(web::get().to(|| HttpResponse::Ok()))
/// .route(web::head().to(|| HttpResponse::MethodNotAllowed())
/// ));
/// }
/// # fn main() {
/// let app = App::new()
/// .wrap(
/// ErrorHandlers::new()
/// .handler(http::StatusCode::INTERNAL_SERVER_ERROR, render_500),
/// )
/// .service(web::resource("/test")
/// .route(web::get().to(|| HttpResponse::Ok()))
/// .route(web::head().to(|| HttpResponse::MethodNotAllowed())
/// ));
/// # }
/// ```
pub struct ErrorHandlers<B> {
handlers: Rc<HashMap<StatusCode, Box<ErrorHandler<B>>>>,
Expand Down Expand Up @@ -92,7 +92,7 @@ where
type Error = Error;
type InitError = ();
type Transform = ErrorHandlersMiddleware<S, B>;
type Future = FutureResult<Self::Transform, Self::InitError>;
type Future = Ready<Result<Self::Transform, Self::InitError>>;

fn new_transform(&self, service: S) -> Self::Future {
ok(ErrorHandlersMiddleware {
Expand All @@ -117,26 +117,30 @@ where
type Request = ServiceRequest;
type Response = ServiceResponse<B>;
type Error = Error;
type Future = Box<dyn Future<Item = Self::Response, Error = Self::Error>>;
type Future = LocalBoxFuture<'static, Result<Self::Response, Self::Error>>;

fn poll_ready(&mut self) -> Poll<(), Self::Error> {
self.service.poll_ready()
fn poll_ready(&mut self, cx: &mut Context) -> Poll<Result<(), Self::Error>> {
self.service.poll_ready(cx)
}

fn call(&mut self, req: ServiceRequest) -> Self::Future {
let handlers = self.handlers.clone();
let fut = self.service.call(req);

async move {
let res = fut.await?;

Box::new(self.service.call(req).and_then(move |res| {
if let Some(handler) = handlers.get(&res.status()) {
match handler(res) {
Ok(ErrorHandlerResponse::Response(res)) => Either::A(ok(res)),
Ok(ErrorHandlerResponse::Future(fut)) => Either::B(fut),
Err(e) => Either::A(err(e)),
Ok(ErrorHandlerResponse::Response(res)) => Ok(res),
Ok(ErrorHandlerResponse::Future(fut)) => fut.await,
Err(e) => Err(e),
}
} else {
Either::A(ok(res))
Ok(res)
}
}))
}
.boxed_local()
}
}

Expand All @@ -147,7 +151,7 @@ mod tests {

use super::*;
use crate::http::{header::CONTENT_TYPE, HeaderValue, StatusCode};
use crate::test::{self, TestRequest};
use crate::test::{self, block_on, TestRequest};
use crate::HttpResponse;

fn render_500<B>(mut res: ServiceResponse<B>) -> Result<ErrorHandlerResponse<B>> {
Expand All @@ -159,19 +163,22 @@ mod tests {

#[test]
fn test_handler() {
let srv = |req: ServiceRequest| {
req.into_response(HttpResponse::InternalServerError().finish())
};
block_on(async {
let srv = |req: ServiceRequest| {
ok(req.into_response(HttpResponse::InternalServerError().finish()))
};

let mut mw = test::block_on(
ErrorHandlers::new()
let mut mw = ErrorHandlers::new()
.handler(StatusCode::INTERNAL_SERVER_ERROR, render_500)
.new_transform(srv.into_service()),
)
.unwrap();

let resp = test::call_service(&mut mw, TestRequest::default().to_srv_request());
assert_eq!(resp.headers().get(CONTENT_TYPE).unwrap(), "0001");
.new_transform(srv.into_service())
.await
.unwrap();

let resp =
test::call_service(&mut mw, TestRequest::default().to_srv_request())
.await;
assert_eq!(resp.headers().get(CONTENT_TYPE).unwrap(), "0001");
})
}

fn render_500_async<B: 'static>(
Expand All @@ -180,23 +187,26 @@ mod tests {
res.response_mut()
.headers_mut()
.insert(CONTENT_TYPE, HeaderValue::from_static("0001"));
Ok(ErrorHandlerResponse::Future(Box::new(ok(res))))
Ok(ErrorHandlerResponse::Future(ok(res).boxed_local()))
}

#[test]
fn test_handler_async() {
let srv = |req: ServiceRequest| {
req.into_response(HttpResponse::InternalServerError().finish())
};
block_on(async {
let srv = |req: ServiceRequest| {
ok(req.into_response(HttpResponse::InternalServerError().finish()))
};

let mut mw = test::block_on(
ErrorHandlers::new()
let mut mw = ErrorHandlers::new()
.handler(StatusCode::INTERNAL_SERVER_ERROR, render_500_async)
.new_transform(srv.into_service()),
)
.unwrap();

let resp = test::call_service(&mut mw, TestRequest::default().to_srv_request());
assert_eq!(resp.headers().get(CONTENT_TYPE).unwrap(), "0001");
.new_transform(srv.into_service())
.await
.unwrap();

let resp =
test::call_service(&mut mw, TestRequest::default().to_srv_request())
.await;
assert_eq!(resp.headers().get(CONTENT_TYPE).unwrap(), "0001");
})
}
}
10 changes: 5 additions & 5 deletions src/middleware/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@
mod compress;
pub use self::compress::{BodyEncoding, Compress};

//mod condition;
mod condition;
mod defaultheaders;
//pub mod errhandlers;
pub mod errhandlers;
mod logger;
//mod normalize;
mod normalize;

//pub use self::condition::Condition;
pub use self::condition::Condition;
pub use self::defaultheaders::DefaultHeaders;
pub use self::logger::Logger;
//pub use self::normalize::NormalizePath;
pub use self::normalize::NormalizePath;
Loading

0 comments on commit 55698f2

Please sign in to comment.