use actix_service::{Service as ActixService, Transform};
use actix_web::{
dev::{ServiceRequest, ServiceResponse},
Error,
};
use futures_util::future::Ready;
use http_body::Body as HttpBody;
use tower_layer::Layer as TowerLayerTrait;
use tower_service::Service as TowerService;
use crate::compat::tower::{
body::ActixRequestBody,
request::DEFAULT_MAX_BODY_BYTES,
service::{ActixServiceWrapper, TowerMiddlewareService},
};
pub struct TowerLayer<L> {
pub(crate) layer: L,
max_body_bytes: usize,
}
impl<L> TowerLayer<L> {
pub fn new(layer: L) -> Self {
Self {
layer,
max_body_bytes: DEFAULT_MAX_BODY_BYTES,
}
}
pub fn with_max_body_bytes(mut self, limit: usize) -> Self {
self.max_body_bytes = limit;
self
}
}
impl<L> Clone for TowerLayer<L>
where
L: Clone,
{
fn clone(&self) -> Self {
Self {
layer: self.layer.clone(),
max_body_bytes: self.max_body_bytes,
}
}
}
impl<S, L, B, E> Transform<S, ServiceRequest> for TowerLayer<L>
where
S: ActixService<ServiceRequest, Response = ServiceResponse, Error = Error> + 'static,
S::Future: 'static,
L: TowerLayerTrait<ActixServiceWrapper<S>> + 'static,
L::Service: TowerService<http::Request<ActixRequestBody>, Response = http::Response<B>, Error = E>
+ 'static,
<L::Service as TowerService<http::Request<ActixRequestBody>>>::Future: 'static,
B: HttpBody<Data = actix_web::web::Bytes> + 'static,
B::Error: std::fmt::Display + 'static,
E: Into<crate::internal::common::BoxError> + 'static,
{
type Response = ServiceResponse;
type Error = Error;
type Transform = TowerMiddlewareService<L::Service>;
type InitError = ();
type Future = Ready<Result<Self::Transform, Self::InitError>>;
fn new_transform(&self, service: S) -> Self::Future {
let wrapper = ActixServiceWrapper::new(service, self.max_body_bytes);
let tower_service = self.layer.layer(wrapper);
let transform = TowerMiddlewareService::new(tower_service, self.max_body_bytes);
futures_util::future::ready(Ok(transform))
}
}
pub type TowerLayerCompat<L> = TowerLayer<L>;