How to handle CORS

Web
To handle CORS in Rust, you must explicitly configure your web server to send the correct `Access-Control-Allow-Origin` and related headers in response to browser requests.

To handle CORS in Rust, you must explicitly configure your web server to send the correct Access-Control-Allow-Origin and related headers in response to browser requests. The most robust approach is to use the cors crate with a framework like actix-web or axum, which automatically handles preflight OPTIONS requests and validates allowed origins, methods, and headers.

For actix-web, add the actix-cors dependency and wrap your app with the Cors middleware. This middleware handles the complex logic of preflight checks and header injection automatically.

use actix_web::{web, App, HttpServer, HttpResponse};
use actix_cors::Cors;

async fn index() -> HttpResponse {
    HttpResponse::Ok().body("Hello CORS!")
}

#[actix_web::main]
async fn main() -> std::io::Result<()> {
    let cors = Cors::default()
        .allow_any_origin() // Use .allowed_origin("https://example.com") in production
        .allow_any_method()
        .allow_any_header()
        .max_age(3600);

    HttpServer::new(move || {
        App::new()
            .wrap(cors)
            .route("/", web::get().to(index))
    })
    .bind("127.0.0.1:8080")?
    .run()
    .await
}

If you are using axum, the tower-http crate provides the cors middleware. You configure it similarly by defining allowed origins and methods, then apply it as a layer to your router.

use axum::{routing::get, Router};
use tower_http::cors::{Any, CorsLayer};

async fn hello() -> &'static str {
    "Hello CORS!"
}

#[tokio::main]
async fn main() {
    let cors = CorsLayer::new()
        .allow_origin(Any) // Restrict to specific origins in production
        .allow_methods(Any)
        .allow_headers(Any);

    let app = Router::new()
        .route("/", get(hello))
        .layer(cors);

    let listener = tokio::net::TcpListener::bind("0.0.0.0:3000").await.unwrap();
    axum::serve(listener, app).await.unwrap();
}

In production, never use allow_any_origin() or Any for origins unless your API is truly public. Instead, specify the exact domain of your frontend application (e.g., https://myapp.com) to prevent cross-site request forgery (CSRF) and data leakage. Also, ensure you explicitly allow the necessary HTTP methods (GET, POST, etc.) and headers (like Content-Type or Authorization) required by your client. If you are building a custom server without a framework, you must manually inspect the Origin header in incoming requests and return the appropriate Access-Control-Allow-Origin header, while also returning a 204 No Content response for OPTIONS requests to satisfy preflight checks.