React JS NodeJS 500 Error hosted on DigitalOcean Droplet with NginX reverse proxy front end

Viewed 21

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;
        }
0 Answers
Related