Intercept requests before and after controller execution with simple annotations.
@Before(LoggingMiddleware.class)
@GET(value = "/dashboard", name = "dashboard")
private Object dashboard(Request req, Response res) {
return render("dashboard.html", Map.of());
}
@Before({CorsMiddleware.class, ApiKeyMiddleware.class, RateLimitMiddleware.class})
@GET(value = "/api/data", name = "api.data")
private Object data(Request req, Response res) {
// 1. CORS headers added
// 2. API key validated (401 otherwise)
// 3. Rate limit checked (429 otherwise)
// 4. Controller executed
return "{ \"data\": [] }";
}
@Before(TimingMiddleware.class)
@After(TimingMiddleware.class)
@GET(value = "/profile", name = "profile")
private Object profile(Request req, Response res) {
return render("profile.html", Map.of());
}
| Middleware | Description | Headers |
|---|---|---|
| LoggingMiddleware | Logs each request with IP and User-Agent. Debugging, monitoring, audit trail |
— |
| CorsMiddleware | Adds CORS headers to allow cross-origin requests. Public APIs, separate frontends, mobile apps |
Access-Control-Allow-Origin: * Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS Access-Control-Allow-Headers: Content-Type, Authorization, X-CSRF-TOKEN |
| RateLimitMiddleware | Limits to 100 requests/minute per IP. Returns 429 if exceeded. Anti-spam, anti-DDoS, public endpoints |
X-RateLimit-Limit: 100 X-RateLimit-Remaining: 87 |
| TimingMiddleware | Measures execution time. Performance optimization, detecting slow routes |
X-Response-Time: 42ms |
| ApiKeyMiddleware | Verifies the X-API-Key header. Returns 401 if invalid. Securing APIs, simple authentication |
— |
public class MaintenanceMiddleware implements Middleware {
@Override
public void handle(Request req, Response res) throws Exception {
boolean isMaintenance = System.getenv("MAINTENANCE_MODE") != null;
if (isMaintenance && !req.pathInfo().equals("/maintenance")) {
res.redirect("/maintenance");
throw new Exception("Maintenance mode");
}
}
}
@Before(MaintenanceMiddleware.class)
@GET("/dashboard")
private Object dashboard(Request req, Response res) {
return render("dashboard.html", Map.of());
}
@Before middlewares execute in array order@After middlewares execute after the controller