20

So I hit this error, when I was trying to send data to the back end using React. From what I learnt I need to allow the communication on the back-end and in the .htaccess file. Here are some of the links I used:

No 'Access-Control-Allow-Origin' - Node / Apache Port Issue

How does Access-Control-Allow-Origin header work?

Both of them have code, but it didn't help.

So far my Server-side code is this:

app.use(function (req, res, next) {
    // Website you wish to allow to connect
    // res.setHeader('Access-Control-Allow-Origin', 'http://localhost:3000');

    res.setHeader('Access-Control-Allow-Origin', '*');

    // Request methods you wish to allow
    res.setHeader('Access-Control-Allow-Methods', 'POST');

    // Request headers you wish to allow
    res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With,content-type');

    // Set to true if you need the website to include cookies in the requests sent
    // to the API (e.g. in case you use sessions)
    res.setHeader('Access-Control-Allow-Credentials', true);

    // Pass to next layer of middleware
    next();
});

This is my Client-side code:

sendMail(e) {
    e.preventDefault();
    var name = document.getElementById('name').value;
    var contactReason = document.getElementById('contactReason').value;
    var email = document.getElementById('email').value;
    var additionalInfo = document.getElementById('additionalInfo').value;
    var body = {
        name: name,
        contactReason: contactReason,
        email: email,
        additionalInfo: additionalInfo,
    };
    console.log(JSON.stringify(body));
    fetch('http://localhost:4000/', {
        method: 'POST',
        body: body,
    }).then(r => console.log(r)).catch(e => console.log(e));
}

So what am I missing? I do not have an .htaccess file, but I'm doing it all locally so I'm not sure if I can even use it.

It looks to me like I'm allowing all I need, but I guess it's not enough.

If you're going to mark as a duplicate, please at least make sure my issues are covered by the answer.

Alex Ironside
  • 4,658
  • 11
  • 59
  • 119

6 Answers6

40

There's a node package called cors which makes it very easy.

$npm install cors

const cors = require('cors')

app.use(cors())

You don't need any config to allow all.

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

barro32
  • 2,559
  • 23
  • 36
9

One reason might be you're using the route as localhost:8000 rather than http://localhost:8000.

USE

http://localhost:8000

DON'T USE

localhost:8000
Sachin Shukla
  • 335
  • 3
  • 3
5

if you add this header

res.setHeader('Access-Control-Allow-Origin', '*');

you're using credential mode (means you're sending some authentication cookie from your app) and as for CORS specification you cannot use the wildcard * in this mode.

you should change your Access-Control-Allow-Origin header to match the specific host who generated the request

you can change this line:

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

to

res.header('Access-Control-Allow-Origin', 'the ip address');

but to be more generic, something like this should work:

res.setHeader('Access-Control-Allow-Origin', req.header('origin') 
|| req.header('x-forwarded-host') || req.header('referer') || req.header('host'));

in addition you have even to allow OPTIONS requests from the browser otherwise you will get a preflight request error.

res.setHeader('Access-Control-Allow-Methods', 'POST, OPTIONS');
Karim
  • 8,454
  • 3
  • 25
  • 33
4

To anyone else that this may help, I was using axios with withCredentials: true.

On my Express backend, I was simply doing,

app.use(cors())

What fixed it was either removing withCredentials: true from the React frontend or changing my backend to,

app.use(cors({ credentials: true }))
Mike K
  • 7,621
  • 14
  • 60
  • 120
0

you have to allow OPTIONS method as well

res.setHeader('Access-Control-Allow-Methods', 'POST, OPTIONS');

the browser send it with any post request to other domain to check how it will communicate with this remote server.

Peter Wilson
  • 4,150
  • 3
  • 35
  • 62
0

Added core with its options worked well(express V.4.18.2)

const cors = require('cors') 

const corsOptions = { 
  // origin:'https://abc.onrender.com',
  AccessControlAllowOrigin: '*',  
  origin: '*',  
  methods: 'GET,HEAD,PUT,PATCH,POST,DELETE' 
}
app.use(cors(corsOptions))

if you are sending authentication cookie/ login stuff from your app then add the API url for the origin as bellow.

 const cors = require('cors')

  const corsOptions = {
    AccessControlAllowOrigin: '*',
    origin: 'https://abc.onrender.com',
    methods: 'GET,HEAD,PUT,PATCH,POST,DELETE'
  }
  app.use(cors(corsOptions))
Amir Danish
  • 418
  • 5
  • 8