I defined my Express js app:
const express = require('express')
var history = require('connect-history-api-fallback');
const path = require('path')
const http = require('http')
const socketio = require('socket.io')
require('./db/mongoose')
const userRouter = require('./routers/user')
const publicDirPath = path.join(__dirname, '../public')
const app = express()
app.use(express.static(publicDirPath))
app.use(history({
index: '../public/index.html'
}))
app.use(express.static(publicDirPath))
app.use(express.json())
app.use(userRouter)
const server = http.createServer(app)
const io = socketio(server)
io.on('connection', socket => {
console.log('New WebSocket connection')
socket.on('join', () => {
socket.emit('message', 'Welcome to the app')
})
})
module.exports = server
Then I use it my index.js file:
const app = require('./app')
const port = process.env.PORT
app.listen(port, () => {
console.log(`Server is up on port ${port}`)
})
When I run the app and send requests from the same port - everything works just fine. But when I try to send requests from different localhost port, ie. 8080, I'm getting cross origin error.
I tried to install cors package and use it as follows:
const cors = require('cors')
app.options('*', cors())
app.use(cors());
And got the same result.
I tried to pass configuration to cors:
app.use(cors({
origin: 'http://localhost:8080'
}));
And still got the same result.
What am I doing wrong and how can I make it work?
When your frontend app tries to make the request to the express server,
The express server is blocking that request because the source of the request (i.e. frontend server) is unknown to the express server
As the request that you are trying to make it out of the domain of the express server. this is the reason where you have to tell the server please accept the request from this origin a.k.a IP Address
and you can achieve the via cors
Let's take a minute to explain what "origin" is in simple words.
When a user browses to a website, he uses an address.
Normally that address is a domain, but when we run our tests we mostly work with local IPs.
For CORS, this doesn't matter. Once you enable Allow-Origins, the server looks at the address the user used to reach the website, and defines it as the "origin" of the request.
Obviously, on a deeper level, everything comes down to IP addresses. But when it comes to CORS, it's more of a high-level security method. It's helps preventing Cross-Site Request-Forgeries for example.
In conclusion, in order for CORS to work,
make sure you allowed the address which the user is using to access the HTTP service.
So, if you're serving a VUE app that's working on http://localhost:8080, and from it calling to an HTTP service on http://localhost:5555, you'll need to do this on the said HTTP service:
app.use(cors({
origin: 'http://localhost:8080'
}));
Related
SOLUTION:
I had my port hardcoded... smh
app.listen(5432, () => {
console.log(`Server is listening on port 5432`)
})
Heroku REQUIRES a process.env.PORT, this solved the issue here:
require("dotenv").config()
const PORT = process.env.PORT || 5432
app.listen(PORT, () => {
console.log(`Server is listening on port ${PORT}`)
})
PROBLEM:
I have a simple ReactJS CRUD form with no validation hosted locally, and a NodeJS Express server hosted on Heroku. Just trying to get cors enabled but nothing I do is setting the headers for the preflight request. Receiving this error:
Access to XMLHttpRequest at
'https://cors-be.herokuapp.com/api/user/create' from origin
'http://localhost:3000' 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.
This is the index.js:
const express = require('express')
const cors = require('cors')
const app = express()
app.use(cors())
app.use(express.json())
app.options("*", cors()) // Edit 1
app.get("/", (req, res) => {
res.json({message: "API is listening"})
})
const userRouter = require("./api/user/router")
app.use("/api/user", userRouter)
app.listen(5432, () => {
console.log(`Server is listening on port 5432`)
})
CORS version installed in package.json:
"cors": "^2.8.5"
This should be enabling all cors across all origins but it isn't. I've tested it on Chrome, Firefox, and Edge with the same result so I'm sure it's not a browser-specific issue. Everything functions correctly on localhost. It's a preflight request error so it wouldn't be an issue with my endpoint code anyway. Been working on this longer than I care to admit and I'm at the point where I will be happy just to get past the preflight request and add origin configuration later.
Edit 1:
Pre-flight seems to be looking for OPTIONS so I've added:
app.options("*", cors())
new index.js:
const express = require('express')
const cors = require('cors')
const app = express()
app.use(cors())
app.use(express.json())
app.options("*", cors())
but still isn't working...
I have a GitHub page with one file in it: model.json. In model.json is a JSON object. I'd like to be able to access that object via a fetch request triggered in the frontend of my app.
However, I have only done mock localhost express server.jses thus far, and I don't know how to point the server.js file at a remote server.
That is, typically what I have done is something like this:
const express = require("express");
const bodyParser = require("body-parser");
const CORS = require("cors");
const app = express();
app.use(bodyParser.json());
app.use(CORS());
let modelObj = modelJSON;
// ^this "modelJSON" would be the json object in question,
// whether accessed remotely or locally.
app.get("/model.json", (req, res) => {
res.send(modelObj);
});
app.listen(5000, () => {
console.log("Server listening on port 5000");
});
I'm wondering how to make this listen to my https://<my-github-username>.github.io page instead of port 5000.
(Incidentally, will I want this server.js file in my local project/app file or in the github page root directory?)
I am using node 10.16.0, express 4.0.0 and express-ws module . In my normal routes that I use REST, I am using a middleware to check if there is a header with a token and validate that token.
How do I do the same thing for websockets?
I cannot just add a header to ws and pass it to the node route, even though express-ws allows to easily create express-style routes.
Currently, I am using an http server to create a ws server and then seperating different express routes
//app.js
const app = express();
const wsHttpServer = http.createServer();
wsHttpServer.listen(5001);
const expressWs = require('express-ws')(app , wsHttpServer);
app.use(cors());
app.use(express.static(path.join(__dirname,'public')));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended:false}));
app.use(express.json());
app.use(express.urlencoded({extended:false}));
app.use('/ws', require('./routes/wsroute'));
app.use('/login', require('./routes/login'));
const port = process.env.PORT || 4000;
app.listen(port, ()=>{
console.log('server runs on port ', port);
});
exports.expressWs = expressWs;
and then for the ws routes, according to the express-ws examples
//wsroute.js
router.ws('/users/:name/:date/:time', /*token.validate(),*/ (ws, req) => {
const name = req.params.name;
const date = req.params.date;
const time = req.params.time;
console.log('ws route');
console.log('ws route',name, date, time);
});
If I un-comment the token.validate() part, this will never control log because there is no header with a token.
How can I add a header to ws, like I do in REST, so it can be checked automatically? I guess that if the ws server is initialized using an http server and the ws route also includes a req, I can somehow do it?
Or is there another method?
Thanks
duplicate of Websockets token authentication using middleware and express in node.js . Follow the example there.
Listen to the wsHttpServer.on('upgrade') event and perform authentication of your choice there. If you wish you can also append a header on the upgrade eventbefore it reaches your route.
I have a frontend-only web application on Netlify which has to consume an API on OpenSubtitles.org. Although OpenSubtitles.org enables CORS, sometimes I got preflight errors, so I decided to use a proxy.
I had problems using Netlify's proxy feature, so I decided I will create my own proxy on Heroku, and send my requests from the frontend to there, so these will be proxied to OpenSubtitles.org from a server.
I came up with the following based on the code I found here:
const express = require('express');
const request = require('request');
express()
.use('/', function(req, res) {
req.pipe(
request({
url: 'http://rest.opensubtitles.org/search' + req.url,
headers: {
'User-Agent': 'TemporaryUserAgent'
}
})
).pipe(res);
})
.listen(process.env.PORT || 8000);
I thought I deploy this, try it out, then I will enable CORS on it after that. However I've just realized it is working perfectly without doing anything else. How is it possible? Why can I call this from a frontend-only app on a different domain without explicitly enabling CORS?
Also, what if the server crashes, how to handle the errors there?
CORS is working because the url you're requesting responds with the header Access-Control-Allow-Origin set with a value of *. Since you're piping that response and its headers back to the original res object, it will enable CORS as if it was coming from your local proxy.
Below is a more straightforward example of how to proxy a request to another site and return its response intact using node streams.
const express = require('express')
const request = require('request')
const port = process.env.PORT || 1337
let server = express()
const proxyMiddleware = (req, res, next) => {
let url = `https://www.google.com/${req.url}`
let proxyRequest = request(url)
// Pass request to proxied request url
req.pipe(proxyRequest)
// Respond to the original request with the response from proxyRequest
proxyRequest.pipe(res)
}
server.use(proxyMiddleware)
server.listen(port, () => console.log(`Listening on ${port}`))
I have a node.js server api app that is not working after being deployed to azure.
It initially relies on google.api to get the data and after that stores the data in an array and sends it to client by responding to express get calls.
Initially I used:
const express = require('express');
const app = express();
const cors = require("cors");
const _ = require("lodash");
const port = 30000;
app.use(cors());
which worked well enough on localhost.
For deployment, after following a tutorial I changed that to:
const express = require('express');
const app = express();
const cors = require("cors");
const _ = require("lodash");
const port = process.env.PORT || 80;
var http = require('http');
app.use(cors());
var server = http.createServer(app);
server.listen(port, function () {
});
which did not work and finally:
const express = require('express');
const app = express();
const _ = require("lodash");
const port = process.env.PORT || 80;
var login = require('./routes/login');
...
app.use('/login', login);
...
module.exports = app;
and created a new folder for the get commands, as is done here https://github.com/Azure-Samples/app-service-web-nodejs-get-started/blob/master/app.js.
Nothing seems to work and I continue to get the error:
GET http://nameofsite/login 404 (Not Found)
XMLHttpRequest cannot load nameofsite/login. No
'Access-Control-Allow-Origin' header is present on the requested
resource. Origin 'nameofclient' is therefore not allowed access. The
response had HTTP status code 404.
I have tried including the cors header as well as adding the client site to cors allowed origins in the azure portal but it makes no difference. Can anyone help with this issue or provide info on how to correctly format a node.js server using info from a google sheets document?
This might be a silly question but when you moved the VM to Azure did you setup your ip address, update your external DNS and configure the virtual network to allow the correct traffic that Node and your code needs?