CORS (Cross-Origin Resource Sharing) is the browser mechanism that lets a page
on one origin make requests to a different origin in a controlled way. It works
through a set of request and response headers, plus an optional preflight
OPTIONS round-trip. This reference lists every header and explains the flow.
How it works
When JavaScript on https://app.example.com calls an API on
https://api.example.com, the browser attaches an Origin header. For
“non-simple” requests the browser first sends a preflight OPTIONS request
carrying Access-Control-Request-Method and Access-Control-Request-Headers.
The server must answer with matching Access-Control-Allow-* headers. Only if
the response approves the method, headers and origin does the browser send the
real request and expose the response to the script.
The preflight flow
Browser → OPTIONS /data
Origin: https://app.example.com
Access-Control-Request-Method: PUT
Access-Control-Request-Headers: content-type, x-token
Server → 204 No Content
Access-Control-Allow-Origin: https://app.example.com
Access-Control-Allow-Methods: GET, PUT, DELETE
Access-Control-Allow-Headers: content-type, x-token
Access-Control-Max-Age: 600
If the response approves everything, the browser proceeds with the actual PUT.
Access-Control-Max-Age lets the browser cache the preflight to skip repeats.
Notes and common mistakes
Never combine Access-Control-Allow-Origin: * with
Access-Control-Allow-Credentials: true — browsers reject it. When you support
credentials, echo the validated Origin from an allow-list and also add
Vary: Origin so caches do not serve the wrong origin’s response. Reflecting any
origin without validation is the classic exploitable CORS bug.