Technical
CORS
Also called Cross-Origin Resource Sharing.
CORS is the set of HTTP headers a server uses to tell a browser which other origins may read its responses. Without them the browser blocks a page on one site from reading data fetched from another.
How it is measured
Compare the request's `Origin` header with the response's `Access-Control-Allow-Origin`, `-Methods`, `-Headers`, and `-Credentials`. For non-simple requests the browser first sends an OPTIONS preflight. Check that it returns 204 with matching allow headers and a sensible `Access-Control-Max-Age`.
The console line 'blocked by CORS policy' is the browser's verdict, not the server's. The server often handled the request fine, and curl will show a 200 while the browser refuses to hand the body to the script.
Worked example
A dashboard at `app.fernlab.example` calls `https://api.fernlab.example/v1/stats` with an `Authorization` header. The browser sends an OPTIONS preflight first, and the API answers 404 because the router only registers GET. The console shows a CORS error although the endpoint works in curl.
An OPTIONS handler that returns `Access-Control-Allow-Origin: https://app.fernlab.example` and `Access-Control-Allow-Headers: Authorization` fixes it. A wildcard would also work here, but not once cookies ride along with `credentials: 'include'`.
How it differs
CORS loosens the same-origin rule for origins you choose. CSP works the other way and restricts what the page itself may load or connect to. CORS is set by the server being called; CSP is set by the page doing the calling.
Common errors
Reflecting any Origin back while allowing credentials. Pairing `*` with cookies. Forgetting `Vary: Origin`, so a cache hands one origin's header to another. Believing CORS protects the API from curl. Not answering OPTIONS. Allowing the `null` origin.
In practice
List the origins that really call your API and allow exactly those. Add `Vary: Origin`. Test one preflighted request from the actual front end, not only curl. Remember CORS only governs browser reads; the API still needs authentication.