//! Middleware for setting headers on requests and responses. //! //! See [request] and [response] for more details. use http::{header::HeaderName, HeaderMap, HeaderValue, Request, Response}; pub mod request; pub mod response; #[doc(inline)] pub use self::{ request::{SetRequestHeader, SetRequestHeaderLayer}, response::{SetResponseHeader, SetResponseHeaderLayer}, }; /// Trait for producing header values. /// /// Used by [`SetRequestHeader`] and [`SetResponseHeader`]. /// /// This trait is implemented for closures with the correct type signature. Typically users will /// not have to implement this trait for their own types. /// /// It is also implemented directly for [`HeaderValue`]. When a fixed header value should be added /// to all responses, it can be supplied directly to the middleware. pub trait MakeHeaderValue { /// Try to create a header value from the request or response. fn make_header_value(&mut self, message: &T) -> Option; } impl MakeHeaderValue for F where F: FnMut(&T) -> Option, { fn make_header_value(&mut self, message: &T) -> Option { self(message) } } impl MakeHeaderValue for HeaderValue { fn make_header_value(&mut self, _message: &T) -> Option { Some(self.clone()) } } impl MakeHeaderValue for Option { fn make_header_value(&mut self, _message: &T) -> Option { self.clone() } } #[derive(Debug, Clone, Copy)] enum InsertHeaderMode { Override, Append, IfNotPresent, } impl InsertHeaderMode { fn apply(self, header_name: &HeaderName, target: &mut T, make: &mut M) where T: Headers, M: MakeHeaderValue, { match self { InsertHeaderMode::Override => { if let Some(value) = make.make_header_value(target) { target.headers_mut().insert(header_name.clone(), value); } } InsertHeaderMode::IfNotPresent => { if !target.headers().contains_key(header_name) { if let Some(value) = make.make_header_value(target) { target.headers_mut().insert(header_name.clone(), value); } } } InsertHeaderMode::Append => { if let Some(value) = make.make_header_value(target) { target.headers_mut().append(header_name.clone(), value); } } } } } trait Headers { fn headers(&self) -> &HeaderMap; fn headers_mut(&mut self) -> &mut HeaderMap; } impl Headers for Request { fn headers(&self) -> &HeaderMap { Request::headers(self) } fn headers_mut(&mut self) -> &mut HeaderMap { Request::headers_mut(self) } } impl Headers for Response { fn headers(&self) -> &HeaderMap { Response::headers(self) } fn headers_mut(&mut self) -> &mut HeaderMap { Response::headers_mut(self) } }