Middleware
Middleware
Rusta supports both per-handler and global middleware.
Per-Handler Middleware
Attach middleware to individual handlers using the #[middleware] attribute:
use rusta::prelude::*;
pub async fn auth_guard( State(container): State<ContainerRef>, mut request: Request, next: Next,) -> Response { let auth_header = request.headers().get("Authorization"); // ... validate token ... request.extensions_mut().insert(claims); next.run(request).await}
#[controller("/posts")]impl PostController { #[get("/:id")] #[middleware(auth_guard)] pub async fn get_post(&self, Path(id): Path<String>) -> Response { Http::json(self.svc.find(&id).await) }}Global Middleware Chain
Apply middleware to all routes:
use rusta::{App, MiddlewareChain, Request, Next, Response};
async fn request_id_middleware(request: Request, next: Next) -> Response { let id = uuid::Uuid::new_v4().to_string(); request.extensions_mut().insert(id.clone()); let mut response = next.run(request).await; response.headers_mut().insert("X-Request-ID", id.parse().unwrap()); response}
let middleware = MiddlewareChain::new() .chain(request_id_middleware) .chain(apm_middleware) .chain(logger_middleware);
App::new() .container(container) .middleware(middleware) .run("0.0.0.0:3000", |res| match res { Ok(addr) => println!("Listening on {}", addr), Err(msg) => eprintln!("Startup error: {}", msg), }) .await;Tower Layers
Add tower-http layers (compression, tracing, etc.):
use rusta::MiddlewareChain;use tower_http::{ compression::CompressionLayer, trace::TraceLayer, timeout::TimeoutLayer,};
let middleware = MiddlewareChain::new() .add_layer(CompressionLayer::new()) .add_layer(TraceLayer::new_for_http()) .add_layer(TimeoutLayer::new(Duration::from_secs(30)));Middleware Ordering
Layers are applied in registration order:
// First added = innermost (closest to handler)// Last added = outermost (first to see request)let middleware = MiddlewareChain::new() .chain(auth_guard) // Runs first on request, last on response .chain(logger_middleware) .add_layer(TraceLayer::new_for_http()); // Runs last on request, first on responseAccessing Container in Middleware
Use State<ContainerRef> to resolve services:
async fn auth_middleware( State(container): State<ContainerRef>, request: Request, next: Next,) -> Response { let auth_svc: Arc<AuthService> = container.resolve(); // ...}Built-in Middleware
CORS
use rusta::CorsConfig;
let cors = CorsConfig::builder() .allow_origins(vec!["https://app.example.com".to_string()]) .allow_methods(vec!["GET".to_string(), "POST".to_string()]) .allow_headers(vec!["content-type".to_string()]) .max_age(3600) .build();
App::new().cors(cors).await;APM Middleware
use rusta_apm::apm_middleware;
let middleware = MiddlewareChain::new() .chain(apm_middleware);Logger Middleware
use rusta_logger::logger_middleware;
let middleware = MiddlewareChain::new() .chain(logger_middleware);