What is CORS and how does the preflight request work?
CORS (Cross-Origin Resource Sharing) is a browser security mechanism that controls whether JavaScript running on one origin (scheme + host + port) can make HTTP requests to a different origin. Without CORS, the Same-Origin Policy would block all such requests entirely.
The browser enforces CORS — servers and network intermediaries cannot. When JavaScript calls `fetch('https://api.example.com/data')` from `https://app.example.com`, the browser checks whether the response includes `Access-Control-Allow-Origin: https://app.example.com` (or `*`). If not, the browser blocks the JavaScript from reading the response, even though the HTTP request was sent and the server responded normally.
**Simple vs. non-simple requests:** Simple requests (GET/HEAD/POST with only safe headers and `application/x-www-form-urlencoded`, `multipart/form-data`, or `text/plain` content types) skip the preflight. The browser sends the request directly with an `Origin` header and validates the response headers.
Non-simple requests — PUT, DELETE, PATCH, any request with custom headers (`Authorization`, `Content-Type: application/json`), or requests with credentials — trigger a **preflight**.
**Preflight request flow:** 1. Browser sends an `OPTIONS` request to the same URL with headers: - `Origin: https://app.example.com` - `Access-Control-Request-Method: POST` - `Access-Control-Request-Headers: Authorization, Content-Type` 2. Server responds (if it allows the request): - `Access-Control-Allow-Origin: https://app.example.com` - `Access-Control-Allow-Methods: POST, PUT, DELETE` - `Access-Control-Allow-Headers: Authorization, Content-Type` - `Access-Control-Max-Age: 86400` (cache preflight for 24h) 3. If the preflight succeeds, the browser sends the actual request. If it fails (missing or mismatched headers), the browser blocks the request without sending it.
**Credentials** (`withCredentials: true` / cookies): the server must respond with `Access-Control-Allow-Credentials: true` and must NOT use `Access-Control-Allow-Origin: *` — it must specify the exact origin.
Common production issues: forgetting to handle `OPTIONS` in server routing (returning 404 or 405), not including custom headers in `Access-Control-Allow-Headers`, or using a wildcard origin with credentials. `Access-Control-Max-Age` is often overlooked — without it, browsers send a preflight on every non-simple request, doubling latency.
Explains the Same-Origin Policy motivation, distinguishes simple from non-simple requests, and describes the preflight OPTIONS request/response header exchange.
Covers the exact header names for both preflight request and response, explains credentials handling (no wildcard with credentials), mentions Access-Control-Max-Age for preflight caching, and names common implementation mistakes.
Reading the answer is step one. Explaining it unprompted — under interview pressure — is what actually matters. Get AI-graded feedback on your answer with follow-up probes on your weak points.
Get Graded — Free Assessment