Understanding CORS: How Browsers and Servers Handle Cross‑Origin Requests
This article explains the CORS mechanism, detailing how browsers automatically add Origin headers, the difference between simple and non‑simple requests, the preflight exchange, required HTTP headers, and how servers respond to enable or reject cross‑origin communication.
Introduction
CORS (Cross‑Origin Resource Sharing) requires support from both browsers and servers; all modern browsers support it, with IE needing version 10 or higher. The entire CORS communication is performed automatically by the browser, so developers write the same AJAX code as for same‑origin requests.
How CORS Works
The specification defines new HTTP headers that browsers must send when they have permission to access remote URLs. While servers perform validation, the browser is responsible for adding these headers and applying related restrictions.
For data‑modifying Ajax or HTTP methods (anything other than GET, or POST with certain MIME types), the browser must first issue an OPTIONS preflight request to determine whether the server permits the cross‑origin request and whether credentials such as cookies may be included.
Two Types of Requests
1. Simple Request
A request is considered simple if it meets two conditions:
The HTTP method is HEAD, GET or POST.
Only the following request headers are used: Accept, Accept-Language, Content-Language, Last-Event-ID, and Content-Type limited to application/x-www-form-urlencoded, multipart/form-data, or text/plain.
For a simple request the browser adds an Origin header to the request.
GET /cors HTTP/1.1
Origin: http://api.tinywan.com
Host: api.alice.com
Accept-Language: en-US
Connection: keep-alive
User-Agent: Mozilla/5.0...The Origin header tells the server the request’s source (scheme + host + port) so the server can decide whether to allow it.
2. Non‑Simple Request (Preflight)
Requests that use methods such as PUT or DELETE, or a Content-Type like application/json, trigger a preflight request.
Non‑simple CORS requests add an extra HTTP query called a "preflight" request before the actual request.
The browser first asks the server whether the origin, method, and custom headers are permitted.
var url = 'http://api.alice.com/cors';
var xhr = new XMLHttpRequest();
xhr.open('PUT', url, true);
xhr.setRequestHeader('X-Custom-Header', 'value');
xhr.send();The browser then sends an OPTIONS request:
OPTIONS /cors HTTP/1.1
Origin: http://api.tinywan.com
Access-Control-Request-Method: PUT
Access-Control-Request-Headers: X-Custom-Header
Host: api.alice.com
Accept-Language: en-US
Connection: keep-alive
User-Agent: Mozilla/5.0...The preflight request uses the OPTIONS method; the key headers are Origin , Access-Control-Request-Method , and Access-Control-Request-Headers .
Access-Control-Request-Method lists the HTTP method the actual request will use (e.g., PUT).
Access-Control-Request-Headers is a comma‑separated list of any custom headers the actual request will send (e.g., X-Custom-Header).
Preflight Response
If the server approves the request, it responds with the appropriate CORS headers:
HTTP/1.1 200 OK
Date: Mon, 01 Dec 2008 01:15:39 GMT
Server: Apache/2.0.61 (Unix)
Access-Control-Allow-Origin: http://api.tinywan.com
Access-Control-Allow-Methods: GET, POST, PUT
Access-Control-Allow-Headers: X-Custom-Header
Access-Control-Allow-Credentials: true
Access-Control-Max-Age: 1728000
Content-Type: text/html; charset=utf-8
Content-Encoding: gzip
Content-Length: 0
Connection: Keep-AliveThe crucial header Access-Control-Allow-Origin indicates which origin may access the resource; it can also be set to * to allow any origin. Access-Control-Allow-Origin: * If the server denies the preflight, it returns a normal HTTP response without CORS headers, causing the browser to fire an error captured by the XMLHttpRequest onerror callback.
XMLHttpRequest cannot load http://api.tinywan2.com.
Origin http://api.bob.com is not allowed by Access-Control-Allow-Origin.Other important response headers include:
Access-Control-Allow-Methods : comma‑separated list of methods the server supports.
Access-Control-Allow-Headers : list of headers the server permits.
Access-Control-Allow-Credentials : indicates whether credentials may be included.
Access-Control-Max-Age : optional cache duration (in seconds) for the preflight result; the example shows 20 days (1728000 s).
Normal Request After Preflight
Once the preflight succeeds, subsequent CORS requests behave like simple requests, always containing an Origin header, and the server always includes Access-Control-Allow-Origin in its response.
PUT /cors HTTP/1.1
Origin: http://api.tinywan.com
Host: api.alice.com
X-Custom-Header: value
Accept-Language: en-US
Connection: keep-alive
User-Agent: Mozilla/5.0...Server response example:
Access-Control-Allow-Origin: http://api.tinywan.com
Content-Type: text/html; charset=utf-8Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Open Source Tech Hub
Sharing cutting-edge internet technologies and practical AI resources.
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.
