How it works and how to identify and fix CORS errors
Browsers have a lot of mechanisms to protect users. One of those things is the “Same Origin” policy. By default, web browsers only allow your site or web app to send a request to an URL of the same origin and block external URLs.
Cross-Origin Resource Sharing(CORS) allows a browser to request data from external URLs.
When developing, you might have seen a CORS error when your frontend sends a request to your backend. You might have also seen a CORS error when you try to fetch an image from an external URL.
In this article, you will understand how CORS works, how to identify a CORS error and how to fix it.
How does it work?
When your browser sends a request to a server, it adds an “Origin” header. The server receives it and sends its response with an “Access-control-allow-origin” header.
If these two header values don’t match, your browser will show a CORS error message.
How do I know that I have a Cors Error?
A Cors error can be a bit cryptic, as you cannot see the error unless you inspect it in your browser. Opening the inspector in Chrome, you will see the following.
In this case you see red lines showing the errors.
The status column for the two red lines in the image say CORS error and 404. You also notice that the type column mentions “xhr” and “preflight”.
Since you sent one request, it might be strange that you see two? And intuitively, you want to figure out why the 404 error is happening. But when looking at your backend logs, everything looks fine. And then you try to send a curl or postman request to your backend you see everything working just fine.
The first error says it all. It clearly says you have a CORS error.
So what about this preflight request. I did not create this additional request?
The second line in the error message belongs to a preflight request.
Your browser automatically sends it for specific requests that require it according to the CORS protocol.
The preflight is a simple OPTION request sent to the server. The browser sends its ORIGIN and the HTTP request method it wishes to use. The Server responds with its allowed origins and the allowed request methods.
It might seem like a waste to send two requests for every request you want to make. The preflight response is cached, so your Server will receive only one request for the majority of the times.
This does not make sense! Some of my requests are not sending preflights. What is wrong? You might lose hope of all the engineering skills you have right now. But not all requests require a preflight.
You will observe that some of your form submissions send a preflight, and some do not.
Nevertheless, all use CORS. With or without preflight.
Here are all the requests that use CORS
- XMLHttpRequest
- FETCH Apis
- Web Fonts
- WebGL textures.
- Images/video frames drawn to a canvas using drawImage().
- CSS Shapes from images.
If you want a deeper dive into CORS and understand what causes a preflight, this reference is an excellent source
How to fix CORS errors
First we need to understand what is causing the CORS error. The following three questions will help you:
- Does the server have cors enabled?
- Is the server allowing your origin?
- Is the server allowing the HTTP method you are using?
1. Does the server have cors enabled?
Suppose you have a CORS error. First, look in your browser’s inspector and see if you have the “Access-control-allow-origin” in your response header. If you do not, you need to enable cors.
You should find out how to enable CORS on your backend of choice with a quick google search.
If enabled, your response headers should now include “Access-control-allow-origin”. Have a look at the value. It could look like the following examples:
- Access-control-allow-origin:*, meaning all origins are allowed
- Access-control-allow-origin:http://domain1.example, meaning only domain1.example is allowed
- Access-Control-Allow-Origin: http://domain1.example, http://domain2.example, meaning domain1.example and domain2.example are allowed.
2. Is the server allowing your origin?
Make sure that your Origin header from your browser matches one of the values in Access-Control-Allow-Origin. If you do not have a match, you need to ensure that your backend is allowing all origins with the * value or that you specify a correct origin.
3. Is the server allowing the HTTP method you are using?
If you still get a cors error even after the origins match, it might be that your server is not allowing the specific HTTP method.
Look at the preflight request and response. The preflight response should have the header Access-Control-Allow-Methods. You will not find this header in the actual request. Only in the preflight.
Look at your actual request. Make sure the request method matches one of the values in Access-Control-Allow-Methods, and you should be good to go.