1
0
mirror of https://github.com/actix/actix-extras.git synced 2024-11-24 07:53:00 +01:00

update middleware impl

This commit is contained in:
Nikolay Kim 2019-03-04 21:37:57 -08:00
parent 2e79562c9d
commit b6fe1dacf2
7 changed files with 102 additions and 103 deletions

View File

@ -56,8 +56,8 @@ ssl = ["openssl", "actix-server/ssl"]
[dependencies]
actix-codec = "0.1.0"
actix-service = "0.3.0"
actix-utils = "0.3.0"
actix-service = "0.3.2"
actix-utils = "0.3.1"
actix-rt = "0.1.0"
actix-http = { git = "https://github.com/actix/actix-http.git" }
@ -99,3 +99,6 @@ serde_derive = "1.0"
lto = true
opt-level = 3
codegen-units = 1
[patch.crates-io]
actix-service = { git = "https://github.com/actix/actix-net.git" }

View File

@ -7,8 +7,8 @@ use actix_http::{Extensions, PayloadStream, Request, Response};
use actix_router::{Path, ResourceDef, ResourceInfo, Router, Url};
use actix_service::boxed::{self, BoxedNewService, BoxedService};
use actix_service::{
AndThenNewService, ApplyNewService, IntoNewService, IntoNewTransform, NewService,
NewTransform, Service,
AndThenNewService, ApplyTransform, IntoNewService, IntoTransform, NewService,
Service, Transform,
};
use futures::future::{ok, Either, FutureResult};
use futures::{Async, Future, IntoFuture, Poll};
@ -237,17 +237,17 @@ where
>,
>
where
M: NewTransform<
M: Transform<
AppRouting<P>,
Request = ServiceRequest<P>,
Response = ServiceResponse<B>,
Error = (),
InitError = (),
>,
F: IntoNewTransform<M, AppRouting<P>>,
F: IntoTransform<M, AppRouting<P>>,
{
let fref = Rc::new(RefCell::new(None));
let endpoint = ApplyNewService::new(mw, AppEntry::new(fref.clone()));
let endpoint = ApplyTransform::new(mw, AppEntry::new(fref.clone()));
AppRouter {
endpoint,
chain: self.chain,
@ -480,7 +480,7 @@ where
>,
>
where
M: NewTransform<
M: Transform<
T::Service,
Request = ServiceRequest<P>,
Response = ServiceResponse<B1>,
@ -488,9 +488,9 @@ where
InitError = (),
>,
B1: MessageBody,
F: IntoNewTransform<M, T::Service>,
F: IntoTransform<M, T::Service>,
{
let endpoint = ApplyNewService::new(mw, self.endpoint);
let endpoint = ApplyTransform::new(mw, self.endpoint);
AppRouter {
endpoint,
chain: self.chain,

View File

@ -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>),

View File

@ -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"

View File

@ -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())
}
}

View File

@ -4,7 +4,7 @@ use std::rc::Rc;
use actix_http::{Error, Response};
use actix_service::boxed::{self, BoxedNewService, BoxedService};
use actix_service::{
ApplyNewService, IntoNewService, IntoNewTransform, NewService, NewTransform, Service,
ApplyTransform, IntoNewService, IntoTransform, NewService, Service, Transform,
};
use futures::future::{ok, Either, FutureResult};
use futures::{Async, Future, IntoFuture, Poll};
@ -194,16 +194,16 @@ where
>,
>
where
M: NewTransform<
M: Transform<
T::Service,
Request = ServiceRequest<P>,
Response = ServiceResponse,
Error = (),
InitError = (),
>,
F: IntoNewTransform<M, T::Service>,
F: IntoTransform<M, T::Service>,
{
let endpoint = ApplyNewService::new(mw, self.endpoint);
let endpoint = ApplyTransform::new(mw, self.endpoint);
Resource {
endpoint,
routes: self.routes,

View File

@ -5,7 +5,7 @@ use actix_http::Response;
use actix_router::{ResourceDef, ResourceInfo, Router};
use actix_service::boxed::{self, BoxedNewService, BoxedService};
use actix_service::{
ApplyNewService, IntoNewService, IntoNewTransform, NewService, NewTransform, Service,
ApplyTransform, IntoNewService, IntoTransform, NewService, Service, Transform,
};
use futures::future::{ok, Either, Future, FutureResult};
use futures::{Async, Poll};
@ -251,16 +251,16 @@ where
>,
>
where
M: NewTransform<
M: Transform<
T::Service,
Request = ServiceRequest<P>,
Response = ServiceResponse,
Error = (),
InitError = (),
>,
F: IntoNewTransform<M, T::Service>,
F: IntoTransform<M, T::Service>,
{
let endpoint = ApplyNewService::new(mw, self.endpoint);
let endpoint = ApplyTransform::new(mw, self.endpoint);
Scope {
endpoint,
rdef: self.rdef,