//! Apply a transformation to the response body. //! //! # Example //! //! ``` //! use bytes::Bytes; //! use http::{Request, Response}; //! use http_body_util::Full; //! use std::convert::Infallible; //! use std::{pin::Pin, task::{ready, Context, Poll}}; //! use tower::{ServiceBuilder, service_fn, ServiceExt, Service}; //! use tower_http::map_response_body::MapResponseBodyLayer; //! //! // A wrapper for a `Full` //! struct BodyWrapper { //! inner: Full, //! } //! //! impl BodyWrapper { //! fn new(inner: Full) -> Self { //! Self { inner } //! } //! } //! //! impl http_body::Body for BodyWrapper { //! // ... //! # type Data = Bytes; //! # type Error = tower::BoxError; //! # fn poll_frame( //! # self: Pin<&mut Self>, //! # cx: &mut Context<'_> //! # ) -> Poll, Self::Error>>> { unimplemented!() } //! # fn is_end_stream(&self) -> bool { unimplemented!() } //! # fn size_hint(&self) -> http_body::SizeHint { unimplemented!() } //! } //! //! async fn handle(_: Request) -> Result>, Infallible> { //! // ... //! # Ok(Response::new(Full::default())) //! } //! //! # #[tokio::main] //! # async fn main() -> Result<(), Box> { //! let mut svc = ServiceBuilder::new() //! // Wrap response bodies in `BodyWrapper` //! .layer(MapResponseBodyLayer::new(BodyWrapper::new)) //! .service_fn(handle); //! //! // Call the service //! let request = Request::new(Full::::from("foobar")); //! //! svc.ready().await?.call(request).await?; //! # Ok(()) //! # } //! ``` use http::{Request, Response}; use pin_project_lite::pin_project; use std::future::Future; use std::{ fmt, pin::Pin, task::{ready, Context, Poll}, }; use tower_layer::Layer; use tower_service::Service; /// Apply a transformation to the response body. /// /// See the [module docs](crate::map_response_body) for an example. #[derive(Clone)] pub struct MapResponseBodyLayer { f: F, } impl MapResponseBodyLayer { /// Create a new [`MapResponseBodyLayer`]. /// /// `F` is expected to be a function that takes a body and returns another body. pub fn new(f: F) -> Self { Self { f } } } impl Layer for MapResponseBodyLayer where F: Clone, { type Service = MapResponseBody; fn layer(&self, inner: S) -> Self::Service { MapResponseBody::new(inner, self.f.clone()) } } impl fmt::Debug for MapResponseBodyLayer { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("MapResponseBodyLayer") .field("f", &std::any::type_name::()) .finish() } } /// Apply a transformation to the response body. /// /// See the [module docs](crate::map_response_body) for an example. #[derive(Clone)] pub struct MapResponseBody { inner: S, f: F, } impl MapResponseBody { /// Create a new [`MapResponseBody`]. /// /// `F` is expected to be a function that takes a body and returns another body. pub fn new(service: S, f: F) -> Self { Self { inner: service, f } } /// Returns a new [`Layer`] that wraps services with a `MapResponseBodyLayer` middleware. /// /// [`Layer`]: tower_layer::Layer pub fn layer(f: F) -> MapResponseBodyLayer { MapResponseBodyLayer::new(f) } define_inner_service_accessors!(); } impl Service> for MapResponseBody where S: Service, Response = Response>, F: FnMut(ResBody) -> NewResBody + Clone, { type Response = Response; type Error = S::Error; type Future = ResponseFuture; fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll> { self.inner.poll_ready(cx) } fn call(&mut self, req: Request) -> Self::Future { ResponseFuture { inner: self.inner.call(req), f: self.f.clone(), } } } impl fmt::Debug for MapResponseBody where S: fmt::Debug, { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("MapResponseBody") .field("inner", &self.inner) .field("f", &std::any::type_name::()) .finish() } } pin_project! { /// Response future for [`MapResponseBody`]. pub struct ResponseFuture { #[pin] inner: Fut, f: F, } } impl Future for ResponseFuture where Fut: Future, E>>, F: FnMut(ResBody) -> NewResBody, { type Output = Result, E>; fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { let this = self.project(); let res = ready!(this.inner.poll(cx)?); Poll::Ready(Ok(res.map(this.f))) } }