Understanding CORS

Rafael Bika(s)
Apr 30, 2023
What is CORS?
If a website is hosted on localhost:8000
and its JavaScript code attempts to send a request to a server running on localhost:9000
, the request will fail due to the same-origin policy enforced by browsers. This policy restricts how a document or script loaded from one origin can interact with resources from another origin, preventing unauthorized cross-origin requests by default.
Here's how it works:
- Requests made to the same origin are allowed by the browser.
- Requests to a different origin (known as cross-origin requests) are blocked by default, resulting in a CORS error.
So, what is CORS? CORS (Cross-Origin Resource Sharing) is an HTTP header based mechanism where servers can tell browsers which origins are allowed to interact with its resources.
The CORS mechanism supports secure cross-origin requests and data transfers between browsers and servers. Modern browsers use CORS in APIs such as XMLHttpRequest or Fetch, to mitigate the risks of cross-origin HTTP requests.
See the full list of what requests use CORS.
How does it work?
When a browser makes a cross-origin request, it includes an Origin header in the request. The server responds with an Access-Control-Allow-Origin header. If the value in this response header matches the Origin header from the request, the browser allows access to the response data. If they do not match, the browser blocks access, resulting in a CORS error.
Requests that use methods other than GET
, POST
, HEAD
, or those that include non-standard headers, must be pre-flighted. In such cases, before sending the actual request, the browser issues a pre-flight request using the OPTIONS HTTP method. The server must respond with Access-Control-Allow-Origin and Access-Control-Allow-Methods headers. If these headers match the request's origin and method, the browser proceeds with the actual request. This mechanism ensures that servers explicitly permit these requests before processing them, preventing unintended modifications to server data.
Although the POST method can modify server data, it does not always trigger a preflight request. Before CORS was introduced, browsers already allowed cross-origin POST requests with standard headers, and servers were designed to handle them. Rather than changing existing behavior, CORS was designed to protect servers from new types of cross-origin requests that they were not previously configured to handle.
How to fix CORS errors?
Let's revisited the example from the beginning of this article where a client application running on localhost:8000
makes a request to a server on localhost:9000
. If CORS is not properly configured, the request will fail and the following error will be displayed in the browser's console:
Access to fetch at http://localhost:9000/api/endpoint' from origin
'http://localhost:8000' has been blocked by CORS policy.
To see what's wrong with the request, open the Network tab in your browser's developer tools and check the response headers:
- Ensure the
Access-Control-Allow-Origin
header is present in the server's response and that its value matches the Origin header from the request. - If the request requires pre-flight, verify that the response includes the
Access-Control-Allow-Methods
header and that it allows the HTTP method being used.
If any required headers are missing or incorrectly set, update the server's configuration to include the correct CORS headers. In an Express.js application, this can be easily handled using the cors middleware:
var express = require('express')
var cors = require('cors')
var app = express()
cors({ origin: 'http://localhost:8000' })
app.get('/api', function (req, res, next) {
res.json({ msg: 'success' })
})
app.listen(9000, function () {
console.log('CORS-enabled for localhost:8000')
})
A common point of confusion when debugging CORS issues is that CORS errors only occur in browsers, not in tools like Postman or curl:
- These tools don't make cross-origin requests. They send a top-level network call (like if you are opening the URL on a new browser tab).
- While CORS is configured on the server side, it is the client's decision to honor these configurations or not. Most browsers do enforce it for security reasons, but developer tools don't care about it.