Middleware and CORS¶
Middleware receives a context and a continuation. Register global layers explicitly on an app.
import system;
import system.webapi;
async fun request_id(ctx: RequestContext, next: Next): HttpOutgoing {
ctx.set("request_id", ctx.incoming.header("X-Request-ID").unwrap_or("local"));
let response = next.call().await;
return response.set_header("X-Request-ID", ctx.get("request_id").unwrap_or(""));
}
@router("")
class Routes {
@get("/hello")
public static fun hello(): string {
return "hello";
}
}
async fun main(): void {
let app = WebApp();
app.include_router(Routes.router()).unwrap();
app.use(Middleware(request_id)).unwrap();
app.use(
Cors.middleware(
CorsOptions(
allow_origins: "https://example.com",
allow_methods: "GET,POST",
allow_headers: "Authorization,Content-Type"
)
)
).unwrap();
app.run("127.0.0.1", 8000).await.unwrap();
}
The first registered layer is outermost. Requests pass through app layers, router @use(handler) layers, route @use(handler) layers, dependency extraction, and the handler. Responses return in reverse order. Repeated @use attributes preserve source order.
A layer may return early, for example to reject a request or answer a preflight, without calling next. Call next.call().await once to continue. App middleware also surrounds documentation and unmatched-route responses.
Middleware building blocks¶
| Name | What it is |
|---|---|
Middleware(handler) |
Wraps an async fun(ctx: RequestContext, next: Next): HttpOutgoing so app.use can install it. |
next.call() |
Runs the rest of the pipeline and returns its Future<HttpOutgoing>. |
@use(handler) |
Applies a middleware function to one router class or one route. Repeatable. |
app.use(middleware) |
Applies middleware to every request the app handles, including documentation pages and 404s. |
Cors.middleware(options) |
Built-in middleware for cross-origin requests. |
CORS options¶
List values are comma-separated strings, such as "GET,POST".
CorsOptions field |
Default | Effect |
|---|---|---|
allow_origins |
"*" |
Origins allowed to call the API, or * for any. |
allow_methods |
"*" |
Methods allowed in preflight responses. * lists all standard methods. |
allow_headers |
"*" |
Request headers allowed in preflight responses. * echoes the headers the browser asks for. |
expose_headers |
"" |
Response headers that browser code may read. |
allow_credentials |
false |
Allow cookies and Authorization on cross-origin requests. |
max_age |
600 |
Seconds a browser may cache a preflight response. |
With credentials enabled, the response echoes the allowed request origin instead of sending *, because browsers reject credentials with a wildcard origin. Include custom response headers in expose_headers when browser code must read them.
See the API lookup and complete example.