Understanding CORS: When Cross‑Origin Requests Are Executed, Intercepted, and Preflighted
This article explains the mechanics of CORS, detailing how browsers decide whether a cross‑origin request is executed directly, blocked, or preceded by a preflight OPTIONS request, and distinguishes between simple and complex requests based on method, headers, and other criteria.
Last week a common interview question sparked a heated discussion: when does a cross‑origin request actually get executed, and when is it blocked?
The answer is that a request may sometimes be executed and sometimes not, depending on several factors.
Cross‑Origin Interception
Some think the server intercepts the request, but the same‑origin policy is a browser strategy, not a server one. The server cannot reliably determine whether a request is cross‑origin because HTTP headers can be forged, and implementing a server‑side interception strategy for every possible origin is impractical.
Therefore, the request is not blocked by the server; instead, the browser may block it before it is sent.
When Does the Browser Intercept?
Many assume the browser stops the request before it leaves, but typical articles suggest using CORS to solve cross‑origin issues. The client relies on response headers such as Access-Control-Allow-Origin to decide if the request is allowed.
If the request never leaves, how does the browser know which origins are permitted? The answer is that the request is sent, and the browser may hide the response if it violates CORS.
Preflight Request
Before the actual request, the browser sends a Preflight request using the OPTIONS method. This explains why the Network panel often shows two requests.
The preflight asks the server whether the upcoming request is allowed, including which HTTP methods and headers are permitted.
When the preflight reaches the server, the server does not execute business logic; it only returns CORS headers (e.g., Access-Control-Allow-Origin: a.com ) indicating whether the real request may proceed.
Simple vs. Complex Requests
Not every request triggers a preflight. If the browser classifies a request as a "simple request," it skips the preflight. A request is considered simple when it meets all of the following:
Uses one of the methods: GET , HEAD , or POST .
Only uses safe headers such as Accept , Accept-Language , Content-Language , and Content-Type with values limited to text/plain , multipart/form-data , or application/x-www-form-urlencoded .
No event listeners are attached to the XMLHttpRequest object, and the XMLHttpRequest.upload property is not used.
The request does not use a ReadableStream object.
If any of these conditions are not met, the request is "complex" and a preflight will be performed. Only after a successful preflight does the actual request reach the server and get executed.
Summary
Simple requests are always sent to the server and executed, regardless of cross‑origin status; the browser may simply hide the response.
Complex requests first undergo a preflight OPTIONS request; the server returns CORS headers, and only if they allow the request does the real request get sent and executed.
IT Services Circle
Delivering cutting-edge internet insights and practical learning resources. We're a passionate and principled IT media platform.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.