1
0
mirror of https://github.com/fafhrd91/actix-web synced 2024-11-27 17:52:56 +01:00

migrade rest of middlewares

This commit is contained in:
Nikolay Kim 2019-11-21 14:52:33 +06:00
parent 471f82f0e0
commit 55698f2524
4 changed files with 170 additions and 134 deletions

View File

@ -1,7 +1,8 @@
//! `Middleware` for conditionally enables another middleware. //! `Middleware` for conditionally enables another middleware.
use std::task::{Context, Poll};
use actix_service::{Service, Transform}; use actix_service::{Service, Transform};
use futures::future::{ok, Either, FutureResult, Map}; use futures::future::{ok, Either, FutureExt, LocalBoxFuture, Ready};
use futures::{Future, Poll};
/// `Middleware` for conditionally enables another middleware. /// `Middleware` for conditionally enables another middleware.
/// The controled middleware must not change the `Service` interfaces. /// The controled middleware must not change the `Service` interfaces.
@ -13,11 +14,11 @@ use futures::{Future, Poll};
/// use actix_web::middleware::{Condition, NormalizePath}; /// use actix_web::middleware::{Condition, NormalizePath};
/// use actix_web::App; /// use actix_web::App;
/// ///
/// fn main() { /// # fn main() {
/// let enable_normalize = std::env::var("NORMALIZE_PATH") == Ok("true".into()); /// let enable_normalize = std::env::var("NORMALIZE_PATH") == Ok("true".into());
/// let app = App::new() /// let app = App::new()
/// .wrap(Condition::new(enable_normalize, NormalizePath)); /// .wrap(Condition::new(enable_normalize, NormalizePath));
/// } /// # }
/// ``` /// ```
pub struct Condition<T> { pub struct Condition<T> {
trans: T, trans: T,
@ -32,29 +33,31 @@ impl<T> Condition<T> {
impl<S, T> Transform<S> for Condition<T> impl<S, T> Transform<S> for Condition<T>
where where
S: Service, S: Service + 'static,
T: Transform<S, Request = S::Request, Response = S::Response, Error = S::Error>, 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 Request = S::Request;
type Response = S::Response; type Response = S::Response;
type Error = S::Error; type Error = S::Error;
type InitError = T::InitError; type InitError = T::InitError;
type Transform = ConditionMiddleware<T::Transform, S>; type Transform = ConditionMiddleware<T::Transform, S>;
type Future = Either< type Future = LocalBoxFuture<'static, Result<Self::Transform, Self::InitError>>;
Map<T::Future, fn(T::Transform) -> Self::Transform>,
FutureResult<Self::Transform, Self::InitError>,
>;
fn new_transform(&self, service: S) -> Self::Future { fn new_transform(&self, service: S) -> Self::Future {
if self.enable { if self.enable {
let f = self let f = self.trans.new_transform(service).map(|res| {
.trans res.map(
.new_transform(service) ConditionMiddleware::Enable as fn(T::Transform) -> Self::Transform,
.map(ConditionMiddleware::Enable as fn(T::Transform) -> Self::Transform); )
Either::A(f) });
Either::Left(f)
} else { } else {
Either::B(ok(ConditionMiddleware::Disable(service))) Either::Right(ok(ConditionMiddleware::Disable(service)))
} }
.boxed_local()
} }
} }
@ -73,19 +76,19 @@ where
type Error = E::Error; type Error = E::Error;
type Future = Either<E::Future, D::Future>; 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::*; use ConditionMiddleware::*;
match self { match self {
Enable(service) => service.poll_ready(), Enable(service) => service.poll_ready(cx),
Disable(service) => service.poll_ready(), Disable(service) => service.poll_ready(cx),
} }
} }
fn call(&mut self, req: E::Request) -> Self::Future { fn call(&mut self, req: E::Request) -> Self::Future {
use ConditionMiddleware::*; use ConditionMiddleware::*;
match self { match self {
Enable(service) => Either::A(service.call(req)), Enable(service) => Either::Left(service.call(req)),
Disable(service) => Either::B(service.call(req)), Disable(service) => Either::Right(service.call(req)),
} }
} }
} }
@ -99,7 +102,7 @@ mod tests {
use crate::error::Result; use crate::error::Result;
use crate::http::{header::CONTENT_TYPE, HeaderValue, StatusCode}; use crate::http::{header::CONTENT_TYPE, HeaderValue, StatusCode};
use crate::middleware::errhandlers::*; use crate::middleware::errhandlers::*;
use crate::test::{self, TestRequest}; use crate::test::{self, block_on, TestRequest};
use crate::HttpResponse; use crate::HttpResponse;
fn render_500<B>(mut res: ServiceResponse<B>) -> Result<ErrorHandlerResponse<B>> { fn render_500<B>(mut res: ServiceResponse<B>) -> Result<ErrorHandlerResponse<B>> {
@ -111,33 +114,44 @@ mod tests {
#[test] #[test]
fn test_handler_enabled() { fn test_handler_enabled() {
let srv = |req: ServiceRequest| { block_on(async {
req.into_response(HttpResponse::InternalServerError().finish()) let srv = |req: ServiceRequest| {
}; ok(req.into_response(HttpResponse::InternalServerError().finish()))
};
let mw = let mw = ErrorHandlers::new()
ErrorHandlers::new().handler(StatusCode::INTERNAL_SERVER_ERROR, render_500); .handler(StatusCode::INTERNAL_SERVER_ERROR, render_500);
let mut mw = let mut mw = Condition::new(true, mw)
test::block_on(Condition::new(true, mw).new_transform(srv.into_service())) .new_transform(srv.into_service())
.await
.unwrap(); .unwrap();
let resp = test::call_service(&mut mw, TestRequest::default().to_srv_request()); let resp =
assert_eq!(resp.headers().get(CONTENT_TYPE).unwrap(), "0001"); test::call_service(&mut mw, TestRequest::default().to_srv_request())
.await;
assert_eq!(resp.headers().get(CONTENT_TYPE).unwrap(), "0001");
})
} }
#[test] #[test]
fn test_handler_disabled() { fn test_handler_disabled() {
let srv = |req: ServiceRequest| { block_on(async {
req.into_response(HttpResponse::InternalServerError().finish()) let srv = |req: ServiceRequest| {
}; ok(req.into_response(HttpResponse::InternalServerError().finish()))
};
let mw = let mw = ErrorHandlers::new()
ErrorHandlers::new().handler(StatusCode::INTERNAL_SERVER_ERROR, render_500); .handler(StatusCode::INTERNAL_SERVER_ERROR, render_500);
let mut mw = let mut mw = Condition::new(false, mw)
test::block_on(Condition::new(false, mw).new_transform(srv.into_service())) .new_transform(srv.into_service())
.await
.unwrap(); .unwrap();
let resp = test::call_service(&mut mw, TestRequest::default().to_srv_request()); let resp =
assert_eq!(resp.headers().get(CONTENT_TYPE), None); test::call_service(&mut mw, TestRequest::default().to_srv_request())
.await;
assert_eq!(resp.headers().get(CONTENT_TYPE), None);
})
} }
} }

View File

@ -1,9 +1,9 @@
//! Custom handlers service for responses. //! Custom handlers service for responses.
use std::rc::Rc; use std::rc::Rc;
use std::task::{Context, Poll};
use actix_service::{Service, Transform}; use actix_service::{Service, Transform};
use futures::future::{err, ok, Either, Future, FutureResult}; use futures::future::{err, ok, Either, Future, FutureExt, LocalBoxFuture, Ready};
use futures::Poll;
use hashbrown::HashMap; use hashbrown::HashMap;
use crate::dev::{ServiceRequest, ServiceResponse}; use crate::dev::{ServiceRequest, ServiceResponse};
@ -15,7 +15,7 @@ pub enum ErrorHandlerResponse<B> {
/// New http response got generated /// New http response got generated
Response(ServiceResponse<B>), Response(ServiceResponse<B>),
/// Result is a future that resolves to a new http response /// 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>>; type ErrorHandler<B> = dyn Fn(ServiceResponse<B>) -> Result<ErrorHandlerResponse<B>>;
@ -39,17 +39,17 @@ type ErrorHandler<B> = dyn Fn(ServiceResponse<B>) -> Result<ErrorHandlerResponse
/// Ok(ErrorHandlerResponse::Response(res)) /// Ok(ErrorHandlerResponse::Response(res))
/// } /// }
/// ///
/// fn main() { /// # fn main() {
/// let app = App::new() /// let app = App::new()
/// .wrap( /// .wrap(
/// ErrorHandlers::new() /// ErrorHandlers::new()
/// .handler(http::StatusCode::INTERNAL_SERVER_ERROR, render_500), /// .handler(http::StatusCode::INTERNAL_SERVER_ERROR, render_500),
/// ) /// )
/// .service(web::resource("/test") /// .service(web::resource("/test")
/// .route(web::get().to(|| HttpResponse::Ok())) /// .route(web::get().to(|| HttpResponse::Ok()))
/// .route(web::head().to(|| HttpResponse::MethodNotAllowed()) /// .route(web::head().to(|| HttpResponse::MethodNotAllowed())
/// )); /// ));
/// } /// # }
/// ``` /// ```
pub struct ErrorHandlers<B> { pub struct ErrorHandlers<B> {
handlers: Rc<HashMap<StatusCode, Box<ErrorHandler<B>>>>, handlers: Rc<HashMap<StatusCode, Box<ErrorHandler<B>>>>,
@ -92,7 +92,7 @@ where
type Error = Error; type Error = Error;
type InitError = (); type InitError = ();
type Transform = ErrorHandlersMiddleware<S, B>; 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 { fn new_transform(&self, service: S) -> Self::Future {
ok(ErrorHandlersMiddleware { ok(ErrorHandlersMiddleware {
@ -117,26 +117,30 @@ where
type Request = ServiceRequest; type Request = ServiceRequest;
type Response = ServiceResponse<B>; type Response = ServiceResponse<B>;
type Error = Error; 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> { fn poll_ready(&mut self, cx: &mut Context) -> Poll<Result<(), Self::Error>> {
self.service.poll_ready() self.service.poll_ready(cx)
} }
fn call(&mut self, req: ServiceRequest) -> Self::Future { fn call(&mut self, req: ServiceRequest) -> Self::Future {
let handlers = self.handlers.clone(); 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()) { if let Some(handler) = handlers.get(&res.status()) {
match handler(res) { match handler(res) {
Ok(ErrorHandlerResponse::Response(res)) => Either::A(ok(res)), Ok(ErrorHandlerResponse::Response(res)) => Ok(res),
Ok(ErrorHandlerResponse::Future(fut)) => Either::B(fut), Ok(ErrorHandlerResponse::Future(fut)) => fut.await,
Err(e) => Either::A(err(e)), Err(e) => Err(e),
} }
} else { } else {
Either::A(ok(res)) Ok(res)
} }
})) }
.boxed_local()
} }
} }
@ -147,7 +151,7 @@ mod tests {
use super::*; use super::*;
use crate::http::{header::CONTENT_TYPE, HeaderValue, StatusCode}; use crate::http::{header::CONTENT_TYPE, HeaderValue, StatusCode};
use crate::test::{self, TestRequest}; use crate::test::{self, block_on, TestRequest};
use crate::HttpResponse; use crate::HttpResponse;
fn render_500<B>(mut res: ServiceResponse<B>) -> Result<ErrorHandlerResponse<B>> { fn render_500<B>(mut res: ServiceResponse<B>) -> Result<ErrorHandlerResponse<B>> {
@ -159,19 +163,22 @@ mod tests {
#[test] #[test]
fn test_handler() { fn test_handler() {
let srv = |req: ServiceRequest| { block_on(async {
req.into_response(HttpResponse::InternalServerError().finish()) let srv = |req: ServiceRequest| {
}; ok(req.into_response(HttpResponse::InternalServerError().finish()))
};
let mut mw = test::block_on( let mut mw = ErrorHandlers::new()
ErrorHandlers::new()
.handler(StatusCode::INTERNAL_SERVER_ERROR, render_500) .handler(StatusCode::INTERNAL_SERVER_ERROR, render_500)
.new_transform(srv.into_service()), .new_transform(srv.into_service())
) .await
.unwrap(); .unwrap();
let resp = test::call_service(&mut mw, TestRequest::default().to_srv_request()); let resp =
assert_eq!(resp.headers().get(CONTENT_TYPE).unwrap(), "0001"); 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>( fn render_500_async<B: 'static>(
@ -180,23 +187,26 @@ mod tests {
res.response_mut() res.response_mut()
.headers_mut() .headers_mut()
.insert(CONTENT_TYPE, HeaderValue::from_static("0001")); .insert(CONTENT_TYPE, HeaderValue::from_static("0001"));
Ok(ErrorHandlerResponse::Future(Box::new(ok(res)))) Ok(ErrorHandlerResponse::Future(ok(res).boxed_local()))
} }
#[test] #[test]
fn test_handler_async() { fn test_handler_async() {
let srv = |req: ServiceRequest| { block_on(async {
req.into_response(HttpResponse::InternalServerError().finish()) let srv = |req: ServiceRequest| {
}; ok(req.into_response(HttpResponse::InternalServerError().finish()))
};
let mut mw = test::block_on( let mut mw = ErrorHandlers::new()
ErrorHandlers::new()
.handler(StatusCode::INTERNAL_SERVER_ERROR, render_500_async) .handler(StatusCode::INTERNAL_SERVER_ERROR, render_500_async)
.new_transform(srv.into_service()), .new_transform(srv.into_service())
) .await
.unwrap(); .unwrap();
let resp = test::call_service(&mut mw, TestRequest::default().to_srv_request()); let resp =
assert_eq!(resp.headers().get(CONTENT_TYPE).unwrap(), "0001"); test::call_service(&mut mw, TestRequest::default().to_srv_request())
.await;
assert_eq!(resp.headers().get(CONTENT_TYPE).unwrap(), "0001");
})
} }
} }

View File

@ -2,13 +2,13 @@
mod compress; mod compress;
pub use self::compress::{BodyEncoding, Compress}; pub use self::compress::{BodyEncoding, Compress};
//mod condition; mod condition;
mod defaultheaders; mod defaultheaders;
//pub mod errhandlers; pub mod errhandlers;
mod logger; mod logger;
//mod normalize; mod normalize;
//pub use self::condition::Condition; pub use self::condition::Condition;
pub use self::defaultheaders::DefaultHeaders; pub use self::defaultheaders::DefaultHeaders;
pub use self::logger::Logger; pub use self::logger::Logger;
//pub use self::normalize::NormalizePath; pub use self::normalize::NormalizePath;

View File

@ -1,9 +1,10 @@
//! `Middleware` to normalize request's URI //! `Middleware` to normalize request's URI
use std::task::{Context, Poll};
use actix_http::http::{HttpTryFrom, PathAndQuery, Uri}; use actix_http::http::{HttpTryFrom, PathAndQuery, Uri};
use actix_service::{Service, Transform}; use actix_service::{Service, Transform};
use bytes::Bytes; use bytes::Bytes;
use futures::future::{self, FutureResult}; use futures::future::{ok, Ready};
use regex::Regex; use regex::Regex;
use crate::service::{ServiceRequest, ServiceResponse}; use crate::service::{ServiceRequest, ServiceResponse};
@ -19,15 +20,15 @@ use crate::Error;
/// ```rust /// ```rust
/// use actix_web::{web, http, middleware, App, HttpResponse}; /// use actix_web::{web, http, middleware, App, HttpResponse};
/// ///
/// fn main() { /// # fn main() {
/// let app = App::new() /// let app = App::new()
/// .wrap(middleware::NormalizePath) /// .wrap(middleware::NormalizePath)
/// .service( /// .service(
/// web::resource("/test") /// web::resource("/test")
/// .route(web::get().to(|| HttpResponse::Ok())) /// .route(web::get().to(|| HttpResponse::Ok()))
/// .route(web::method(http::Method::HEAD).to(|| HttpResponse::MethodNotAllowed())) /// .route(web::method(http::Method::HEAD).to(|| HttpResponse::MethodNotAllowed()))
/// ); /// );
/// } /// # }
/// ``` /// ```
pub struct NormalizePath; pub struct NormalizePath;
@ -42,10 +43,10 @@ where
type Error = Error; type Error = Error;
type InitError = (); type InitError = ();
type Transform = NormalizePathNormalization<S>; type Transform = NormalizePathNormalization<S>;
type Future = FutureResult<Self::Transform, Self::InitError>; type Future = Ready<Result<Self::Transform, Self::InitError>>;
fn new_transform(&self, service: S) -> Self::Future { fn new_transform(&self, service: S) -> Self::Future {
future::ok(NormalizePathNormalization { ok(NormalizePathNormalization {
service, service,
merge_slash: Regex::new("//+").unwrap(), merge_slash: Regex::new("//+").unwrap(),
}) })
@ -67,8 +68,8 @@ where
type Error = Error; type Error = Error;
type Future = S::Future; type Future = S::Future;
fn poll_ready(&mut self) -> futures::Poll<(), Self::Error> { fn poll_ready(&mut self, cx: &mut Context) -> Poll<Result<(), Self::Error>> {
self.service.poll_ready() self.service.poll_ready(cx)
} }
fn call(&mut self, mut req: ServiceRequest) -> Self::Future { fn call(&mut self, mut req: ServiceRequest) -> Self::Future {
@ -109,46 +110,57 @@ mod tests {
#[test] #[test]
fn test_wrap() { fn test_wrap() {
let mut app = init_service( block_on(async {
App::new() let mut app = init_service(
.wrap(NormalizePath::default()) App::new()
.service(web::resource("/v1/something/").to(|| HttpResponse::Ok())), .wrap(NormalizePath::default())
); .service(web::resource("/v1/something/").to(|| HttpResponse::Ok())),
)
.await;
let req = TestRequest::with_uri("/v1//something////").to_request(); let req = TestRequest::with_uri("/v1//something////").to_request();
let res = call_service(&mut app, req); let res = call_service(&mut app, req).await;
assert!(res.status().is_success()); assert!(res.status().is_success());
})
} }
#[test] #[test]
fn test_in_place_normalization() { fn test_in_place_normalization() {
let srv = |req: ServiceRequest| { block_on(async {
assert_eq!("/v1/something/", req.path()); let srv = |req: ServiceRequest| {
req.into_response(HttpResponse::Ok().finish()) assert_eq!("/v1/something/", req.path());
}; ok(req.into_response(HttpResponse::Ok().finish()))
};
let mut normalize = let mut normalize = NormalizePath
block_on(NormalizePath.new_transform(srv.into_service())).unwrap(); .new_transform(srv.into_service())
.await
.unwrap();
let req = TestRequest::with_uri("/v1//something////").to_srv_request(); let req = TestRequest::with_uri("/v1//something////").to_srv_request();
let res = block_on(normalize.call(req)).unwrap(); let res = normalize.call(req).await.unwrap();
assert!(res.status().is_success()); assert!(res.status().is_success());
})
} }
#[test] #[test]
fn should_normalize_nothing() { fn should_normalize_nothing() {
const URI: &str = "/v1/something/"; block_on(async {
const URI: &str = "/v1/something/";
let srv = |req: ServiceRequest| { let srv = |req: ServiceRequest| {
assert_eq!(URI, req.path()); assert_eq!(URI, req.path());
req.into_response(HttpResponse::Ok().finish()) ok(req.into_response(HttpResponse::Ok().finish()))
}; };
let mut normalize = let mut normalize = NormalizePath
block_on(NormalizePath.new_transform(srv.into_service())).unwrap(); .new_transform(srv.into_service())
.await
.unwrap();
let req = TestRequest::with_uri(URI).to_srv_request(); let req = TestRequest::with_uri(URI).to_srv_request();
let res = block_on(normalize.call(req)).unwrap(); let res = normalize.call(req).await.unwrap();
assert!(res.status().is_success()); assert!(res.status().is_success());
})
} }
} }