What is CORS (cross origin resource sharing)— and How to fix the CORS error
What is same-origin policy and CORS?
Cross origin resource sharing is a mechanism that allows websites on one URL to request data from another URL. For example, you try to fetch data from an API and the application fails with a cors error in the console. That happens because the browser implements the same-origin policy. This policy allows clients to freely request data from its own URL but blocks anything from a different URL unless certain conditions are met.
When a browser makes request to a server it adds an origin header
Origin: https://localhost:3000 to the request. If this request goes to a server with the same origin, it is allowed by the browser. But if the request goes to a different URL, called as a cross-origin request then, the server must add a
Access-Control-Allow-Origin header to the response message. The browser will then match this header with the Origin. In case of a mismatch the browser will reject the response throwing a cors error. This is the same-origin policy and it is implemented to prevent cross-site request forgery attacks in which malicious websites take advantage of the browser’s cookie storage system.
When working with API’s and or hosting this error often troubles developers. Below are some of the methods to resolve this issue.
Scenario 1 — Building a full-stack application
Everything seems to be working fine in the development environment because you are running the server and client programs on the same machine. However, when you deploy your server(using heroku or some other service) and then try to request data, Snap! the cors error kicks in.
Good news… The fix is really easy. You just needs to add the Access-Control-Allow-Origin header to the server responses.
Here, the ‘*’ specifies the wildcard value to allow all domains to access the server resources. The server can also be very specific, and only include the origin URL of the domain that can access the resources in the header.
— Alternative solution: using the cors package.
npm install cors
const cors = require('cors')
Add middleware to your server —
You can configure the cors options and even add it to only specific endpoints instead of all the responses. Check out the package documentation here.
Scenario 2 — Fetching data from a third-party API at the frontend
Say your frontend is trying to make a GET request to the GitHub Jobs API. But this API does not include a
Access-Control-Allow-Origin header in the response resulting in a cors error.
— Solution1: send your request to a fetch proxy (quick-fix)
The proxy server acts as a middleware between the client and the API. The GET request first goes to the proxy that adds the
Access-Control-Allow-Origin header and forwards the request to the client.
Here is a list of 10 free proxy servers you could use. This solution is great due to it’s ease of implementation. However, most of these proxies are for development purposes only and either provide only a demo for temporary use or won’t work in production environment. Also, it often takes a while to receive a response affecting the performance of the application.
— Solution2: build your own proxy server
Don’t worry it’s much easier than it sounds and the best solution as well as building your own proxy gives you more flexibility and control into its design and implementation. Build a simple server that fetches data from the API and servers the same data to your frontend meanwhile adding the
Access-Control-Allow-Origin header to the response. Here is an example of a Node proxy for fetching data from the GitHub Jobs API using restify.
Http requests with non-standard headers(Put, Patch, Delete) need to be preflighted. The browser first makes a request with the options Http verb to which the server responds with the allowed methods for that Origin using the header
Access-Control-Allow-Methods: PUT after which the actual request can be sent. The server can respond with a
Access-Control-Max-Age: 30000 header allowing the browser to cache the preflight for a certain amount of time making the process more efficient.
Some temporary fixes —
"proxy": "API_URL"to the package.json file and modify the fetch query to send request to ‘/’
- Install the Allow-Control-Allow-Origin browser plugin.
Disclaimer — These solutions work only in development and would fail in production environments.