mirror of
https://github.com/fafhrd91/actix-web
synced 2025-06-27 15:29:03 +02:00
update middleware impl
This commit is contained in:
@ -8,8 +8,9 @@ use actix_http::http::header::{
|
||||
};
|
||||
use actix_http::http::{HttpTryFrom, StatusCode};
|
||||
use actix_http::{Error, Head, ResponseHead};
|
||||
use actix_service::{IntoNewTransform, Service, Transform};
|
||||
use actix_service::{Service, Transform};
|
||||
use bytes::{Bytes, BytesMut};
|
||||
use futures::future::{ok, FutureResult};
|
||||
use futures::{Async, Future, Poll};
|
||||
use log::trace;
|
||||
|
||||
@ -18,7 +19,6 @@ use brotli2::write::BrotliEncoder;
|
||||
#[cfg(feature = "flate2")]
|
||||
use flate2::write::{GzEncoder, ZlibEncoder};
|
||||
|
||||
use crate::middleware::MiddlewareFactory;
|
||||
use crate::service::{ServiceRequest, ServiceResponse};
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
@ -37,6 +37,33 @@ impl Default for Compress {
|
||||
}
|
||||
|
||||
impl<S, P, B> Transform<S> for Compress
|
||||
where
|
||||
P: 'static,
|
||||
B: MessageBody,
|
||||
S: Service<Request = ServiceRequest<P>, Response = ServiceResponse<B>>,
|
||||
S::Future: 'static,
|
||||
{
|
||||
type Request = ServiceRequest<P>;
|
||||
type Response = ServiceResponse<Encoder<B>>;
|
||||
type Error = S::Error;
|
||||
type InitError = ();
|
||||
type Transform = CompressMiddleware<S>;
|
||||
type Future = FutureResult<Self::Transform, Self::InitError>;
|
||||
|
||||
fn new_transform(&self, service: S) -> Self::Future {
|
||||
ok(CompressMiddleware {
|
||||
service,
|
||||
encoding: self.0,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub struct CompressMiddleware<S> {
|
||||
service: S,
|
||||
encoding: ContentEncoding,
|
||||
}
|
||||
|
||||
impl<S, P, B> Service for CompressMiddleware<S>
|
||||
where
|
||||
P: 'static,
|
||||
B: MessageBody,
|
||||
@ -49,14 +76,14 @@ where
|
||||
type Future = CompressResponse<S, P, B>;
|
||||
|
||||
fn poll_ready(&mut self) -> Poll<(), Self::Error> {
|
||||
Ok(Async::Ready(()))
|
||||
self.service.poll_ready()
|
||||
}
|
||||
|
||||
fn call(&mut self, req: ServiceRequest<P>, srv: &mut S) -> Self::Future {
|
||||
fn call(&mut self, req: ServiceRequest<P>) -> Self::Future {
|
||||
// negotiate content-encoding
|
||||
let encoding = if let Some(val) = req.headers.get(ACCEPT_ENCODING) {
|
||||
if let Ok(enc) = val.to_str() {
|
||||
AcceptEncoding::parse(enc, self.0)
|
||||
AcceptEncoding::parse(enc, self.encoding)
|
||||
} else {
|
||||
ContentEncoding::Identity
|
||||
}
|
||||
@ -66,7 +93,7 @@ where
|
||||
|
||||
CompressResponse {
|
||||
encoding,
|
||||
fut: srv.call(req),
|
||||
fut: self.service.call(req),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -102,18 +129,6 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<S, P, B> IntoNewTransform<MiddlewareFactory<Compress, S>, S> for Compress
|
||||
where
|
||||
P: 'static,
|
||||
B: MessageBody,
|
||||
S: Service<Request = ServiceRequest<P>, Response = ServiceResponse<B>>,
|
||||
S::Future: 'static,
|
||||
{
|
||||
fn into_new_transform(self) -> MiddlewareFactory<Compress, S> {
|
||||
MiddlewareFactory::new(self)
|
||||
}
|
||||
}
|
||||
|
||||
enum EncoderBody<B> {
|
||||
Body(B),
|
||||
Other(Box<dyn MessageBody>),
|
||||
|
@ -3,10 +3,10 @@ use std::rc::Rc;
|
||||
|
||||
use actix_http::http::header::{HeaderName, HeaderValue, CONTENT_TYPE};
|
||||
use actix_http::http::{HeaderMap, HttpTryFrom};
|
||||
use actix_service::{IntoNewTransform, Service, Transform};
|
||||
use futures::{Async, Future, Poll};
|
||||
use actix_service::{Service, Transform};
|
||||
use futures::future::{ok, FutureResult};
|
||||
use futures::{Future, Poll};
|
||||
|
||||
use crate::middleware::MiddlewareFactory;
|
||||
use crate::service::{ServiceRequest, ServiceResponse};
|
||||
|
||||
/// `Middleware` for setting default response headers.
|
||||
@ -84,35 +84,49 @@ impl DefaultHeaders {
|
||||
}
|
||||
}
|
||||
|
||||
impl<S, State, B> IntoNewTransform<MiddlewareFactory<DefaultHeaders, S>, S>
|
||||
for DefaultHeaders
|
||||
impl<S, P, B> Transform<S> for DefaultHeaders
|
||||
where
|
||||
S: Service<Request = ServiceRequest<State>, Response = ServiceResponse<B>>,
|
||||
S: Service<Request = ServiceRequest<P>, Response = ServiceResponse<B>>,
|
||||
S::Future: 'static,
|
||||
{
|
||||
fn into_new_transform(self) -> MiddlewareFactory<DefaultHeaders, S> {
|
||||
MiddlewareFactory::new(self)
|
||||
type Request = ServiceRequest<P>;
|
||||
type Response = ServiceResponse<B>;
|
||||
type Error = S::Error;
|
||||
type InitError = ();
|
||||
type Transform = DefaultHeadersMiddleware<S>;
|
||||
type Future = FutureResult<Self::Transform, Self::InitError>;
|
||||
|
||||
fn new_transform(&self, service: S) -> Self::Future {
|
||||
ok(DefaultHeadersMiddleware {
|
||||
service,
|
||||
inner: self.inner.clone(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<S, State, B> Transform<S> for DefaultHeaders
|
||||
pub struct DefaultHeadersMiddleware<S> {
|
||||
service: S,
|
||||
inner: Rc<Inner>,
|
||||
}
|
||||
|
||||
impl<S, P, B> Service for DefaultHeadersMiddleware<S>
|
||||
where
|
||||
S: Service<Request = ServiceRequest<State>, Response = ServiceResponse<B>>,
|
||||
S: Service<Request = ServiceRequest<P>, Response = ServiceResponse<B>>,
|
||||
S::Future: 'static,
|
||||
{
|
||||
type Request = ServiceRequest<State>;
|
||||
type Request = ServiceRequest<P>;
|
||||
type Response = ServiceResponse<B>;
|
||||
type Error = S::Error;
|
||||
type Future = Box<Future<Item = Self::Response, Error = Self::Error>>;
|
||||
|
||||
fn poll_ready(&mut self) -> Poll<(), Self::Error> {
|
||||
Ok(Async::Ready(()))
|
||||
self.service.poll_ready()
|
||||
}
|
||||
|
||||
fn call(&mut self, req: ServiceRequest<State>, srv: &mut S) -> Self::Future {
|
||||
fn call(&mut self, req: ServiceRequest<P>) -> Self::Future {
|
||||
let inner = self.inner.clone();
|
||||
|
||||
Box::new(srv.call(req).map(move |mut res| {
|
||||
Box::new(self.service.call(req).map(move |mut res| {
|
||||
// set response headers
|
||||
for (key, value) in inner.headers.iter() {
|
||||
if !res.headers().contains_key(key) {
|
||||
@ -143,32 +157,44 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_default_headers() {
|
||||
let mut mw = DefaultHeaders::new().header(CONTENT_TYPE, "0001");
|
||||
let mut srv = FnService::new(|req: ServiceRequest<_>| {
|
||||
let srv = FnService::new(|req: ServiceRequest<_>| {
|
||||
req.into_response(HttpResponse::Ok().finish())
|
||||
});
|
||||
let mut mw = block_on(
|
||||
DefaultHeaders::new()
|
||||
.header(CONTENT_TYPE, "0001")
|
||||
.new_transform(srv),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let req = TestRequest::default().to_service();
|
||||
let resp = block_on(mw.call(req, &mut srv)).unwrap();
|
||||
let resp = block_on(mw.call(req)).unwrap();
|
||||
assert_eq!(resp.headers().get(CONTENT_TYPE).unwrap(), "0001");
|
||||
|
||||
let req = TestRequest::default().to_service();
|
||||
let mut srv = FnService::new(|req: ServiceRequest<_>| {
|
||||
let srv = FnService::new(|req: ServiceRequest<_>| {
|
||||
req.into_response(HttpResponse::Ok().header(CONTENT_TYPE, "0002").finish())
|
||||
});
|
||||
let resp = block_on(mw.call(req, &mut srv)).unwrap();
|
||||
let mut mw = block_on(
|
||||
DefaultHeaders::new()
|
||||
.header(CONTENT_TYPE, "0001")
|
||||
.new_transform(srv),
|
||||
)
|
||||
.unwrap();
|
||||
let resp = block_on(mw.call(req)).unwrap();
|
||||
assert_eq!(resp.headers().get(CONTENT_TYPE).unwrap(), "0002");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_content_type() {
|
||||
let mut mw = DefaultHeaders::new().content_type();
|
||||
let mut srv = FnService::new(|req: ServiceRequest<_>| {
|
||||
let srv = FnService::new(|req: ServiceRequest<_>| {
|
||||
req.into_response(HttpResponse::Ok().finish())
|
||||
});
|
||||
let mut mw =
|
||||
block_on(DefaultHeaders::new().content_type().new_transform(srv)).unwrap();
|
||||
|
||||
let req = TestRequest::default().to_service();
|
||||
let resp = block_on(mw.call(req, &mut srv)).unwrap();
|
||||
let resp = block_on(mw.call(req)).unwrap();
|
||||
assert_eq!(
|
||||
resp.headers().get(CONTENT_TYPE).unwrap(),
|
||||
"application/octet-stream"
|
||||
|
@ -1,8 +1,3 @@
|
||||
use std::marker::PhantomData;
|
||||
|
||||
use actix_service::{NewTransform, Service, Transform};
|
||||
use futures::future::{ok, FutureResult};
|
||||
|
||||
#[cfg(any(feature = "brotli", feature = "flate2"))]
|
||||
mod compress;
|
||||
#[cfg(any(feature = "brotli", feature = "flate2"))]
|
||||
@ -10,43 +5,3 @@ pub use self::compress::Compress;
|
||||
|
||||
mod defaultheaders;
|
||||
pub use self::defaultheaders::DefaultHeaders;
|
||||
|
||||
/// Helper for middleware service factory
|
||||
pub struct MiddlewareFactory<T, S>
|
||||
where
|
||||
T: Transform<S> + Clone,
|
||||
S: Service,
|
||||
{
|
||||
tr: T,
|
||||
_t: PhantomData<S>,
|
||||
}
|
||||
|
||||
impl<T, S> MiddlewareFactory<T, S>
|
||||
where
|
||||
T: Transform<S> + Clone,
|
||||
S: Service,
|
||||
{
|
||||
pub fn new(tr: T) -> Self {
|
||||
MiddlewareFactory {
|
||||
tr,
|
||||
_t: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, S, C> NewTransform<S, C> for MiddlewareFactory<T, S>
|
||||
where
|
||||
T: Transform<S> + Clone,
|
||||
S: Service,
|
||||
{
|
||||
type Request = T::Request;
|
||||
type Response = T::Response;
|
||||
type Error = T::Error;
|
||||
type Transform = T;
|
||||
type InitError = ();
|
||||
type Future = FutureResult<Self::Transform, Self::InitError>;
|
||||
|
||||
fn new_transform(&self, _: &C) -> Self::Future {
|
||||
ok(self.tr.clone())
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user