Access Control Origin Header error using Axios
I'm making an API call using Axios in a React Web app. However, I'm getting this error in Chrome:
XMLHttpRequest cannot load https://example.restdb.io/rest/mock-data. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:8080' is therefore not allowed access.
{
axios
.get("https://example.restdb.io/rest/mock-data", {
headers: {
"x-apikey": "API_KEY",
},
responseType: "json",
})
.then((response) => {
this.setState({ tableData: response.data });
});
}
I have also read several answers on Stack Overflow about the same issue, titled Access-Control-Allow-Origin
but still couldn't figure out how to solve this. I don't want to use an extension in Chrome or use a temporary hack to solve this. Please suggest the standard way of solving the above issue.
After trying out few answers I have tried with this,
headers: {
'x-apikey': '59a7ad19f5a9fa0808f11931',
'Access-Control-Allow-Origin' : '*',
'Access-Control-Allow-Methods':'GET,PUT,POST,DELETE,PATCH,OPTIONS',
},
Now I get the error as,
Request header field Access-Control-Allow-Origin is not allowed by Access-Control-Allow-Headers in preflight response
I'll have a go at this complicated subject.
What is origin?
The origin itself is the name of a host (scheme, hostname, and port) i.g. https://www.google.com
or could be a locally opened file file://
etc.. It is where something (i.g. a web page) originated from. When you open your web browser and go to https://www.google.com
, the origin of the web page that is displayed to you is https://www.google.com
. You can see this in Chrome Dev Tools under Security
:
The same applies for if you open a local HTML file via your file explorer (which is not served via a server):
What has this got to do with CORS issues?
When you open your browser and go to https://website.com
, that website will have the origin of https://website.com
. This website will most likely only fetch images, icons, js files and do API calls towards https://website.com
, basically it is calling the same server as it was served from. It is doing calls to the same origin.
If you open your web browser and open a local HTML file and in that html file there is javascript which wants to do a request to google for example, you get the following error:
The same-origin policy tells the browser to block cross-origin requests. In this instance origin null
is trying to do a request to https://www.google.com
(a cross-origin request). The browser will not allow this because of the CORS Policy which is set and that policy is that cross-origin requests is not allowed.
Same applies for if my page was served from a server on localhost:
Localhost server example
If we host our own localhost API server running on localhost:3000 with the following code:
const express = require('express')
const app = express()
app.use(express.static('public'))
app.get('/hello', function (req, res) {
// res.header("Access-Control-Allow-Origin", "*");
res.send('Hello World');
})
app.listen(3000, () => {
console.log('alive');
})
And open a HTML file (that does a request to the localhost:3000 server) directory from the file explorer the following error will happen:
Since the web page was not served from the localhost server on localhost:3000 and via the file explorer the origin is not the same as the server API origin, hence a cross-origin request is being attempted. The browser is stopping this attempt due to CORS Policy.
But if we uncomment the commented line:
const express = require('express')
const app = express()
app.use(express.static('public'))
app.get('/hello', function (req, res) {
res.header("Access-Control-Allow-Origin", "*");
res.send('Hello World');
})
app.listen(3000, () => {
console.log('alive');
})
And now try again:
It works, because the server which sends the HTTP response included now a header stating that it is ok for cross-origin requests to happen to the server, this means the browser will let it happen, hence no error.
How to fix things (One of the following)
- Serve the page from the same origin as where the requests you are making reside (same host).
- Allow the server to receive cross-origin requests by explicitly stating it in the response headers.
- If using a reverse proxy such as NGINX, configure NGINX to send response headers that allow CORS.
- Don't use a browser. Use cURL for example, it doesn't care about CORS Policies like browsers do and will get you what you want.
Example flow
Following is taken from: https://web.dev/cross-origin-resource-sharing/#how-does-cors-work
Remember, the same-origin policy tells the browser to block cross-origin requests. When you want to get a public resource from a different origin, the resource-providing server needs to tell the browser "This origin where the request is coming from can access my resource". The browser remembers that and allows cross-origin resource sharing.
-
Step 1: client (browser) request When the browser is making a cross-origin request, the browser adds an Origin header with the current origin (scheme, host, and port).
-
Step 2: server response On the server side, when a server sees this header, and wants to allow access, it needs to add an Access-Control-Allow-Origin header to the response specifying the requesting origin (or * to allow any origin.)
-
Step 3: browser receives response When the browser sees this response with an appropriate Access-Control-Allow-Origin header, the browser allows the response data to be shared with the client site.
More links
Here is another good answer, more detailed as to what is happening: https://stackoverflow.com/a/10636765/1137669
If your backend support CORS, you probably need to add to your request this header:
headers: {"Access-Control-Allow-Origin": "*"}
[Update] Access-Control-Allow-Origin is a response header - so in order to enable CORS - you need to add this header to the response from your server.
But for the most cases better solution would be configuring the reverse proxy, so that your server would be able to redirect requests from the frontend to backend, without enabling CORS.
You can find documentation about CORS mechanism here: https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS
I had a similar problem and I found that in my case the withCredentials: true
in the request was activating the CORS check while issuing the same in the header would avoid the check:
Reason: expected ‘true’ in CORS header ‘Access-Control-Allow-Credentials’
Do not use
withCredentials: true
but set
'Access-Control-Allow-Credentials':true
in the headers.
I had the same error. I solved it by installing CORS in my backend using npm i cors
. You'll then need to add this to your code:
const cors = require('cors');
app.use(cors());
This fixed it for me; now I can post my forms using AJAX and without needing to add any customized headers.