Express CORS not working - node.js

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.

Related

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.

nodejs post method not getting called

I found my question was asked a year ago here app.post() not working with Express but the code written there is outdated (the way bodyparser was added doesn't work anymore as well as function mentioned below) plus the asker never chose an answer so the question was never solved.
Here's my code
const express = require("express");
const db = require("mysql");
const app = express();
const bodyParser = require("body-parser");
const multer = require("multer"); // v1.0.5
const upload = multer(); // for parsing multipart/form-data
const http = require("http");
const path = require("path");
app.set("view engine", "jade");
app.set("views", path.join(__dirname));
console.log("before");
app.listen(8000, () => {
console.log("Server started!");
console.log("within");
});
console.log("after");
app.use(bodyParser.json()); // for parsing application/json
app.use(bodyParser.urlencoded({ extended: true })); // for parsing application/x-www-form-urlencoded
app.post("/", function(req, res) {
console.log("hit here in post");
res.render("index.jade", {});
console.log("hit here in post");
res.json({ name: "John" });
res.status(500).json({ error: "message" });
res.end();
});
app.get("/", function(req, res) {
res.render("index.jade", {});
console.log("hit here in get");
console.log(req.body);
});
Here's the output.
before
after
Server started!
within
hit here in get
{}
I even tried to wrap the app sets and uses in app.configure like the asker of the other question to see if that was the issue but that configure function doesn't seem to exist anymore because I got an error about it.
Also I should probably note. My routing here is correct. I haven't made a views subfolder yet so that's why I have it written as it is.
Update
I think I may have spotted the issue but I don't understand why it's occurring. In the network tab of the browser I see that GET is getting 404 error because of a favicon.ico request but I don't understand where that request is coming from. I've seen the serve-favicon npm module to support it but didn't want to added because I never intended to add a favicon image to my server. I don't even understand how that would work.
Reply to last comment by James
What do you mean by I configure the middleware after it has started? Are you referring to the fact that the post method is written after port listening has started? Also if that's the reason why post isn't executing how come the get method executes regardless of that? I'm not holding back any server code aside from code I currently have commented out for the moment but that code I posted is my main index.js file and it's the only file I modified from the standard npm init project. I haven't setup any routes because I don't see the need to do so (even when I add react since my project is simple in concept of communication between reactjs, nodejs and a database "hence my frustration") which is why I'm trying to have get and post only access the root directory.
favicon is automatically requested by the browser. it is the icon used in the browser tab or url address bar
Add this, before app.get():
app.all('/', function(req, res, next) {
console.log({method: req.method, url: req.url});
next();
});

Webpack proxy messing up my routing?

So I'm using webpack for a project on 8080 with a backend on 3000. The proxy seems to work fine, as I can send requests to the backend and access it without issue. However. I need to include this middleware that allows me to have a user load the page, and if they've logged in within a certain amount of time, the initial request they send to the server logs them in automatically.
router.use(function (req, res, next) {
//check token for routes beneath vvvv
})
router.post('/preauth', function (req, res) {
//return user account info if req.token is valid
})
When I try to get to prauth, or even any route before that from the page loaded on 8080 I only touch the middleware and nothing else.
When I do npm run build then try it again from the identical page on 3000, it works as expected.
No, CORS is not enabled and the proxy does not rewrite any url.
Does anyone know if something in my Webpack config might be causing this?
You need install Cors in nodejs:npm install cors, you can try the following below or you see: Nodejs + Vuejs
var express = require('express')
var cors = require('cors')
var app = express()
app.use(cors())
app.get('/products/:id', function (req, res, next) {
res.json({msg: 'This is CORS-enabled for all origins!'})
})
app.listen(80, function () {
console.log('This is a CORS-enabled web server listening on port 80')
})

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.

POST Request to expressjs not working despite using CORS

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.

Resources