CORS Configuration

Guide to configuring Cross-Origin Resource Sharing (CORS).

Table of Contents


Basic Setup

CorsMiddleware

Use CorsMiddleware to configure CORS.

use reinhardt::CorsMiddleware;
use reinhardt_middleware::cors::CorsConfig;

let mut config = CorsConfig::default();
config.allow_origins = vec!["https://example.com".to_string()];
config.allow_methods = vec!["GET".to_string(), "POST".to_string()];
config.allow_headers = vec!["Content-Type".to_string()];
config.allow_credentials = true;
config.max_age = Some(3600);

let middleware = CorsMiddleware::new(config);

CORS Configuration Options

CorsConfig

FieldTypeDefaultDescription
allow_originsVec<String>["*"]Allowed origins
allow_methodsVec<String>["GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS"]Allowed HTTP methods
allow_headersVec<String>["Content-Type", "Authorization"]Allowed request headers
allow_credentialsboolfalseWhether to allow credentials
max_ageOption<u64>Some(3600)Preflight cache duration (seconds)

Preflight Requests

Automatic OPTIONS Handling

CorsMiddleware automatically handles preflight requests (OPTIONS method).

use reinhardt::CorsMiddleware;

let middleware = CorsMiddleware::permissive();

// Preflight requests are automatically responded to with 204 No Content
// Access-Control-Allow-Origin: *
// Access-Control-Allow-Methods: GET, POST, PUT, PATCH, DELETE, OPTIONS
// Access-Control-Allow-Headers: Content-Type, Authorization
// Access-Control-Max-Age: 3600

Example Preflight Response

HTTP/1.1 204 No Content
Access-Control-Allow-Origin: https://example.com
Access-Control-Allow-Methods: GET, POST
Access-Control-Allow-Headers: Content-Type, Authorization
Access-Control-Max-Age: 3600
Access-Control-Allow-Credentials: true

Development Environment

Permissive Mode

Use permissive() to allow all origins in development.

use reinhardt::CorsMiddleware;

// Allow all (development only)
let middleware = CorsMiddleware::permissive();

This is equivalent to:

use reinhardt_middleware::cors::CorsConfig;

let mut config = CorsConfig::default();
config.allow_origins = vec!["*".to_string()];
config.allow_methods = vec![
    "GET".to_string(),
    "POST".to_string(),
    "PUT".to_string(),
    "PATCH".to_string(),
    "DELETE".to_string(),
    "OPTIONS".to_string(),
];
config.allow_headers = vec!["Content-Type".to_string(), "Authorization".to_string()];
config.allow_credentials = false;
config.max_age = Some(3600);

Production Environment

Single Origin

Allow only a specific origin.

use reinhardt_middleware::cors::CorsConfig;

let mut config = CorsConfig::default();
config.allow_origins = vec!["https://app.example.com".to_string()];
config.allow_methods = vec!["GET".to_string(), "POST".to_string()];
config.allow_headers = vec!["Content-Type".to_string()];
config.allow_credentials = false;
config.max_age = Some(3600);

Multiple Origins

Allow multiple origins (comma-separated).

use reinhardt_middleware::cors::CorsConfig;

let mut config = CorsConfig::default();
config.allow_origins = vec![
    "https://app1.example.com".to_string(),
    "https://app2.example.com".to_string(),
];
// ... other config

Allow Credentials

Allow requests with cookies and authentication headers.

Note: When allow_credentials: true, you cannot use "*" in allow_origins.

use reinhardt_middleware::cors::CorsConfig;

// Cannot use wildcard with credentials
let mut config = CorsConfig::default();
config.allow_origins = vec!["https://app.example.com".to_string()];
config.allow_methods = vec!["GET".to_string(), "POST".to_string()];
config.allow_headers = vec![
    "Content-Type".to_string(),
    "Authorization".to_string(),
    "X-CSRF-Token".to_string(),
];
config.allow_credentials = true;
config.max_age = Some(7200); // 2 hours

Router Integration

Apply at Router Level

use reinhardt::ServerRouter;
use reinhardt::CorsMiddleware;

let router = ServerRouter::new()
    .with_middleware(CorsMiddleware::permissive());

Apply to Specific Routes

use reinhardt::ServerRouter;
use hyper::Method;

async fn api_handler(_req: reinhardt::Request) -> reinhardt::Result<reinhardt::Response> {
    Ok(reinhardt::Response::ok())
}
let router = ServerRouter::new()
    .function("/api/data", Method::GET, api_handler)
    .with_route_middleware(CorsMiddleware::permissive());

Middleware Order

CORS middleware should be applied as early as possible.

Recommended order:

  1. RequestIdMiddleware (request tracking)
  2. LoggingMiddleware (logging)
  3. CorsMiddleware (CORS handling)
  4. SecurityMiddleware (security headers)
  5. Other middleware...
use reinhardt::ServerRouter;
use reinhardt::{CorsMiddleware, LoggingMiddleware};
use reinhardt_middleware::SecurityMiddleware;

let router = ServerRouter::new()
    .with_middleware(LoggingMiddleware::new())
    .with_middleware(CorsMiddleware::permissive())
    .with_middleware(SecurityMiddleware::new());

See Also