I'm running an issue with my Angular 2 web app.
On Node JS server side, I got an issue with CORS preflighting.
I want to upload a file on the server, and when I do it, I have this issue :
XMLHttpRequest cannot load http://localhost:4000/upload. Response to preflight request doesn't pass access control check: The value of the 'Access-Control-Allow-Origin' header in the response must not be the wildcard '*' when the request's credentials mode is 'include'. Origin 'http://localhost:3000' is therefore not allowed access. The credentials mode of requests initiated by the XMLHttpRequest is controlled by the withCredentials attribute.
where localhost:4000 is my server and localhost:3000 is my client.
My server.js file is like this :
require('rootpath')();
var express = require('express');
var app = express();
var cors = require('cors');
var bodyParser = require('body-parser');
var expressJwt = require('express-jwt');
var config = require('config.json');
var multer = require('multer');
app.use(cors());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
// // use JWT auth to secure the api
app.use(expressJwt({ secret: config.secret }).unless({ path: ['/users/authenticate', '/users/register'] }));
// // routes
app.use('/users', require('./controllers/users.controller'));
app.use('/challenges', require('./controllers/challenges.controller'));
// NEW UPLOAD
app.use(function(req, res, next) { //allow cross origin requests
res.setHeader("Access-Control-Allow-Methods", "POST, PUT, OPTIONS, DELETE, GET");
res.header("Access-Control-Allow-Origin", "http://localhost:3000");
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
res.header("Access-Control-Allow-Credentials", true);
next();
});
/** Serving from the same express Server
No cors required */
app.use(express.static('../client'));
app.use(bodyParser.json());
var storage = multer.diskStorage({ //multers disk storage settings
destination: function (req, file, cb) {
cb(null, './uploads/');
},
filename: function (req, file, cb) {
var datetimestamp = Date.now();
cb(null, file.fieldname + '-' + datetimestamp + '.' + file.originalname.split('.')[file.originalname.split('.').length -1]);
}
});
var upload = multer({ //multer settings
storage: storage
}).single('file');
/** API path that will upload the files */
app.post('/upload', function(req, res) {
upload(req,res,function(err){
console.log(req.file);
if(err){
res.json({error_code:1,err_desc:err});
return;
}
res.json({error_code:0,err_desc:null});
});
});
// FIN NEW UPLOAD
// start server
var port = process.env.NODE_ENV === 'production' ? 80 : 4000;
var server = app.listen(port, function () {
console.log('Server listening on port ' + port);
});
The weirdest thing is that, when I remove the following part, the upload is working :
app.use(cors());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
// // use JWT auth to secure the api
app.use(expressJwt({ secret: config.secret }).unless({ path: ['/users/authenticate', '/users/register'] }));
// // routes
app.use('/users', require('./controllers/users.controller'));
app.use('/challenges', require('./controllers/challenges.controller'));
But then, I got other issues :
(I did not include http prefix before localhost due to reputation)
1) zone.js:2019 OPTIONS localhost:4000/users 404 (Not Found)
2) XMLHttpRequest cannot load localhost:4000/users. Response for preflight has invalid HTTP status code 404
3) EXCEPTION: Response with status: 0 for URL: null
4) Uncaught Response {_body: ProgressEvent, status: 0, ok: false, statusText: "", headers: Headers…}
I think we have to fix the cors() part in the first example but I don't know what to really do.
Thanks
UPDATE : After modifying with your code, I'm running a new issue :
XMLHttpRequest cannot load localhost:4000/users. Request header field Authorization is not allowed by Access-Control-Allow-Headers in preflight response
and when I try to upload my file, I got a new issue :
POST localhost:4000/upload 401 (Unauthorized)
I tried to add many origins in an array instead of only localhost:3000, but nothing changes.
Anything else : if I add "Origin","Content-Type","Accept" to the list of headers, I have this following error :
OPTIONS localhost:4000/users net::ERR_CONNECTION_REFUSED.
I got to admit CORS is a bit difficult.
According to the cors docs, https://github.com/expressjs/cors, to enable CORS Pre-Flight you should add the following code:
app.options('*', cors()) // include before other routes
You can also enable it for specific routes:
app.options('/products/:id', cors()) // enable pre-flight request for DELETE request
app.del('/products/:id', cors(), function (req, res, next) {
res.json({msg: 'This is CORS-enabled for all origins!'})
})
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With