#[derive(Debug, Clone)]
pub enum ApiKeyLocation {
Header(String),
Query(String),
AuthorizationHeader(String),
}
impl Default for ApiKeyLocation {
fn default() -> Self {
Self::Header("X-API-Key".to_string())
}
}
impl ApiKeyLocation {
pub fn header(name: impl Into<String>) -> Self {
Self::Header(name.into())
}
pub fn query(name: impl Into<String>) -> Self {
Self::Query(name.into())
}
pub fn authorization(scheme: impl Into<String>) -> Self {
Self::AuthorizationHeader(scheme.into())
}
}
#[derive(Debug, Clone)]
pub struct ApiKeyConfig {
locations: Vec<ApiKeyLocation>,
validate_expiration: bool,
validate_enabled: bool,
realm: String,
}
impl Default for ApiKeyConfig {
fn default() -> Self {
Self {
locations: vec![ApiKeyLocation::default()],
validate_expiration: true,
validate_enabled: true,
realm: "API".to_string(),
}
}
}
impl ApiKeyConfig {
pub fn new() -> Self {
Self::default()
}
pub fn header(name: impl Into<String>) -> Self {
Self {
locations: vec![ApiKeyLocation::Header(name.into())],
..Default::default()
}
}
pub fn query(name: impl Into<String>) -> Self {
Self {
locations: vec![ApiKeyLocation::Query(name.into())],
..Default::default()
}
}
pub fn authorization(scheme: impl Into<String>) -> Self {
Self {
locations: vec![ApiKeyLocation::AuthorizationHeader(scheme.into())],
..Default::default()
}
}
pub fn add_location(mut self, location: ApiKeyLocation) -> Self {
self.locations.push(location);
self
}
pub fn locations(mut self, locations: Vec<ApiKeyLocation>) -> Self {
self.locations = locations;
self
}
pub fn validate_expiration(mut self, validate: bool) -> Self {
self.validate_expiration = validate;
self
}
pub fn validate_enabled(mut self, validate: bool) -> Self {
self.validate_enabled = validate;
self
}
pub fn realm(mut self, realm: impl Into<String>) -> Self {
self.realm = realm.into();
self
}
pub fn get_locations(&self) -> &[ApiKeyLocation] {
&self.locations
}
pub fn should_validate_expiration(&self) -> bool {
self.validate_expiration
}
pub fn should_validate_enabled(&self) -> bool {
self.validate_enabled
}
pub fn get_realm(&self) -> &str {
&self.realm
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_default_config() {
let config = ApiKeyConfig::default();
assert_eq!(config.get_locations().len(), 1);
assert!(matches!(
&config.get_locations()[0],
ApiKeyLocation::Header(name) if name == "X-API-Key"
));
assert!(config.should_validate_expiration());
assert!(config.should_validate_enabled());
assert_eq!(config.get_realm(), "API");
}
#[test]
fn test_header_config() {
let config = ApiKeyConfig::header("X-Custom-Key");
assert!(matches!(
&config.get_locations()[0],
ApiKeyLocation::Header(name) if name == "X-Custom-Key"
));
}
#[test]
fn test_query_config() {
let config = ApiKeyConfig::query("api_key");
assert!(matches!(
&config.get_locations()[0],
ApiKeyLocation::Query(name) if name == "api_key"
));
}
#[test]
fn test_authorization_config() {
let config = ApiKeyConfig::authorization("ApiKey");
assert!(matches!(
&config.get_locations()[0],
ApiKeyLocation::AuthorizationHeader(scheme) if scheme == "ApiKey"
));
}
#[test]
fn test_multiple_locations() {
let config = ApiKeyConfig::new().locations(vec![
ApiKeyLocation::header("X-API-Key"),
ApiKeyLocation::query("api_key"),
ApiKeyLocation::authorization("Bearer"),
]);
assert_eq!(config.get_locations().len(), 3);
}
#[test]
fn test_add_location() {
let config =
ApiKeyConfig::header("X-API-Key").add_location(ApiKeyLocation::query("api_key"));
assert_eq!(config.get_locations().len(), 2);
}
}