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