CORS OPTIONS preflights at the edge

Browsers send OPTIONS requests before performing cross-origin POSTs. You can answer these requests directly from the edge.

VCL

Use this solution in your VCL service (click RUN below to test this solution or clone it to make changes):

Compute@Edge

Use this solution in your Compute@Edge service:

  1. Rust
if req.get_method() == Method::OPTIONS
&& req.contains_header(header::ORIGIN)
&& (req.contains_header(header::ACCESS_CONTROL_REQUEST_HEADERS)
|| req.contains_header(header::ACCESS_CONTROL_REQUEST_METHOD))
{
Ok(Response::new()
// Standard response to a preflight does not have a
// response body, so a 204 No Content is appropriate,
// though you can also send a 200 OK, that works too.
.with_status(StatusCode::NO_CONTENT)
// Echo the requested origin back to the client. You
// may like to check this against a whitelist of origins
// instead of blindly allowing potentially destructive
// requests from any origin
.with_header(
header::ACCESS_CONTROL_ALLOW_ORIGIN,
req.get_header(header::ORIGIN).unwrap(), // We checked the `Origin` header exists above.
)
// Client may use this preflight response to authorise
// future requests that would otherwise also require a
// preflight, so to maximise reuse, we'll list all allowed
// methods here, not just the one that was requested.
// (think carefully before adding 'DELETE' to this list!)
.with_header(
header::ACCESS_CONTROL_ALLOW_METHODS,
"GET,HEAD,POST,OPTIONS",
)
// Setting a cache TTL on the response allows the client
// to use this preflight response for other requests.
.with_header(header::ACCESS_CONTROL_ALLOW_METHODS, "86400"))
} else {
Ok(
Response::from_body("The page you requested could not be found")
.with_status(StatusCode::NOT_FOUND),
)
}