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}