Skip to main content

alibi_core/middleware/
mod.rs

1pub mod body_limit;
2
3pub mod cors;
4
5pub mod csrf;
6
7pub mod rate_limit;
8
9use crate::error::AuthResult;
10use crate::types::{AuthRequest, AuthResponse};
11use async_trait::async_trait;
12pub use body_limit::{BodyLimitConfig, BodyLimitMiddleware};
13pub use cors::{CorsConfig, CorsMiddleware};
14pub use csrf::{CsrfConfig, CsrfMiddleware};
15pub use rate_limit::{
16    CacheRateLimitStorage, EndpointRateLimit, MemoryRateLimitStorage, PluginRateLimit,
17    RateLimitConfig, RateLimitDecision, RateLimitMiddleware, RateLimitResolver, RateLimitRule,
18    RateLimitStorage,
19};
20
21/// Middleware trait for request/response processing.
22///
23/// Middleware runs before plugin dispatch (`before_request`) and after
24/// a response has been produced (`after_request`).
25#[async_trait]
26pub trait Middleware: Send + Sync {
27    /// Human-readable name for logging / debugging.
28    fn name(&self) -> &'static str;
29
30    /// Called before the request is dispatched to plugins.
31    ///
32    /// Return `Ok(Some(response))` to short-circuit (e.g. block the request).
33    /// Return `Ok(None)` to continue processing.
34    async fn before_request(&self, req: &AuthRequest) -> AuthResult<Option<AuthResponse>>;
35
36    /// Called after a response has been produced.
37    ///
38    /// Allows the middleware to mutate the response (e.g. add CORS headers).
39    /// The default implementation is a no-op pass-through.
40    async fn after_request(
41        &self,
42        _req: &AuthRequest,
43        response: AuthResponse,
44    ) -> AuthResult<AuthResponse> {
45        Ok(response)
46    }
47}
48
49/// Run a middleware chain on a request.
50///
51/// Returns `Ok(Some(response))` if any middleware short-circuits, otherwise `Ok(None)`.
52///
53/// # Errors
54///
55/// Propagates errors returned by a before-request middleware.
56pub async fn run_before(
57    middlewares: &[Box<dyn Middleware>],
58    req: &AuthRequest,
59) -> AuthResult<Option<AuthResponse>> {
60    for mw in middlewares {
61        if let Some(response) = mw.before_request(req).await? {
62            return Ok(Some(response));
63        }
64    }
65    Ok(None)
66}
67
68/// Run the after-request middleware chain, applying each middleware in reverse order.
69///
70/// # Errors
71///
72/// Propagates errors returned by an after-response middleware.
73pub async fn run_after(
74    middlewares: &[Box<dyn Middleware>],
75    req: &AuthRequest,
76    mut response: AuthResponse,
77) -> AuthResult<AuthResponse> {
78    for mw in middlewares.iter().rev() {
79        response = mw.after_request(req, response).await?;
80    }
81    Ok(response)
82}