POST Request to expressjs not working despite using CORS - node.js

I've got this function in my component, that's supposed to send a POST request to an express API:
onSubmit (evt) {
evt.preventDefault();
//alert(JSON.stringify(this.description));
axios.post('http://localhost:3000/api/v1/addComment', {
articleid: this.id,
description: this.description
});
}
This is the API to which the request is being sent:
router.post('/api/v1/addComment/', function(req, res){
var newComment = req.body;
//newComment.id = parseInt(commentsData.length);
commentsData.comments.push(newComment);
fs.writeFile('app/data/comments.json', JSON.stringify(commentsData), 'utf8', function(err){
console.log(err);
});
res.setHeader("Access-Control-Allow-Origin", "*");
res.json(newComment);
});
I've also required the the neccessary CORS dependency in my express, app.js file
var express = require('express');
var reload = require('reload');
var app = express();
var cors = require('cors');
var dataFile = require('./data/articles.json');
app.set('port', process.env.PORT || 3000 );
//app.set('appData', dataFile);
app.set('view engine', 'ejs');
app.set('views', 'app/views');
app.use(express.static('app/public'));
app.use(require('./routes/index'));
app.use(require('./routes/comments'));
app.use(cors());
var server = app.listen(app.get('port'), function(){
console.log('Listening on port ' + app.get('port'));
});
reload(server, app);
The API routes work fine, when I do get requests, however, I keep getting this error when I do a post request:
Failed to load http://localhost:3000/api/v1/addComment: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:8080' is therefore not allowed
access. createError.js?16d0:16 Uncaught (in promise) Error: Network Error at createError (createError.js?16d0:16) at XMLHttpRequest.handleError (xhr.js?ec6c:87)
I've also tried sending a headers object along with the axios post request, but to no avail.
Based on my research into CORS, I understand that Using CORS is neccessary to allow requests to your API, coming from a different domain.
My express server runs on localhost 3000, while my vue server runs at local host 8080.
Could someone explain why I'm still getting this error despite requiring and using CORS in express?

Try moving the
app.use(cors())
up before you assign the routes

The pre-flight part is referring to xhr making a OPTIONS request to /api/v1/addComment before the actual POST. You'll need to configure cors to handle that:
// preflight for aspecific route
router.options('/api/v1/addComment/', cors())
// or preflight for all routes
router.options('*', cors())
Note: you'll want to make these calls before defining the rest of the routes. See the docs on npmjs.

Related

HTTPS Server CORS Issue

So I have a NodeJS Express server which I am switching over from http to https. I have two files starting this:
app.js which defines the express part of the server, sets headers etc...
const express = require('express');
const app = express();
const dataRoutes = require('./routes/data');
app.use((req, res, next) => {
res.setHeader("Access-Control-Allow-Origin", "*"); //"https://www.wordleleague.org");
res.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, Authorization");
res.setHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
next();
})
app.use("/api/data", dataRoutes);
module.exports = app;
and server js which is the main part of the code, the launched file:
const app = require("./app");
const https = require("https");
const fs = require("fs");
const port = normalizePort(process.env.PORT || "3000");
app.set("port", port);
const httpsOptions = {
key: fs.readFileSync('key.pem'),
cert: fs.readFileSync('cert.pem')
};
const server = https.createServer(httpsOptions, app);
server.listen(port);
Whilst this all worked fine when I was using http, now I get a CORS error when trying to query this:
Cross-Origin Request Blocked: The Same Origin Policy disallows reading
the remote resource at https://localhost:3000/api/data/login. (Reason:
CORS header ‘Access-Control-Allow-Origin’ missing). Status code: 499.
It looks like the express app object isnt being used by the createServer. This all worked in http but its when I tried adding the credentials to the object for https that it went wrong.
If there is any further info anybody needs I am happy to provide, but this seems like all that is relevant. The requests are not being routed to the appropriate method and the http call from the angular app is definatele working.
Edit - The call to the server and more error detail
This is the code which calls the server:
this.subscriptions['leaguesub'] = this.http.get<{success: boolean, data: League[]}>(environment.apiUrl+'api/data/all/userId=' + id).subscribe({
next: (result: {success: boolean, data: League[]}) => {
this.leaguesLocal = [...result.data];
this.leagues.next([...this.leaguesLocal]);
}})
Works fine when I am using http. The only header which is added is an authorisation token:
req.headers.set('Authorization', "Bearer " + token)
The error it seems is a 499:
Status 499 Request has been forbidden by antivirus Referrer Policy
strict-origin-when-cross-origin
edit 2
If I reverse the order of createserver arguments then the CORs issue goes away but I have a new, different CORs issue:
const server = https.createServer(app, httpsOptions);
Cross-Origin Request Blocked: The Same Origin Policy disallows reading
the remote resource at https://localhost:3001/api/user/login. (Reason:
CORS request did not succeed). Status code: (null).
One of the comments suggests using a CORs module but im not sure why my code isnt working
edit 3
Ok so I modified the main app.js express file to reflect the CORS suggestion made below:
const cors = require('cors');
const app = express();
app.use(cors());
And the error is persistent. Still no luck connecting to the server or any idea how to debug it. I tried using these methods to check a connection:
app.post("*", (req, res, next) => {
console.log(`post here`);
next();
})
app.get("*", (req, res, next) => {
console.log(`get here`);
next();
})
But alas I get no info from the concole about these running the event of a call being made to the API. Same errors as before.
edit 4
Running in Chrome gives me a new info source:
ERR_SSL_VERSION_OR_CIPHER_MISMATCH
Looking this up it seems there may be a problem with the SSL certificate. It is a self created SSL certificate which normally requires you to press ALLOW or something. It would explain why there seems to be nothing getting through to the server whatsoever as my browser is blocking it.
The problem then it how to get around this?

No 'Access-Control-Allow-Origin' header is present on the requested resource in Express app

I have an Express app running on same server with my Web app. I'm trying to make a XMLHttpRequest to my Express app and I get this error:
Access to XMLHttpRequest at 'http://10.0.0.222:9999/' from origin 'http://10.0.0.222:8080' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.
Though in my app this header is clearly 'present'.
App code:
var cors = require('cors')
const util = require('util');
var inspect = require('eyes').inspector({maxLength: false})
const express = require('express');
var bodyParser = require('body-parser')
const app = express();
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
var corsOptions = {
origin: 'http://10.0.0.222:8080',
optionsSuccessStatus: 200, // some legacy browsers (IE11, various SmartTVs) choke on 204
}
app.post('/', cors(corsOptions), function (req, res) {
console.dir(req.body, {depth: null});
res.send('a');
});
const PORT = process.env.PORT || 9999;
app.listen(PORT, () => {
console.log(`Server listening on port ${PORT}...`);
});
XMLHttpRequest Code:
var xhr = new XMLHttpRequest();
xhr.open("POST", 'http://10.0.0.222:9999', true);
xhr.setRequestHeader('Content-Type', 'application/json');
xhr.send(goodJSON)
Why do I still get this error even though the origin option has my web app's host included?
It won't work because you have placed the headers in the base route i.e /.
You must check the headers before resolving the route. In your case route is already resolved and then you are applying the cors headers.
Use this:
app.use('/', cors(corsOptions)); or app.use(cors(corsOptions));
app.post('/', function (req, res) {
console.dir(req.body, {depth: null});
res.send('a');
});
Applying cors in app.use will add the headers. After that path will be resolved and it won't throw the error
The error message says:
Response to preflight request
The preflight is an OPTIONS request sent to ask permission to make the actual request.
Your handler only accepts POST requests, so the OPTIONS request doesn't have the required headers on it.
The documentation specifically covers preflight requests:
app.options('/', cors(corsOptions));

Node Express Cors issue

I cant figure why the cors express middleware wont work. cors, express, and ejs are all saved in package.json. The app works fine if I add corsanywhere proxy on the front end but id like to work around this on the server side. any help much appreciated I've been stuck on this.
the api is in the get View/index path
the error is:
Access to fetch at 'https://api.darksky.net/forecast/' from origin 'http://localhost:3000' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
const express = require('express');
const app = express();
const ejs = require('ejs');
const cors = require('cors');
const PORT = process.env.PORT || 3000;
// app.use((req, res, next) => {
// res.header('Access-Control-Allow-Origin', '*')
// res.header('Access-Control-Allow-Headers', 'Origin', 'X-Requested-With')
// next();
// });
app.use(cors());
app.use(express.static(__dirname + '/Public'));
app.set('view engine', 'ejs');
app.get('/', cors(), (req, res) => {
res.render(__dirname + '/Views/index')
});
app.listen(PORT, () => {
console.log(`server is listening on ${PORT}`)
});
client side:
it works with the ${proxy} in there but id like to get rid of that
if(navigator.geolocation){
navigator.geolocation.getCurrentPosition(position => {
long = position.coords.longitude;
lat = position.coords.latitude;
var proxy = 'https://cors-anywhere.herokuapp.com/'
var api = `${proxy}https://api.darksky.net/forecast/042750f3abefefdfe2c9d43cf33ce576/${lat},${long}`;
fetch(api)
.then(response => {
return response.json();
})
.then(data => {
let {temperature, summary, icon,} = data.currently;
temperatureDegree.textContent = Math.floor(temperature);
temperatureDescription.textContent = summary;
locationTimezone.textContent = data.timezone;
setIcons(icon, document.querySelector('.icon'
w
``````
So, if you're trying to access some other service https://api.darksky.net/forecast/ (that you don't control) from your web page, then there is nothing you can do to make CORs work for that. It's up to the api.darksky.net server to decide if CORs is allowed or not. You can't change that.
You could make a request from your web page to your server to ask it to get some data from api.darksky.net for you and then return it back to your webpage (working as a simple proxy). Your server is not subject to any CORs limitations when accessing api.darksky.net. Only browsers are limited by CORs.
And, as you've found, you can also use a proxy service that enables CORs and fetches data for you.
Let's suppose you want to proxy the parts of the darksky API, you could do something simple like this:
const express = require('express');
const app = express();
const request = require('request');
const apiRouter = express.Router();
// maps /api/forecast/whatever to http://api.darksky.net/forecast/developerKey/whatever
// and pipes the response back
const apiKey = "yourAPIKeyHere";
apiRouter.get("/*", (req, res, next) => {
// parse out action and params
// from an incoming URL of /api/forecast/42.3601,-71.0589
// the /api will be the root of the router (so not in the URL here)
// "forecast" will be the action
// "42.3601,-71.0589" will be the params
let parts = req.path.slice(1).split("/"); // split into path segments, skipping leading /
let action = parts[0]; // take first path segment as the action
let params = parts.slice(1).join("/"); // take everything else for params
request({
uri: `https://api.darksky.net/${action}/${apiKey}/${params}`,
method: "get"
}).pipe(res);
});
app.use("/api", apiRouter);
app.listen(80);
Now, when you send this server, this request:
/api/forecast/42.3601,-71.0589
it will request:
https://api.darksky.net/forecast/yourAPIKeyHere/42.3601,-71.0589
and pipe the result back to the caller. I ran this test app and it worked for me. While I didn't see anything other than forecast URLs in the darksky.net API, it would work for anything of the format /api/someAction/someParams.
Note, you probably do NOT want to enable CORS on your server because you don't want other people's web pages to be able to use your proxy. And, since you're just sending requests to your own server now, you don't need CORS to be able to do that.

API Management on IBM Cloud for Node.js vs CORS headers

I have an Node.JS application that defines CORS settings. We thought about taking advantage of limitting requests per client-id that comes with 'API Management'. This 'API Management' has it's own CORS enable toggle. But even when 'Off', it seems to overwrite application CORS headers.
Did some experimenting with app like this:
var express = require('express');
var cors = require('cors');
var app = express();
app.get('/hasset', cors({ origin: "http://localhost/" }), function(req, res) {
return res.json({status: "ok", message: "with cors setting"});
});
app.get('/nonset', function(req, res){
return res.json({"status":"ok", "message":"without cors"});
});
var port = (process.env.PORT || 3100);
app.listen(port);
console.log('App started on port ' + port);
Should we wan't to use own CORS settings - does that rule us out of 'API Management' ?
No, you can use API Management and simply turn off the "CORS" option. In that case, the gateway will simply pass through any CORS headers you return manually.

Express CORS not working

I just started my nodejs express template buy cors is not working.
I used npm install cors --save
here is the file:
var express = require('express');
var cors = require('cors');
var app = express();
app.use(cors());
var corsOptions = {
origin: 'https://example.com/',
optionsSuccessStatus: 200
};
app.get('/', cors(corsOptions), function(req, res, next) {
res.json({ message: 'hooray! welcome to our api!' });
});
app.get('/tt', function(req, res, next) {
res.json({ message: 'hooray! welcome to our api!' });
});
var port = process.env.PORT || 3030;
app.listen(port);
console.log('Magic happens on port ' + port);
Now with the above code when I access localhost:3030/tt or / I still see the content and I shouldn't
What's wrong with this.. I just lost like 2 hours working on this.. :(
At this time I would like not to use CORS, but in near future when my app is finished, I want to allow incoming calls only from my project, since this app will be my API.
The behavior you are describing seems is what I would expect.
CORS won't help you filter out incoming calls on the server. In this case the browser's CORS check won't kick-in as it appears you are directly typing in the URL in the browser. Browser does a CORS check only when the the webpage loaded from a particular domain tries to access/submit to a URL in a different domain.
A different way to think about CORS. CORS is intended to protect the user sitting in front of the browser, and not the server-code that is being accessed.

Resources