0

I have a React application and Nodejs(Express) in the Backend. After deploying to the host server, The function I did for updating some documents stop working properly. It gives the CORS error:

enter image description here

I have this line of code to handle CORS policy in my server.js:

app.use((req, res, next) => {
  res.set({"Access-Control-Allow-Origin" : "*", 
           "Access-Control-Allow-Methods" : "HEAD, OPTIONS, GET, POST, PUT, PATCH, DELETE", 
           "Access-Control-Allow-Headers" : "Content-Type, Authorization, X-Requested-With"})
  next();
});

It is ok for GET and POST methods but does not work for PUT (Don't know if Delete works haven't tried)

I am on this issue for plenty of time; tried this: https://stackoverflow.com/a/42463858/11896129

looked for a bunch of solutions on the net, tried to configure it from IIS web.config file, nothing resolve my problem. Which part may I miss?

Oner T.
  • 394
  • 1
  • 7
  • 22
  • [related](https://stackoverflow.com/questions/7067966/why-doesnt-adding-cors-headers-to-an-options-route-allow-browsers-to-access-my) – Jonas Wilms Mar 11 '20 at 07:49
  • Have you tried using the `cors` nodeJS module? It might do the job for you. – Tomafa06 Mar 11 '20 at 08:56
  • I did it also. I am now trying to configure from its npm page: https://www.npmjs.com/package/cors#configuring-cors but still no result – Oner T. Mar 11 '20 at 08:57
  • What’s the HTTP status code of the response? You can use the Network pane in browser devtools to check. Is it a 4xx or 5xx error rather than a 200 OK success response? – sideshowbarker Mar 11 '20 at 11:01
  • @sideshowbarker https://i.hizliresim.com/Am1zzU.png – Oner T. Mar 11 '20 at 11:20
  • @sideshowbarker When I click it, it gives my "failed token" message, which I configured in my auth.js middleware in the backend, it simply checks if the user logged in, before changing a post – Oner T. Mar 11 '20 at 11:22
  • 1
    _I have a React application and Nodejs(Express) in the Backend_ - The best way to solve the CORS problem is to eliminate it by serving React script bundles from the backend server. See [this](https://github.com/winwiz1/crisp-react/) project (I'm the author) and search README for _CORS_. – winwiz1 Mar 12 '20 at 09:08
  • Thanks, I took a look but didn't understand exactly. Is it a server-side rendering app like Next.js? – Oner T. Mar 12 '20 at 11:10
  • 1
    Currently there is no SSR. Coming back to CORS, the result of the React application build are files: `.html` pages, `.js` script bundles with React code and optionally `.map` files. All these files are called build artifacts. If you make Express serve the build artifacts then client's browser gets everything (build artifacts and API responses) from the single backend server. This leaves to room for CORS. So there is no need for CORS headers and packages that send these headers. – winwiz1 Mar 12 '20 at 11:43
  • hmm, But why this CORs config I made doesn't work? I mean I am executing all the details, OPTIONS, preflight, etc. what is the problem right now, right here ? – Oner T. Mar 12 '20 at 14:08
  • 1
    Try disabling all your extensions, and/or try in an Incognito window. And try clearing the cookies and your browser cache for the site. And disable any anti-virus software you have installed. And try from a different browser, and from a different machine, and from a different network. The point being to eliminate the possibility that some other software running or your machine might be interfering with the request, and eliminate the possibility that some firewall setting is interfering with, etc. – sideshowbarker Mar 13 '20 at 08:08
  • _what is the problem right now, right here_ You got a very reasonable [answer](https://stackoverflow.com/a/60631328/12005425). It tells you (along with the supplied links) that `PUT` requires a preflight request. The error screenshot you provided suggests that either (a) this request is not sent or (b) the response is not received from `reactback.2ccrm.org` or (c) this response is received and contains a rejection/error or (d) this response is received without the HTTP header your red error message complains about as being not present. So I'd suggest start looking at (a)-(d) using DevTools. – winwiz1 Mar 13 '20 at 09:15
  • @OnerT. how do you serve your application to the server? Apache or Nginx proxy? Maybe the proxy server blocks CORS related requests. – Christos Lytras Mar 13 '20 at 12:48
  • @ChristosLytras it is Plesk Obsidian for Windows – Oner T. Mar 13 '20 at 12:50
  • @OnerT. if the issue only occurs in the `localhost`, download a browser plugin called `Cors Everywhere` . that shoudl solve it right away – Abdullah Abid Mar 18 '20 at 16:03

7 Answers7

5

As stated on MDN:

Additionally, for HTTP request methods that can cause side-effects on server's data (in particular, for HTTP methods other than GET, or for POST usage with certain MIME types), the specification mandates that browsers "preflight" the request, soliciting supported methods from the server with an HTTP OPTIONS request method, and then, upon "approval" from the server, sending the actual request with the actual HTTP request method.

So you do have to answer preflight requests:

  app.options("*", (req, res) => {
    res.status(200).send("Preflight request allowed");
  });

Read more about preflight requests here.

Jonas Wilms
  • 132,000
  • 20
  • 149
  • 151
  • @Jonas Does [`cors`](https://www.npmjs.com/package/cors) package add `options` by default? Because I have an express server that serves a `PUT` request and I don't add any `options` handling just the `cors` package. – Christos Lytras Mar 13 '20 at 12:37
  • @ChristosLytras yes, it does, as you can see [in the sourcecode](https://github.com/expressjs/cors/blob/c3c262bae2fa9ef0b1fbdad2f6cb922f78cfaa40/lib/index.js#L180) – Jonas Wilms Mar 14 '20 at 14:15
  • Can you show the order of your registration of your middlewares for your `express` server? These options and the `CORs` headers that you are using look good. – jeeves Mar 19 '20 at 14:15
2

This should work, I used this CORS configuration

  app.use(function(req,res,next){
    res.header("Access-Control-Allow-Origin", "*");
    res.header("Access-Control-Allow-Methods", "GET, PUT, POST, DELETE, PATCH");
    res.header("Access-Control-Allow-Headers", "Accept, Content-Type, Authorization, X-Requested-With");

    next();
  });
Adeel Nawaz
  • 398
  • 2
  • 10
  • Nope, not working. I 've tried lots of variations of these, no use – Oner T. Mar 11 '20 at 09:44
  • do you test with "Access-Control-Allow-Origin", "*" – Adeel Nawaz Mar 11 '20 at 09:53
  • yep, I did it also. It is ok for POST and GET, PUT doesn't work – Oner T. Mar 11 '20 at 10:22
  • are you using Nginx ? if yes then use this configurations as well . – Adeel Nawaz Mar 15 '20 at 11:05
  • Nginx `add_header Access-Control-Allow-Headers "Authorization";` – Adeel Nawaz Mar 15 '20 at 11:06
  • share your request code here as well , as get and post is working as they are only using in login and register before session but put is using after login in session so error is only due to Authorization header – Adeel Nawaz Mar 15 '20 at 11:20
  • please remove all cors settings and i updated new code use this as app middleware before routes – Adeel Nawaz Mar 15 '20 at 11:21
  • 1
    `app.use(function(req,res,next){ res.header("Access-Control-Allow-Origin", "*"); res.header("Access-Control-Allow-Methods", "GET, PUT, POST, DELETE, PATCH"); res.header("Access-Control-Allow-Headers", "Accept, Content-Type, Authorization, X-Requested-With"); next(); });` – Adeel Nawaz Mar 15 '20 at 11:22
  • sorry not working, I think the problem is different, I will reset all stuff and try again – Oner T. Mar 16 '20 at 06:19
2

Most likely the error No 'Access-Control-Allow-Origin' header is present that you see is coming from the preflight OPTIONS request, which is most likely not even reaching your express backend but is being hanlded by webserver in the front.

Either arrange for OPTIONS requests also to be relayed to your express backend in your webserver configuration or instruct the webserver to respond to it with required headers.

Check these:

https://support.plesk.com/hc/en-us/articles/115001338265-How-to-set-up-CORS-cross-origin-resource-sharing-in-Plesk-for-Linux-

https://support.plesk.com/hc/en-us/articles/360005431913-Is-it-possible-to-enable-CORS-cross-origin-resource-sharing-on-Plesk-for-Windows

https://talk.plesk.com/threads/iis-cors-configuration-problem-for-node-js-backend.355677/

ckedar
  • 1,859
  • 4
  • 7
1

You can use npm package cors (https://www.npmjs.com/package/cors) in your project. Install it and then configure it as a middleware. And put it before your application routes.

 const cors = require("cors");

    const corsOptions = {   origin: "*",   methods:
    "GET,HEAD,PUT,PATCH,POST,DELETE",   allowedHeaders:
        "Access-Control-Allow-Headers,Access-Control-Allow-Origin,Access-Control-Request-Method,Access-Control-Request-Headers,Origin,Cache-Control,Content-Type,X-Token,X-Refresh-Token",   credentials: true,   preflightContinue: false,  
    optionsSuccessStatus: 204 };

    app.use(cors(corsOptions));
Asif Iqbal
  • 502
  • 6
  • 24
  • Brother Oner, I am using the same in my project and it's working. – Asif Iqbal Mar 11 '20 at 12:00
  • I understand but it is not working in mine. I tried lots of variants of these cors package, also did it with manually setting headers etc. There should be another way, because, in the backend, I have routes and auth middleware like any other usual app, nothing exceptional but still doesn't work. I can share whole app.js and routes also – Oner T. Mar 11 '20 at 12:03
0

Please try with below configuration

const cors = require('cors');
app.use(cors())

Please let me know if works for you or not.

See the Github repo for more info: https://github.com/expressjs/cors

Vaibhav Bhuva
  • 445
  • 4
  • 15
0

We can use npm package to enable this too

npm install --save cors

After package is in place, use it as middleware as follows.

var express = require('express');
var cors = require('cors');
var app = express();
app.use(cors());

If you have requirement to confine your resource access to single application, that can be done as following

app.use(cors({
  origin: 'http://yourapp.com'
}));

If you have requirement to add access to multiple applications, that can be done as follows

var allowedOrigins = ['http://localhost:3000',
                      'http://yourapp.com'];
app.use(cors({
  origin: function(origin, callback){
    // allow requests with no origin 
    // (like mobile apps or curl requests)
    if(!origin) return callback(null, true);
    if(allowedOrigins.indexOf(origin) === -1){
      var msg = 'The CORS policy for this site does not ' +
                'allow access from the specified Origin.';
      return callback(new Error(msg), false);
    }
    return callback(null, true);
  }
}));
0

Did you write middleware that attaches header before the line of code that handles PUT request? I have a similar code but it worked for me. Another approach is to use npm 'cors' module.

For testing purpose, you can attach below test (you can attach the specific headers/methods later):

res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Headers', '*');
res.header('Access-Control-Allow-Methods', '*');