Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

No 'Access-Control-Allow-Origin' react express docker app

I am using docker to run a front end react application and a node/express api. The react app is running on localhost:3000 and the api is running on localhost:9000. They are both fully functioning and working apps. However when I try to make a rest call from the React app to http://localhost:9000/api/whatever I am getting the following error

XMLHttpRequest cannot load http://localhost:9000/api/schedule. No
Access-Control-Allow-Origin' header is present on the requested 
resource. Origin 'http://localhost:3000' is therefore not allowed access.`

This is my server.js file for my express api :

const express = require('express');
const port = process.env.PORT || 9000;

const app = express();

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

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

    // 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();
});
app.listen(port, () => {
    console.log('listening on port : ' + port);
})

Not sure what I'm missing here.

Chrome network tab :

Request URL:http://localhost:9000/api/schedule
Request Method:GET
Status Code:200 OK
Remote Address:[::1]:9000
Response Headers
view source
Connection:keep-alive
Content-Length:86
Content-Type:application/json; charset=utf-8
Date:Mon, 10 Apr 2017 04:40:06 GMT
ETag:W/"56-l2wi6AdD2GGTOMvRjRYO96YmR0w"
X-Powered-By:Express
Request Headers
view source
Accept:application/json, text/plain, */*
Accept-Encoding:gzip, deflate, sdch, br
Accept-Language:en-US,en;q=0.8
Connection:keep-alive
Host:localhost:9000
Origin:http://localhost:3000
Referer:http://localhost:3000/
User-Agent:Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36
like image 762
erichardson30 Avatar asked Apr 10 '17 04:04

erichardson30


People also ask

Why am I getting this error in my react and/or express app?

Getting this error in your React and/or Express app? No ‘Access-Control-Allow-Origin’ header is present on the requested resource. You’ve run afoul of the Same Origin Policy – it says that every AJAX request must match the exact host, protocol, and port of your site.

Why can't I access the URL that served my react application?

1 In simple words: You are trying to access a different url (in your case a localhost with different port) then the url that served your react application. You can solve this by changing your server side code to both serve the app AND listen to API requests. – RtmY

Where is the ‘Access-Control-Allow-Origin’ header?

No ‘Access-Control-Allow-Origin’ header is present on the requested resource. You’ve run afoul of the Same Origin Policy – it says that every AJAX request must match the exact host, protocol, and port of your site.

Why is Access-Control-Allow-Origin missing from my Ajax request?

No ‘Access-Control-Allow-Origin’ header is present on the requested resource. You’ve run afoul of the Same Origin Policy – it says that every AJAX request must match the exact host, protocol, and port of your site. Things that might cause this:


1 Answers

I have been able to do this before with the following configuration:

app.use((req, res, next) => {
  const origin = req.get('origin');

  // TODO Add origin validation
  res.header('Access-Control-Allow-Origin', origin);
  res.header('Access-Control-Allow-Credentials', true);
  res.header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE');
  res.header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept, Authorization, Cache-Control, Pragma');

  // intercept OPTIONS method
  if (req.method === 'OPTIONS') {
    res.sendStatus(204);
  } else {
    next();
  }
});

As you can see in my case I was allowing more methods than only the GET one and added additional allowed headers (such as the Authorization one that I needed in this case), notice that in your case you specified only X-Requested-With and Content-Type, but you might as well need the Origin one if you want to validate the origin.

I am as well intercepting the OPTIONS request to avoid sending additional data in that case.

like image 199
oirad Avatar answered Sep 20 '22 11:09

oirad