Skip to main content

rama_http/layer/
map_request_body.rs

1//! Apply a transformation to the request body.
2//!
3//! # Example
4//!
5//! ```
6//! use rama_http::{Body, Request, Response, StreamingBody, body::{Frame, SizeHint}};
7//! use rama_core::bytes::Bytes;
8//! use std::convert::Infallible;
9//! use std::{pin::Pin, task::{ready, Context, Poll}};
10//! use rama_core::{Layer, Service};
11//! use rama_core::service::service_fn;
12//! use rama_http::layer::map_request_body::MapRequestBodyLayer;
13//! use rama_core::error::BoxError;
14//!
15//! // A wrapper for a `Full<Bytes>`
16//! struct BodyWrapper {
17//!     inner: Body,
18//! }
19//!
20//! impl BodyWrapper {
21//!     fn new(inner: Body) -> Self {
22//!         Self { inner }
23//!     }
24//! }
25//!
26//! impl StreamingBody for BodyWrapper {
27//!     // ...
28//!     # type Data = Bytes;
29//!     # type Error = BoxError;
30//!     # fn poll_frame(
31//!     #     self: Pin<&mut Self>,
32//!     #     cx: &mut Context<'_>
33//!     # ) -> Poll<Option<Result<Frame<Self::Data>, Self::Error>>> { unimplemented!() }
34//!     # fn is_end_stream(&self) -> bool { unimplemented!() }
35//!     # fn size_hint(&self) -> SizeHint { unimplemented!() }
36//! }
37//!
38//! async fn handle<B>(_: Request<B>) -> Result<Response, Infallible> {
39//!     // ...
40//!     # Ok(Response::new(Body::default()))
41//! }
42//!
43//! # #[tokio::main]
44//! # async fn main() -> Result<(), Box<dyn std::error::Error>> {
45//! let mut svc = (
46//!     // Wrap response bodies in `BodyWrapper`
47//!     MapRequestBodyLayer::new(BodyWrapper::new),
48//! ).into_layer(service_fn(handle));
49//!
50//! // Call the service
51//! let request = Request::new(Body::default());
52//!
53//! svc.serve(request).await?;
54//! # Ok(())
55//! # }
56//! ```
57
58use crate::{Request, Response};
59use rama_core::{Layer, Service, bytes::Bytes, error::BoxError};
60use rama_http_types::StreamingBody;
61use rama_utils::macros::define_inner_service_accessors;
62use std::fmt;
63
64/// Apply a transformation to the request body.
65///
66/// See the [module docs](crate::layer::map_request_body) for an example.
67#[derive(Clone)]
68pub struct MapRequestBodyLayer<F> {
69    f: F,
70}
71
72impl<F> MapRequestBodyLayer<F> {
73    /// Create a new [`MapRequestBodyLayer`].
74    ///
75    /// `F` is expected to be a function that takes a body and returns another body.
76    pub const fn new(f: F) -> Self {
77        Self { f }
78    }
79}
80
81impl<Body> MapRequestBodyLayer<fn(Body) -> crate::Body>
82where
83    Body: StreamingBody<Data = Bytes, Error: Into<BoxError>> + Send + Sync + 'static,
84{
85    /// Turn the [`StreamingBody`] into a [`crate::Body`] using [`crate::Body::new`].
86    ///
87    /// This is shorthand for `MapRequestBodyLayer::new(Body::new)`.
88    pub const fn new_boxed_streaming_body() -> Self {
89        Self::new(crate::Body::new)
90    }
91}
92
93impl<Body> MapRequestBodyLayer<fn(Body) -> crate::Body>
94where
95    crate::Body: From<Body>,
96{
97    /// Turn the body into a [`crate::Body`] using [`crate::Body::from`].
98    ///
99    /// This is shorthand for `MapRequestBodyLayer::new(Body::from)`.
100    pub const fn into_boxed_streaming_body() -> Self {
101        Self::new(crate::Body::from)
102    }
103}
104
105impl<S, F> Layer<S> for MapRequestBodyLayer<F>
106where
107    F: Clone,
108{
109    type Service = MapRequestBody<S, F>;
110
111    fn layer(&self, inner: S) -> Self::Service {
112        MapRequestBody::new(inner, self.f.clone())
113    }
114
115    fn into_layer(self, inner: S) -> Self::Service {
116        MapRequestBody::new(inner, self.f)
117    }
118}
119
120impl<F> fmt::Debug for MapRequestBodyLayer<F> {
121    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
122        f.debug_struct("MapRequestBodyLayer")
123            .field("f", &std::any::type_name::<F>())
124            .finish()
125    }
126}
127
128/// Apply a transformation to the request body.
129///
130/// See the [module docs](crate::layer::map_request_body) for an example.
131#[derive(Clone)]
132pub struct MapRequestBody<S, F> {
133    inner: S,
134    f: F,
135}
136
137impl<S, F> MapRequestBody<S, F> {
138    /// Create a new [`MapRequestBody`].
139    ///
140    /// `F` is expected to be a function that takes a body and returns another body.
141    pub const fn new(service: S, f: F) -> Self {
142        Self { inner: service, f }
143    }
144
145    define_inner_service_accessors!();
146}
147
148impl<S, Body> MapRequestBody<S, fn(Body) -> crate::Body>
149where
150    Body: StreamingBody<Data = Bytes, Error: Into<BoxError>> + Send + Sync + 'static,
151{
152    /// Turn the [`StreamingBody`] into a [`crate::Body`] using [`crate::Body::new`].
153    ///
154    /// This is shorthand for `MapRequestBody::new(..., Body::new)`.
155    pub const fn new_boxed_streaming_body(inner: S) -> Self {
156        Self::new(inner, crate::Body::new)
157    }
158}
159
160impl<S, Body> MapRequestBody<S, fn(Body) -> crate::Body>
161where
162    crate::Body: From<Body>,
163{
164    /// Turn the body into a [`crate::Body`] using [`crate::Body::from`].
165    ///
166    /// This is shorthand for `MapRequestBody::new(..., Body::from)`.
167    pub const fn into_boxed_streaming_body(inner: S) -> Self {
168        Self::new(inner, crate::Body::from)
169    }
170}
171
172impl<F, S, ReqBody, ResBody, NewReqBody> Service<Request<ReqBody>> for MapRequestBody<S, F>
173where
174    S: Service<Request<NewReqBody>, Output = Response<ResBody>>,
175    ReqBody: Send + 'static,
176    NewReqBody: Send + 'static,
177    ResBody: Send + Sync + 'static,
178    F: Fn(ReqBody) -> NewReqBody + Send + Sync + 'static,
179{
180    type Output = S::Output;
181    type Error = S::Error;
182
183    async fn serve(&self, req: Request<ReqBody>) -> Result<Self::Output, Self::Error> {
184        let req = req.map(&self.f);
185        self.inner.serve(req).await
186    }
187}
188
189impl<S, F> fmt::Debug for MapRequestBody<S, F>
190where
191    S: fmt::Debug,
192{
193    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
194        f.debug_struct("MapRequestBody")
195            .field("inner", &self.inner)
196            .field("f", &std::any::type_name::<F>())
197            .finish()
198    }
199}