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