Search code examples
node.jsreactjsaxioscorssails.js

Sails, React and Axios Error with CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource


I have really researched this problem and nothing is clear for SailsJS. I'm running the sails and react locally with npm start.

The verions:

  • Sailsjs: 1.4.0
  • ReactJS: ^16.13.1
  • Axios: ^0.19.2
  • Node: v15.0.1

The error: Access to XMLHttpRequest at 'http://localhost:1337/User/Read/2' from origin 'http://localhost:3000' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

I really checked the tickets in stackoverflow.com and the docu in sails, also tested the different solutions and options, the only way I can work is with Moesif Origin & CORS Changer widget in chrome, but I need config the headers and the security for prod:

https://sailsjs.com/documentation/concepts/security/cors, https://sailsjs.com/documentation/reference/configuration/sails-config-security

Request Headers:

GET /User/Read/2 HTTP/1.1
Host: localhost:1337
Connection: keep-alive
Pragma: no-cache
Cache-Control: no-cache
Accept: application/json
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 11_1_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36
Origin: http://localhost:3000
Sec-Fetch-Site: same-site
Sec-Fetch-Mode: cors
Sec-Fetch-Dest: empty
Referer: http://localhost:3000/
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9

My config in security.js for cors in sails is:

module.exports.security = {
  cors: {
    allRoutes: true,
    allowOrigins: ['http://localhost:3000'],
    allowCredentials: false,
    allowRequestHeaders: [
      'X-Powered-By', 
      'Content-Type', 
      'Accept', 
      'Origin',
      'Accept-Encoding',
      'Accept-Language',
      'Connection',
      'Host',
      'Origin',
      'Referer',
      'Sec-Fetch-Dest',
      'Sec-Fetch-Mode',
      'Sec-Fetch-Site',
      'User-Agent',
      'Pragma',
      'Cache-Control',
    ]
  },
  csrf: false
};

The Axios Request in React:

var axios = require('axios');
axios({
      method: 'get',
      headers: {     
        'Accept': 'application/json',
        'Content-Type': 'application/json;charset=UTF-8'},
      url: 'http://localhost:1337/User/Read/2',
    }).then(function (response) {
      console.log(response.data);
});

And the route request:

  'GET /User/Read/:id': {
    controller: "User", 
    action: "read"
  },


Solution

  • In /config/http.js file, uncomment the 'order' array fragment and add header params inside myRequestLogger method.

    order: [
      'startRequestTimer',
      'cookieParser',
      'session',
      'myRequestLogger',
      'bodyParser',
      'handleBodyParserError',
      'compress',
      'methodOverride',
      'poweredBy',
      '$custom',
      'router',
      'www',
      'favicon',
      '404',
      '500'
    ],
    
    
     myRequestLogger: function (req, res, next) {
      res.header('Access-Control-Allow-Origin', '*');
      res.header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept, Authorization');
      res.header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS, HEAD');
      res.header('Allow', 'GET, POST, PUT, DELETE, OPTIONS, HEAD');
      res.header('X-Powered-By', '');
      return next();
    },
    

    Inside /config/cors.js (sails v0.12) or /config/security.js (sails v1.x) add the following code snippet

    module.exports.security = { //sails v1.x, if is sails v0.12 change security for cors
      allRoutes: true,
      allowOrigins: '*',
      allowCredentials: false,
      allowRequestMethods: 'GET,POST,PUT,DELETE,OPTIONS,HEAD',
      allowRequestHeaders: 'content-type'
    }
    

    In case none of this works (which I find difficult to happen), add in the return of your controller method (but, I think it is not necessary):

      return res.set({
        'Content-Type': 'application/json',
        'Access-Control-Allow-Origin': '*',
      }).json({ status: true, //body });