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, Clone, Copy)] #[must_use] pub struct AppendHeaders(pub I); impl IntoResponse for AppendHeaders where I: IntoIterator, K: TryInto, K::Error: fmt::Display, V: TryInto, V::Error: fmt::Display, { fn into_response(self) -> Response { (self, ()).into_response() } } impl IntoResponseParts for AppendHeaders where I: IntoIterator, K: TryInto, K::Error: fmt::Display, V: TryInto, V::Error: fmt::Display, { type Error = TryIntoHeaderError; fn into_response_parts(self, mut res: ResponseParts) -> Result { 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) } }