CORS - Cross-Origin Resource Sharing
In simple terms, when you want to allow requests from a different domain (read origin) to your server, CORS comes into the picture. CORS is a policy that is enforced by the browser.
Let's say you're reading this post on
Dev.to is the origin here and it's allowed to request for resources (make https calls) that are present in its origin only. If it's making calls to any other origin, even to its sub-domain, the request will be termed cross-origin request.
In the world of microservices, even within your architecture, you might have different services talking to multiple servers. CORS is a mechanism to let only the trusted origins make the Cross-Origin HTTP request to your server.
Consider this naive example where there's an application running at
rahul.dev.to and there's a functionality to edit my posts. Once the post is edited, I have to update the post across all my blogging sites - dev.to, medium.com, blogger.com
For this hypothetical case to work, I would need to hit this patch API on
PATCH https://dev.to/rahul_ramfort/post/20 Request-Headers: User-Agent, api_key
(for brevity, ignoring medium and blogger API calls)
I am trying to post the data from my server (rahul.dev.to) to another server (dev.to) and I might or might not be allowed to actually make this request on
This is the problem at hand. Browsers do not know if it's safe to make this request.
To solve this, Browsers for security reasons, do not directly allow this cross-origin requests to go through. Before firing the actual
patch request, it instead fires an OPTIONS request to the cross-origin (dev.to) with all the details of the CORS request.
The details include:
Origin of the requested server - rahul.dev.to Method rahul.dev.to is trying to hit - PATCH Headers rahul.dev.to is trying to send - User-Agent, api_key
Dev.to, the cross-origin receives the OPTIONS request and can deny or allow the origin (rahul.dev.to) to make requests.
In this case,
dev.to would have configured a list of trusted origins that can make the CORS requests at its application layer.
#sample configuration at the nginx layer (dev.to) 'Access-Control-Allow-Origin' "https://api.dev.to, https://rahul.dev.to" 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS, DELETE, PUT, PATCH' 'Access-Control-Allow-Headers' 'User-Agent,Content-Type,access-key,api-key' 'Access-Control-Max-Age' 86400
rahul.dev.to is listed as one of the trusted origins, the browser receives a successful 204. Now the browser understands that it is safe to allow the CORS request and fires the actual
rahul.dev.to is not listed in the allow-origin, the server denies the OPTIONS request.
The browser considering this as a potential threat, will not fire the actual
PATCH request throwing an error,
Preflight response is not successful
These are the headers received for the preflight request.
- Access-Control-Allow-Origin - specifies the requested origin if it has access.
- Access-Control-Allow-Methods - specifies which methods are allowed for CORS.
- Access-Control-Allow-Headers - specifies which headers can be used with the actual CORS request.
- Access-Control-Max-Age - specifies how much time (in seconds) the response of the preflight request can be cached. The browser will skip further preflight requests and directly hit the actual request during that time period.
It is pretty common to see people configuring like this as a workaround to allow CORS requests.
What this essentially means is that your server is allowing all the origins to hit CORS requests. No, do not do this. 🙅🏻♂️ Allow only trusted origins here and using
'*' should totally be avoided.
Further, if you want to reduce the frequency of preflight requests for your trusted origins, you can set the
Access-Control-Max-Age header to a higher value.
To read more: 📖