Module map_response_body

Source
Available on crate feature map-response-body only.
Expand description

Apply a transformation to the response body.

§Example

use bytes::Bytes;
use http::{Request, Response};
use http_body::{Body, Frame};
use http_body_util::Full;
use std::convert::Infallible;
use std::{pin::Pin, task::{Context, Poll}};
use tower_async::{ServiceBuilder, service_fn, ServiceExt, Service, BoxError};
use tower_async_http::map_response_body::MapResponseBodyLayer;
use futures::ready;

// A wrapper for a `http_body::Body` that prints the size of data chunks
pin_project_lite::pin_project! {
    struct PrintChunkSizesBody<B> {
        #[pin]
        inner: B,
    }
}

impl<B> PrintChunkSizesBody<B> {
    fn new(inner: B) -> Self {
        Self { inner }
    }
}

impl<B> Body for PrintChunkSizesBody<B>
    where B: Body<Data = Bytes, Error = BoxError>,
{
    type Data = Bytes;
    type Error = BoxError;

    fn poll_frame(
        mut self: Pin<&mut Self>,
        cx: &mut Context<'_>,
    ) -> Poll<Option<Result<Frame<Self::Data>, Self::Error>>> {
        let inner_body = self.as_mut().project().inner;
        if let Some(frame) = ready!(inner_body.poll_frame(cx)?) {
            if let Some(chunk) = frame.data_ref() {
                println!("chunk size = {}", chunk.len());
            } else {
                eprintln!("no data chunk found");
            }
            Poll::Ready(Some(Ok(frame)))
        } else {
            Poll::Ready(None)
        }
    }

    fn is_end_stream(&self) -> bool {
        self.inner.is_end_stream()
    }

    fn size_hint(&self) -> http_body::SizeHint {
        self.inner.size_hint()
    }
}

async fn handle(_: Request<Full<Bytes>>) -> Result<Response<Full<Bytes>>, Infallible> {
    // ...
}

let mut svc = ServiceBuilder::new()
    // Wrap response bodies in `PrintChunkSizesBody`
    .layer(MapResponseBodyLayer::new(PrintChunkSizesBody::new))
    .service_fn(handle);

// Call the service
let request = Request::new(Full::from("foobar"));

svc.call(request).await?;

Structs§

MapResponseBody
Apply a transformation to the response body.
MapResponseBodyLayer
Apply a transformation to the response body.