use reqwest::header::{HeaderMap, HeaderValue};
use crate::runtime::error::Error;
/// Trait for authenticating HTTP requests.
pub trait Authenticator: Send + Sync + std::fmt::Debug {
/// Apply authentication to the given headers.
fn authenticate(&self, headers: &mut HeaderMap) -> Result<(), Error>;
}
/// Bearer token authentication.
#[derive(Debug, Clone)]
pub struct BearerAuth {
token: String,
}
impl BearerAuth {
/// Create a new bearer token authenticator.
pub fn new(token: impl Into<String>) -> Self {
Self {
token: token.into(),
}
}
}
impl Authenticator for BearerAuth {
fn authenticate(&self, headers: &mut HeaderMap) -> Result<(), Error> {
let value = HeaderValue::from_str(&format!("Bearer {}", self.token))
.map_err(|e| Error::Api {
status: reqwest::StatusCode::INTERNAL_SERVER_ERROR,
body: format!("invalid auth header: {e}"),
})?;
headers.insert(reqwest::header::AUTHORIZATION, value);
Ok(())
}
}
/// API key authentication via header.
#[derive(Debug, Clone)]
pub struct ApiKeyAuth {
header_name: String,
api_key: String,
}
impl ApiKeyAuth {
/// Create a new API key authenticator.
pub fn new(header_name: impl Into<String>, api_key: impl Into<String>) -> Self {
Self {
header_name: header_name.into(),
api_key: api_key.into(),
}
}
}
impl Authenticator for ApiKeyAuth {
fn authenticate(&self, headers: &mut HeaderMap) -> Result<(), Error> {
let name = reqwest::header::HeaderName::from_bytes(self.header_name.as_bytes())
.map_err(|e| Error::Api {
status: reqwest::StatusCode::INTERNAL_SERVER_ERROR,
body: format!("invalid header name: {e}"),
})?;
let value = HeaderValue::from_str(&self.api_key).map_err(|e| Error::Api {
status: reqwest::StatusCode::INTERNAL_SERVER_ERROR,
body: format!("invalid header value: {e}"),
})?;
headers.insert(name, value);
Ok(())
}
}