Fixing CROSS Origin Resource Sharing (CORS) from the Front end.
Mopharr
Posted on December 18, 2021
Most front-end developer tends to come across CORS issue and they try to fix it with a solution on Stack overflow as I did, some turns out wrong and some didn't explain fully for better understanding.
In this article, I will talk about CORS and how it can be fixed from the Front End (client-side).
Know Your Enemy, What is CORS? 👹👹
The common Cross Origin Resource Sharing (CORS) is a mechanism that allows restricted resources on a web page to be requested from another domain outside the domain from which the first resource was served.
Why does it Exist?🤔
To protect us! It’s our friend!💯🐕
Most of the time a website will require resources hosted in the same place as the website is, for example, making API calls to the same Back end that is serving the website.🏡
So this policy would be the first layer of protection to avoid other unknown people using our API.⚔️
Why do we end up having CORS issues?
Because in some scenarios we need to request resources from one origin to a different one. For example, when our API is hosted in a different domain than our website (any 3rd party API), or when you need to use web fonts.
CORS doesn’t allow this by default, so an error will appear that can be seen in the browser console.
What is happening between our browser and the destination of our requests?
Web browsers can use special headers to determine whether or not an XMLHttpRequest call should continue or fail.
Let’s get into more technical detail… 👇👇👇👇👇👇👇
OPTIONS request 🧐
Most people know the basic request methods (POST, GET, PUT) but not everyone is familiarized with the OPTIONS method. This request method is used to ask for information from a specific endpoint about what communication options it supports.
This request is used to determine the exact CORS capabilities of the server, which is in turn used to determine whether or not the intended CORS protocol is understood. If the result of the OPTIONS call dictates that the request cannot be made, the actual request to the server will not be executed.
The options contained in an OPTIONS request are the following:
Access-Control-Request-Method
: The intended method of the request (e.g. GET or POST)Access-Control-Request-Headers
: An indication of the custom headers that will be sent with the requestOrigin
: The usual origin header that contains the script's current origin
So our client is asking🤔:
“_I would like to make a GET request with the Content-Type and Accept headers from http://localhost:3000 — is that possible?_”.
curl -i -X OPTIONS localhost:3001/api/ping
'Access-Control-Request-Method: GET'
'Access-Control-Request-Headers: Content-Type, Accept'
'Origin: <http://localhost:3000>'
The server will include some Access-Control-*
headers within the response to indicate whether the request that follows will be allowed or not. These include:
Access-Control-Allow-Origin
: The origin that is allowed to make the request, or * if a request can be made from any origin.Access-Control-Allow-Methods
: A comma-separated list of HTTP methods that are allowed.Access-Control-Allow-Headers
: A comma-separated list of the custom headers that are allowed to be sent.Access-Control-Max-Age
: The maximum duration that the response to the pref light request can be cached before another call is made.
The response would then be examined by the browser to decide whether to continue with the requester to abandon it.
So our server is replying🤓:
“I accept requests from every domain (*) and I allow the following methods GET, HEAD, PUT, PATCH, POST, DELETE”
HTTP/1.1 204 No Content
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: GET,HEAD,PUT,PATCH,POST,DELETE
Vary: Access-Control-Request-Headers
Access-Control-Allow-Headers: Content-Type, Accept
Content-Length: 0
Date: Fri, 05 Apr 2019 11:41:08 GMT
Connection: keep-alive
So if the first request the client is trying to perform meets the requirements it sends the initial request and the process continues normally, and everyone is happy 🎊🎊🎉😁 . If it doesn’t you get a dramatic CORS error which means your initial request wasn’t even sent and you cry 😭.
So, how do we fix it? 🔧
If a CORS issue appears during development, because we are using a local development server, this is not an “error”, it is just an inconvenience that we will learn to solve.
🤔Maybe you are thinking about changing the “origin” header to avoid CORS, forget about it, ‘origin’ is a forbidden header which means you can’t update it.🙄
🤔The next and most common solution is to ask the server to set the headers to *** (allow all)**.
💩🤦♀️This is not a good practice, the final domain for the Front end should be whitelisted of course, but to simply allow all is a breach of security that shouldn’t be encouraged.🤦♂️💩
While developing our domain is usually localhost and toward the outside world that domain is our IP, unless you whitelist it, which can be ineffective if the IP changes, it is never allowed by CORS restrictions unless you allow all domains. 🤷♂️🤷♀️
🤓Now the most efficient and least painful way to bypass this restriction for development is to use a proxy. This way we do the request to a proxy server that allows our requests and this one does the request to the original API domain. This request will be performed by a proxy server, not a browser, so it will be able to perform the requests without restrictions. It will also send the original content back to our Front end in the response from the API.👌
There are already built proxy servers, so you don’t have to create your own, just install one cors-proxy from npm and you are all set.
Setting up a CORS proxy 🛠
In my case, I used this:
https://www.npmjs.com/package/local-cors-proxy but there are hundreds. You can install it locally in your project or globally on your computer, depending on if you want to add it to your project development dependencies and make it run while you are developing.
(Usually automating stuff is a good idea, just saying🙄)
In this case, the steps are easy to follow, but just in case I’m going to review them one by one:
Simple Example
API endpoint that we want to request that has CORS issues:
https://www.yourdomain.ie/movies/list
- Install dependency by running the following command:
npm i local-cors-proxy
- Start proxy for the specific domain if it’s giving you issues:
lcp --proxyUrl https://www.yourdomain.ie
- In your client update your API endpoint to point it to your proxy: From this:
<https://www.yourdomain.ie/movies/list>
To this:
<http://localhost:8010/proxy/movies/list>
CORS Fixed 🎉🎉🎉🎉
Conclusion
As I hope you can see now, there is no magic surrounding CORS🧙♂️, it’s something “the backend is supposed to fix”. But if you are working with a Public API, we have the issue and now you can fix CORS yourself. Thank You
Posted on December 18, 2021
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.