Skip to content

Commit

Permalink
feat(client): add default header middleware
Browse files Browse the repository at this point in the history
  • Loading branch information
joelwurtz committed Jan 16, 2025
1 parent 99f7c97 commit f9a7fd5
Show file tree
Hide file tree
Showing 2 changed files with 113 additions and 0 deletions.
111 changes: 111 additions & 0 deletions client/src/middleware/default_headers.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
use std::ops::{Deref, DerefMut};

use crate::{
http::HeaderMap,
service::{Service, ServiceRequest},
};

/// A default header map that can be used to append, replace or set headers if they are unset.
pub enum DefaultHeaderMap {
Append(HeaderMap),
Replace(HeaderMap),
SetIfUnset(HeaderMap),
}

impl DefaultHeaderMap {
pub fn new_append() -> Self {
Self::Append(HeaderMap::new())
}

pub fn new_replace() -> Self {
Self::Replace(HeaderMap::new())
}

pub fn new_set_if_unset() -> Self {
Self::SetIfUnset(HeaderMap::new())
}
}

impl Deref for DefaultHeaderMap {
type Target = HeaderMap;

fn deref(&self) -> &Self::Target {
match self {
Self::Append(headers) => headers,
Self::Replace(headers) => headers,
Self::SetIfUnset(headers) => headers,
}
}
}

impl DerefMut for DefaultHeaderMap {
fn deref_mut(&mut self) -> &mut Self::Target {
match self {
Self::Append(headers) => headers,
Self::Replace(headers) => headers,
Self::SetIfUnset(headers) => headers,
}
}
}

pub struct DefaultHeaders<S> {
service: S,
default_header_map: DefaultHeaderMap,
}

impl<S> DefaultHeaders<S> {
pub fn new(service: S, default_header_map: DefaultHeaderMap) -> Self {
Self {
service,
default_header_map,
}
}
}

impl<'r, 'c, S, Res, Err> Service<ServiceRequest<'r, 'c>> for DefaultHeaders<S>
where
S: for<'r2, 'c2> Service<ServiceRequest<'r2, 'c2>, Response = Res, Error = Err> + Send + Sync,
{
type Response = Res;
type Error = Err;

async fn call(&self, req: ServiceRequest<'r, 'c>) -> Result<Self::Response, Self::Error> {
match &self.default_header_map {
DefaultHeaderMap::Append(headers) => {
for (key, value) in headers {
req.req.headers_mut().append(key, value.clone());
}
}
DefaultHeaderMap::Replace(headers) => {
for (key, value) in headers {
req.req.headers_mut().insert(key, value.clone());
}
}
DefaultHeaderMap::SetIfUnset(headers) => {
for (key, value) in headers {
req.req.headers_mut().entry(key).or_insert(value.clone());
}
}
}

self.service.call(req).await
}
}

#[cfg(test)]
mod test {
use crate::Client;
use xitca_http::http::HeaderValue;

use super::*;

#[tokio::test]
async fn build_default_headers_mw() {
let mut default_headers = DefaultHeaderMap::new_append();
default_headers.insert("content-type", HeaderValue::from_static("application/json"));

let _ = Client::builder()
.middleware(move |x| DefaultHeaders::new(x, default_headers))
.finish();
}
}
2 changes: 2 additions & 0 deletions client/src/middleware/mod.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
//! middleware offer extended functionality to http client.
mod default_headers;
mod redirect;

#[cfg(feature = "compress")]
Expand All @@ -8,4 +9,5 @@ mod decompress;
#[cfg(feature = "compress")]
pub use decompress::Decompress;

pub use default_headers::{DefaultHeaderMap, DefaultHeaders};
pub use redirect::FollowRedirect;

0 comments on commit f9a7fd5

Please sign in to comment.