I am stuck for two complete days with this problem. I read a lot about it, and tried several things. The good side is that I think I now understand what CORS is about, but the bad side is that the issue is still there.
My PROD environment:
- Hosted droplet on digital ocean. Installed NginX as reverse proxy to direct the incoming traffic over https (default port 443) to an internal "React Server" running using command "serve -s build" and listening on port 3000.
- The React server talks to a nodeJS server running on the same droplet listening on port 3500
- The nodeJS server takes care of interfacing with an external mongoDB.
My Dev environment:
- The same as above but running on my Windows laptop using VSCode, and http instead of https.
- No CORS issues faced.
What is the issue:
- Running the PROD environment and accessing it from my browser returns a CORS error.
Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://localhost:3500/employees. (Reason: CORS header ‘Access-Control-Allow-Origin’ missing). Status code: 500.
What did I try:
- Based on my understanding from reading about CORS, I understood that it will be most probably a server side issue (The NodeJS running on port 3500 is not handling CORS properly).
- I checked multiple time how CORS is implemented, and compared to all the recommendations and answers over the internet, and I seemed to be doing the right thing.
- So, I thought of using cURL while enforcing it to provide an "Origin" in its request and see.
- I ran the following two commands from ssh on the droplet command line with the results.
===================================
curl -H "Origin: http://localhost:3000" -v http://localhost:3500/employees/firstname/Arth; echo
===================================
* Trying 127.0.0.1:3500...
* Connected to localhost (127.0.0.1) port 3500 (#0)
> GET /employees/firstname/Arth HTTP/1.1
> Host: localhost:3500
> User-Agent: curl/7.81.0
> Accept: */*
> Origin: http://localhost:3000
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< X-Powered-By: Express
< Access-Control-Allow-Credentials: true
< Access-Control-Allow-Origin: http://localhost:3000
< Vary: Origin
< Content-Type: application/json; charset=utf-8
< Content-Length: 567
< ETag: W/"237-vPb0kecEsX8rIXbwsqXHL/P/Z5w"
< Date: Mon, 19 Sep 2022 07:28:33 GMT
< Connection: keep-alive
< Keep-Alive: timeout=5
<
* Connection #0 to host localhost left intact
[{"_id":"63261071cb56fb978ebfe8bf","firstname":"Arthur","lastname":"Bretherton","email":"abrethertonh@imgur.com","dob":"16/11/1986","age":52,"country":"Thailand","phone":"+66 236 991 7545"},{"_id":"63261071cb56fb978ebfea17","firstname":"Bartholemy","lastname":"Denney","email":"bdenneya1@deliciousdays.com","dob":"09/10/1975","age":48,"country":"China","phone":"+86 721 149 5566"},{"_id":"63261071cb56fb978ebfeb2f","firstname":"Barth","lastname":"Flacknell","email":"bflacknellht@squidoo.com","dob":"22/03/1971","age":44,"country":"China","phone":"+86 880 563 0713"}]
==================================
curl -H "Origin: http://localhost:300" -v http://localhost:3500/employees/firstname/Arth; echo
===================================
* Trying 127.0.0.1:3500...
* Connected to localhost (127.0.0.1) port 3500 (#0)
> GET /employees/firstname/Arth HTTP/1.1
> Host: localhost:3500
> User-Agent: curl/7.81.0
> Accept: */*
> Origin: http://localhost:300
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 500 Internal Server Error
< X-Powered-By: Express
< Content-Type: text/html; charset=utf-8
< Content-Length: 19
< ETag: W/"13-MClrdFoaBMV/BSRr2tsNTknKVAU"
< Date: Mon, 19 Sep 2022 07:29:24 GMT
< Connection: keep-alive
< Keep-Alive: timeout=5
<
* Connection #0 to host localhost left intact
Not allowed by CORS
As seen from the above, when the origin is http://localhost:3000 which is on the white list of my nodeJS CORS Origin array, the call succeed.
const allowedOrigins = require('./allowedOrigins');
const corsOptions = {
origin: (origin, callback) => {
console.log('origin: ', origin);
if (allowedOrigins.indexOf(origin) !== -1 || !origin) {
callback(null, true)
} else {
callback(new Error('Not allowed by CORS'));
}
},
optionsSuccessStatus: 200
}
module.exports = corsOptions;
const allowedOrigins = [
'https://www.yoursite.com',
'http://localhost:3000'
];
module.exports = allowedOrigins;
However when I change the port# to be 300 (just to make it not in my whitelist), it fails with the "Not allowed by CORS" error.
I am deducing from the above test that my nodeJS server is acting correctly. Is this the case?
If so, then what do I need to do special on the React side to make it work?
Here is a part of my code on the React side:
const fetchEmployees = async () => {
try {
const response = await api.get("/employees");
setEmployees(response.data);
);
} catch (err) {
showError(err);
}
};
fetchEmployees();
}
Here is as well the configuration of Nginx in case it comes into play:
location / {
# First attempt to serve request as file, then
# as directory, then fall back to displaying a 404.
# try_files $uri $uri/ =404;
proxy_pass http://localhost:3000;
proxy_buffering off;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Port $server_port;
}