mirror of
https://github.com/actix/actix-extras.git
synced 2024-11-23 23:51:06 +01:00
update middleware impl
This commit is contained in:
parent
2e79562c9d
commit
b6fe1dacf2
@ -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" }
|
||||
|
16
src/app.rs
16
src/app.rs
@ -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,
|
||||
|
@ -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())
|
||||
}
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
Loading…
Reference in New Issue
Block a user