1 use super::{IntoResponse, IntoResponseParts, Response, ResponseParts, TryIntoHeaderError};
2 use http::header::{HeaderName, HeaderValue};
3 use std::fmt;
4 
5 /// Append headers to a response.
6 ///
7 /// Returning something like `[("content-type", "foo=bar")]` from a handler will override any
8 /// existing `content-type` headers. If instead you want to append headers, use `AppendHeaders`:
9 ///
10 /// ```rust
11 /// use axum::{
12 ///     response::{AppendHeaders, IntoResponse},
13 ///     http::header::SET_COOKIE,
14 /// };
15 ///
16 /// async fn handler() -> impl IntoResponse {
17 ///     // something that sets the `set-cookie` header
18 ///     let set_some_cookies = /* ... */
19 ///     # axum::http::HeaderMap::new();
20 ///
21 ///     (
22 ///         set_some_cookies,
23 ///         // append two `set-cookie` headers to the response
24 ///         // without overriding the ones added by `set_some_cookies`
25 ///         AppendHeaders([
26 ///             (SET_COOKIE, "foo=bar"),
27 ///             (SET_COOKIE, "baz=qux"),
28 ///         ])
29 ///     )
30 /// }
31 /// ```
32 #[derive(Debug)]
33 #[must_use]
34 pub struct AppendHeaders<I>(pub I);
35 
36 impl<I, K, V> IntoResponse for AppendHeaders<I>
37 where
38     I: IntoIterator<Item = (K, V)>,
39     K: TryInto<HeaderName>,
40     K::Error: fmt::Display,
41     V: TryInto<HeaderValue>,
42     V::Error: fmt::Display,
43 {
into_response(self) -> Response44     fn into_response(self) -> Response {
45         (self, ()).into_response()
46     }
47 }
48 
49 impl<I, K, V> IntoResponseParts for AppendHeaders<I>
50 where
51     I: IntoIterator<Item = (K, V)>,
52     K: TryInto<HeaderName>,
53     K::Error: fmt::Display,
54     V: TryInto<HeaderValue>,
55     V::Error: fmt::Display,
56 {
57     type Error = TryIntoHeaderError<K::Error, V::Error>;
58 
into_response_parts(self, mut res: ResponseParts) -> Result<ResponseParts, Self::Error>59     fn into_response_parts(self, mut res: ResponseParts) -> Result<ResponseParts, Self::Error> {
60         for (key, value) in self.0 {
61             let key = key.try_into().map_err(TryIntoHeaderError::key)?;
62             let value = value.try_into().map_err(TryIntoHeaderError::value)?;
63             res.headers_mut().append(key, value);
64         }
65 
66         Ok(res)
67     }
68 }
69