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