rama_http/service/web/endpoint/response/
into_response_parts.rs1use super::IntoResponse;
2use crate::{
3 Response, StatusCode,
4 dep::http::Extensions,
5 header::{HeaderMap, HeaderName, HeaderValue},
6};
7use rama_utils::macros::all_the_tuples_no_last_special_case;
8use std::{convert::Infallible, fmt};
9
10pub trait IntoResponseParts {
78 type Error: IntoResponse;
82
83 fn into_response_parts(self, res: ResponseParts) -> Result<ResponseParts, Self::Error>;
85}
86
87impl<T> IntoResponseParts for Option<T>
88where
89 T: IntoResponseParts,
90{
91 type Error = T::Error;
92
93 fn into_response_parts(self, res: ResponseParts) -> Result<ResponseParts, Self::Error> {
94 if let Some(inner) = self {
95 inner.into_response_parts(res)
96 } else {
97 Ok(res)
98 }
99 }
100}
101
102#[derive(Debug)]
106pub struct ResponseParts {
107 pub(crate) res: Response,
108}
109
110impl ResponseParts {
111 pub fn headers(&self) -> &HeaderMap {
113 self.res.headers()
114 }
115
116 pub fn headers_mut(&mut self) -> &mut HeaderMap {
118 self.res.headers_mut()
119 }
120
121 pub fn extensions(&self) -> &Extensions {
123 self.res.extensions()
124 }
125
126 pub fn extensions_mut(&mut self) -> &mut Extensions {
128 self.res.extensions_mut()
129 }
130}
131
132impl IntoResponseParts for HeaderMap {
133 type Error = Infallible;
134
135 fn into_response_parts(self, mut res: ResponseParts) -> Result<ResponseParts, Self::Error> {
136 res.headers_mut().extend(self);
137 Ok(res)
138 }
139}
140
141impl<K, V, const N: usize> IntoResponseParts for [(K, V); N]
142where
143 K: TryInto<HeaderName, Error: fmt::Display>,
144 V: TryInto<HeaderValue, Error: fmt::Display>,
145{
146 type Error = TryIntoHeaderError<K::Error, V::Error>;
147
148 fn into_response_parts(self, mut res: ResponseParts) -> Result<ResponseParts, Self::Error> {
149 for (key, value) in self {
150 let key = key.try_into().map_err(TryIntoHeaderError::key)?;
151 let value = value.try_into().map_err(TryIntoHeaderError::value)?;
152 res.headers_mut().insert(key, value);
153 }
154
155 Ok(res)
156 }
157}
158
159pub struct TryIntoHeaderError<K, V> {
161 kind: TryIntoHeaderErrorKind<K, V>,
162}
163
164impl<K: fmt::Debug, V: fmt::Debug> fmt::Debug for TryIntoHeaderError<K, V> {
165 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
166 f.debug_struct("TryIntoHeaderError")
167 .field("kind", &self.kind)
168 .finish()
169 }
170}
171
172impl<K, V> TryIntoHeaderError<K, V> {
173 pub(super) fn key(err: K) -> Self {
174 Self {
175 kind: TryIntoHeaderErrorKind::Key(err),
176 }
177 }
178
179 pub(super) fn value(err: V) -> Self {
180 Self {
181 kind: TryIntoHeaderErrorKind::Value(err),
182 }
183 }
184}
185
186enum TryIntoHeaderErrorKind<K, V> {
187 Key(K),
188 Value(V),
189}
190
191impl<K: fmt::Debug, V: fmt::Debug> fmt::Debug for TryIntoHeaderErrorKind<K, V> {
192 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
193 match self {
194 Self::Key(key) => write!(f, "TryIntoHeaderErrorKind::Key({key:?})"),
195 Self::Value(value) => write!(f, "TryIntoHeaderErrorKind::Value({value:?})"),
196 }
197 }
198}
199
200impl<K, V> IntoResponse for TryIntoHeaderError<K, V>
201where
202 K: fmt::Display,
203 V: fmt::Display,
204{
205 fn into_response(self) -> Response {
206 match self.kind {
207 TryIntoHeaderErrorKind::Key(inner) => {
208 (StatusCode::INTERNAL_SERVER_ERROR, inner.to_string()).into_response()
209 }
210 TryIntoHeaderErrorKind::Value(inner) => {
211 (StatusCode::INTERNAL_SERVER_ERROR, inner.to_string()).into_response()
212 }
213 }
214 }
215}
216
217impl<K, V> fmt::Display for TryIntoHeaderError<K, V> {
218 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
219 match self.kind {
220 TryIntoHeaderErrorKind::Key(_) => write!(f, "failed to convert key to a header name"),
221 TryIntoHeaderErrorKind::Value(_) => {
222 write!(f, "failed to convert value to a header value")
223 }
224 }
225 }
226}
227
228impl<K, V> std::error::Error for TryIntoHeaderError<K, V>
229where
230 K: std::error::Error + 'static,
231 V: std::error::Error + 'static,
232{
233 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
234 match &self.kind {
235 TryIntoHeaderErrorKind::Key(inner) => Some(inner),
236 TryIntoHeaderErrorKind::Value(inner) => Some(inner),
237 }
238 }
239}
240
241macro_rules! impl_into_response_parts {
242 ( $($ty:ident),* $(,)? ) => {
243 #[allow(non_snake_case)]
244 impl<$($ty,)*> IntoResponseParts for ($($ty,)*)
245 where
246 $( $ty: IntoResponseParts, )*
247 {
248 type Error = Response;
249
250 fn into_response_parts(self, res: ResponseParts) -> Result<ResponseParts, Self::Error> {
251 let ($($ty,)*) = self;
252
253 $(
254 let res = match $ty.into_response_parts(res) {
255 Ok(res) => res,
256 Err(err) => {
257 return Err(err.into_response());
258 }
259 };
260 )*
261
262 Ok(res)
263 }
264 }
265 }
266}
267
268all_the_tuples_no_last_special_case!(impl_into_response_parts);
269
270impl IntoResponseParts for Extensions {
271 type Error = Infallible;
272
273 fn into_response_parts(self, mut res: ResponseParts) -> Result<ResponseParts, Self::Error> {
274 res.extensions_mut().extend(self);
275 Ok(res)
276 }
277}