Skip to content

CORS ​

Cross-origin resource sharing (CORS) lets a browser call your API from a page served on another origin. Corvis enables it with app.enable_cors(...) and follows the semantics of Express's cors package: same options, same headers and same handling of preflight requests.

Enabling it ​

rust
let mut app = CorvisFactory::create::<AppModule>().await?;
app.enable_cors(CorsOptions::default());

CorsOptions::default() (same as CorsOptions::new()) allows any origin (Access-Control-Allow-Origin: *) with the methods GET, HEAD, PUT, PATCH, POST and DELETE.

You can also pass it when creating the application, in CorvisApplicationOptions:

rust
use corvis::CorvisApplicationOptions;

let app = CorvisFactory::create_with_options::<AppModule>(CorvisApplicationOptions {
    cors: Some(CorsOptions::new().origin("https://app.example.com")),
    ..Default::default()
})
.await?;

Typical configuration ​

rust
app.enable_cors(
    CorsOptions::new()
        .origins(["https://app.example.com", "http://localhost:5173"])
        .methods(["GET", "HEAD", "POST", "PATCH", "PUT", "DELETE", "OPTIONS"])
        .allowed_headers(["Content-Type", "Authorization"])
        .exposed_headers(["Content-Disposition"])
        .credentials(true)
        .max_age(86_400),
);
MethodEquivalent cors optionEffect
.origin("https://a.com")origin: 'https://a.com'A fixed origin. Calling it twice builds a list; "*" is any origin
.origins([...])origin: [...]List of exact origins
.origin_regex(Regex::new(...)?)origin: /re/Adds a regular expression to the list (use your own dependency on the regex crate)
.reflect_origin()origin: trueReflects the request's origin
.origin_fn(|origin| ...)origin: (origin, cb) => ...Decides per request by returning a CorsOrigin
.origin_value(CorsOrigin::Disabled)origin: falseDoes not send CORS headers
.methods([...])methodsAccess-Control-Allow-Methods
.allowed_headers([...])allowedHeadersWithout a value, the requested headers are reflected
.exposed_headers([...])exposedHeadersAccess-Control-Expose-Headers
.credentials(true)credentialsAccess-Control-Allow-Credentials: true
.max_age(seconds)maxAgeAccess-Control-Max-Age in the preflight
.preflight_continue(true)preflightContinuePasses the OPTIONS to the application instead of answering it
.options_success_status(200)optionsSuccessStatusPreflight status (204 by default)

Dynamic origins ​

origin_fn receives the request's origin (if any) and returns a CorsOrigin:

rust
use corvis::CorsOrigin;

app.enable_cors(
    CorsOptions::new()
        .origin_fn(|origin| match origin {
            Some(o) if o.ends_with(".example.com") => CorsOrigin::Reflect,
            _ => CorsOrigin::Disabled,
        })
        .credentials(true),
);

The CorsOrigin variants are Any, Reflect, Disabled, Fixed(String), List(...) and Dynamic(...). Disabled omits the CORS headers for that request only.

Behavior ​

  • Any OPTIONS is treated as a preflight, even if it carries no Access-Control-Request-Method and even if the route does not exist: 204 is returned with Content-Length: 0 and the Access-Control-* headers. This happens before middleware and guards. The exceptions are preflight_continue(true) and an origin_fn that returns CorsOrigin::Disabled for that request: in those cases the OPTIONS continues to the application.
  • Vary: Origin is always sent when the configured origin is not *, also when the request's origin is not allowed (in that case Access-Control-Allow-Origin is missing and the browser blocks the response).
  • CORS headers are also added to error responses, including those from the body parser.
  • Headers set by the handler take priority over those from CORS.

credentials and open origins

With credentials(true) the browser sends cookies. Do not combine it with reflect_origin() or an origin_fn that accepts any origin: any site could make authenticated requests on behalf of the user. Use an explicit list.

WebSockets ​

enable_cors does not affect gateways. To limit the origins that can open a WebSocket use GatewayOptions::allowed_origins (responds 403 on the handshake). See Gateways.

Released under the MIT License.