rust 32 lines · 7 steps

Configuring CORS on an Axum Router

How to build an Axum router that applies a tuned CORS policy across its JSON API routes.

Explained by highlit
1use std::time::Duration;
2 
3use axum::{
4 http::{header, HeaderValue, Method},
5 routing::{get, post},
6 Json, Router,
7};
8use serde_json::{json, Value};
9use tower_http::cors::CorsLayer;
10 
11pub fn app() -> Router {
12 let cors = CorsLayer::new()
13 .allow_origin("https://app.example.com".parse::<HeaderValue>().unwrap())
14 .allow_methods([Method::GET, Method::POST, Method::PUT, Method::DELETE])
15 .allow_headers([header::AUTHORIZATION, header::CONTENT_TYPE])
16 .expose_headers([header::CONTENT_DISPOSITION])
17 .allow_credentials(true)
18 .max_age(Duration::from_secs(3600));
19 
20 Router::new()
21 .route("/api/profile", get(profile))
22 .route("/api/sessions", post(create_session))
23 .layer(cors)
24}
25 
26async fn profile() -> Json<Value> {
27 Json(json!({ "id": 42, "name": "Ada Lovelace" }))
28}
29 
30async fn create_session() -> Json<Value> {
31 Json(json!({ "token": "eyJhbGciOi...", "expires_in": 3600 }))
32}
01 / 01
STEP 01

Walkthrough

Space play ←→ step click any line
Three takeaways
  1. 1A CORS layer must explicitly whitelist origins, methods, and headers rather than defaulting to permissive.
  2. 2Tower middleware applied with `.layer` wraps every route on the router uniformly.
  3. 3`allow_credentials(true)` requires a concrete origin — wildcards are rejected by browsers when credentials are sent.

Related explainers

Share this explainer

Here's the card — post it anywhere.

Configuring CORS on an Axum Router — share card
Made with highlit — turn any snippet into a walkthrough like this in about a minute.
Explain your code