use anyhow::Context;
use async_trait::async_trait;
use http::Extensions;
use reqwest::{Request, Response};
use reqwest_middleware::{ClientWithMiddleware, Middleware, Next, Result};
use crate::AuthHeaderManager;
pub struct AuthenticatorMiddleware {
authenticator: AuthHeaderManager,
}
#[derive(Clone)]
struct AuthenticatorFlag;
#[derive(Clone)]
pub struct SkipAuthentication;
impl AuthenticatorMiddleware {
pub fn new(authenticator: AuthHeaderManager) -> crate::Result<Self> {
Ok(Self { authenticator })
}
}
#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
impl Middleware for AuthenticatorMiddleware {
async fn handle(
&self,
mut req: Request,
extensions: &mut Extensions,
next: Next<'_>,
) -> Result<Response> {
if extensions.get::<AuthenticatorFlag>().is_none()
&& extensions.get::<SkipAuthentication>().is_none()
{
extensions.insert(AuthenticatorFlag);
if let Some(client) = extensions.get::<ClientWithMiddleware>() {
self.authenticator
.set_headers(req.headers_mut(), client)
.await
.map_err(|e| reqwest_middleware::Error::Middleware(e.into()))
.context("Failed to authenticate request")?;
}
extensions.remove::<AuthenticatorFlag>();
}
next.run(req, extensions).await
}
}