use std::time::Duration;
use rapina::middleware::{
BoxFuture, CompressionConfig, CorsConfig, RequestLogConfig, TimeoutMiddleware,
TraceIdMiddleware,
};
use rapina::prelude::*;
use rapina::response::BoxBody;
struct RequestTimerMiddleware;
impl Middleware for RequestTimerMiddleware {
fn handle<'a>(
&'a self,
req: hyper::Request<hyper::body::Incoming>,
ctx: &'a RequestContext,
next: Next<'a>,
) -> BoxFuture<'a, hyper::Response<BoxBody>> {
Box::pin(async move {
let mut response = next.run(req).await;
let duration_ms = ctx.elapsed().as_millis();
response.headers_mut().insert(
"x-request-duration-ms",
http::HeaderValue::from_str(&duration_ms.to_string()).unwrap(),
);
response
})
}
}
#[get("/")]
async fn hello() -> &'static str {
"Hello from the middleware example!"
}
#[get("/data")]
async fn data() -> Json<serde_json::Value> {
let items: Vec<serde_json::Value> = (1..=50)
.map(|i| {
serde_json::json!({
"id": i,
"name": format!("Item {}", i),
"description": format!("This is item number {} in our dataset", i),
})
})
.collect();
Json(serde_json::json!({ "items": items }))
}
#[get("/slow")]
async fn slow() -> &'static str {
tokio::time::sleep(Duration::from_secs(2)).await;
"Done (took 2 seconds)"
}
#[tokio::main]
async fn main() -> std::io::Result<()> {
let cors = CorsConfig::with_origins(vec![
"https://example.com".to_string(),
"https://app.example.com".to_string(),
]);
let rate_limit = RateLimitConfig::per_minute(10);
let compression = CompressionConfig::default();
let timeout = TimeoutMiddleware::new(Duration::from_secs(5));
println!();
println!(" Rapina Middleware Example");
println!(" ------------------------");
println!();
println!(" Server: http://127.0.0.1:3000");
println!();
println!(" Endpoints:");
println!(" GET / — hello world");
println!(" GET /data — large JSON (try with Accept-Encoding: gzip)");
println!(" GET /slow — 2s delay (timeout set to 5s)");
println!();
println!(" Middleware stack (outermost first):");
println!(" 1. TraceId");
println!(" 2. RequestLog");
println!(" 3. RequestTimer (custom)");
println!(" 4. CORS (origins: example.com, app.example.com)");
println!(" 5. RateLimit (10 req/min per IP)");
println!(" 6. Compression (gzip/deflate)");
println!(" 7. Timeout (5s)");
println!();
Rapina::new()
.middleware(TraceIdMiddleware::new())
.with_request_log(RequestLogConfig::verbose())
.middleware(RequestTimerMiddleware)
.with_cors(cors)
.with_rate_limit(rate_limit)
.with_compression(compression)
.middleware(timeout)
.discover()
.listen("127.0.0.1:3000")
.await
}