Reputation: 93
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:
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"
},
Upvotes: 0
Views: 4502
Reputation: 855
Make sure to add authorization in allowed header to allow tokens / cookies to be passed to back-end
config/settings.js ->
module.exports.security = {
cors: {
allRoutes: true,
allowOrigins: '*',
allowCredentials: true,
allowAnyOriginWithCredentialsUnsafe: true,
allowRequestHeaders : 'content-type,Authorization'
}
}
Upvotes: 1
Reputation: 36
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 });
Upvotes: 2
Reputation: 111
I just use like this
cors: {
allRoutes: true,
allowOrigins: "*",
allowCredentials: false,
allowRequestHeaders: "*",
}
Make sure to add, client side host in allowOrigins: ['http://mywebsite.com]
on production
Upvotes: 3
Reputation: 93
In the end, I solved it in this way:
On http.js in sails, added the req headers:
module.exports.http = {
middleware: {
order: [
'cookieParser',
'session',
'bodyParser',
'compress',
'poweredBy',
'appRequestLogger', // custom logger
'router',
'www',
'favicon'
],
appRequestLogger: function (req, res, next) {
const env = process.env.NODE_ENV || 'development';
sails.log.debug('<<------------------------------');
sails.log.debug('Requested data :: ');
sails.log.debug(' ', req.method, req.url);
sails.log.debug(' Headers:');
sails.log.debug(req.headers);
if (env.toLowerCase() !== 'production') {
sails.log.debug(' Params:');
sails.log.debug(req.params);
sails.log.debug(' Body:');
sails.log.debug(req.body);
}
sails.log.debug('------------------------------>>');
// This is a work around to allow CORS requests as Sails does not send these
// headers in the response to preflight/actual requests even when they are
// declared in config/security.js under CORS config
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', '');
// Check graphql preflight request, if yes then prevent the request reaching
// the express-graphql server. Currently the express-graphql server only accepts
// GET and POST hence rejects the preflight request. CORS needs that a server
// accepts preflight requests to facilitate cross-site access. Therefore, return
// immediately with a success.
// Otherwise fall through by calling next()
if (req.method === 'OPTIONS' && req.url.indexOf('graphql') > -1) {
return res.status(200).send();
} else {
return next();
}
},
},
};
Upvotes: 1