76 lines
2.5 KiB
Rust
76 lines
2.5 KiB
Rust
//! API Key authentication middleware.
|
|
//!
|
|
//! Validates requests by checking for a valid API key in the X-API-Key header.
|
|
|
|
use crate::{
|
|
Responder,
|
|
middleware::{Middleware, MiddlewareFuture, MiddlewareResult},
|
|
};
|
|
use http::{Request, Response};
|
|
use hyper::body::{Bytes, Incoming};
|
|
use log::warn;
|
|
|
|
/// Middleware that validates API key authentication via X-API-Key header.
|
|
pub struct ApiKeyMiddleware {
|
|
api_key: String,
|
|
}
|
|
|
|
impl ApiKeyMiddleware {
|
|
/// Creates a new ApiKeyMiddleware with the specified expected API key.
|
|
pub fn new(api_key: &str) -> Self {
|
|
Self {
|
|
api_key: api_key.to_string(),
|
|
}
|
|
}
|
|
|
|
/// Checks if the given API key is invalid.
|
|
pub fn is_invalid_key(&self, key: &str) -> bool {
|
|
key != self.api_key
|
|
}
|
|
}
|
|
|
|
impl Middleware for ApiKeyMiddleware {
|
|
fn run(&self, req: Request<Incoming>) -> MiddlewareFuture<'_> {
|
|
Box::pin(async move {
|
|
match req.headers().get("X-API-Key") {
|
|
Some(header) => {
|
|
if header == self.api_key.as_str() {
|
|
MiddlewareResult::Continue(req)
|
|
} else {
|
|
warn!("X-API-Key validation failed for request");
|
|
let response = Responder::unauthorized().unwrap_or_else(|_| {
|
|
Response::builder()
|
|
.status(http::StatusCode::UNAUTHORIZED)
|
|
.body(http_body_util::Full::new(Bytes::from("Unauthorized")))
|
|
.expect("Failed to build fallback response")
|
|
});
|
|
MiddlewareResult::Respond(response)
|
|
}
|
|
}
|
|
None => {
|
|
warn!("X-API-Key header missing from request");
|
|
let response = Responder::unauthorized().unwrap_or_else(|_| {
|
|
Response::builder()
|
|
.status(http::StatusCode::UNAUTHORIZED)
|
|
.body(http_body_util::Full::new(Bytes::from("Unauthorized")))
|
|
.expect("Failed to build fallback response")
|
|
});
|
|
MiddlewareResult::Respond(response)
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
|
|
#[test]
|
|
fn test_api_key_middleware_new() {
|
|
let middleware = ApiKeyMiddleware::new("test-key");
|
|
assert!(!middleware.is_invalid_key("test-key"));
|
|
assert!(middleware.is_invalid_key("wrong-key"));
|
|
}
|
|
}
|