nodejs + express: Cors is not a function - node.js

Been working fine up until this morning and now, suddenly i am getting a type error stating that Cors is not a function
My code
import * as Cors from "cors";
...
const corsOptions: Cors.CorsOptions = {
allowedHeaders: ["Origin", "X-Requested-With", "Content-Type", "Accept", "X-Access-Token", "Authorization"],
credentials: true,
methods: "GET,HEAD,OPTIONS,PUT,PATCH,POST,DELETE",
origin: "*",
preflightContinue: true
};
createConnection(ormConfig).then(async connection => {
// run pending migrations
await connection.runMigrations();
// create express server
const app = express();
app.use(bodyParser.json({limit: "50mb"}));
app.use(bodyParser.urlencoded({limit: "50mb", extended: true}));
// register cors
app.use(Cors(corsOptions)); //<---error occurs here
// register all controllers
useExpressServer(app, {
routePrefix: "/api",
controllers: [
__dirname + "/controllers/**/*{.js,.ts}"
],
authorizationChecker: async (action: any, roles: string[]) => {
return JwtAuthorizationMiddleware.checkIsAuthorized(action, roles);
},
currentUserChecker: async (actions: any) => {
return JwtAuthorizationMiddleware.extractUserFromJwtToken(actions);
}
});
// start the express server
const port: number = +(process.env.PORT || 44320);
app.listen(port, (err: Error) => {
console.log(`App listening on port ${port}`);
console.log("Press Ctrl+C to quit.");
});
}).catch(error => console.error("TypeORM connection error: ", error));
Current versions of cors and Node
cors: "^2.8.4"
Node: v8.4.0
The only change that recently done was on Friday when I included the following packages
multer: "^1.3.0"
#google-cloud/datastore: "^1.1.0"
#google-cloud/storage: "^1.4.0"
and everything was working till this morning, same version is deployed on gcloud and this works so I am a little bemused as to why I Am suddenly getting this error and what could be the cause.
Any help is greatly appreciated

You have to have something such as
const cors = require('cors');
in the top of your file, and then refer to the module as cors, not Cors.

You can read Express's cors documentation to learn more.
To apply cors to all routes in your project you can write:
var express = require('express')
var cors = require('cors')
var app = express()
app.use(cors())

Ok, so I found the problem which turned out to be PEBKAC.
While implementing file uploads and storage in gcloud, I had to enable CORS on gcloud and had saved the settings file in the root of my project, this file was called cors.json.
In the code posted in my question above the import statement was reading my cors.json file and not (as I thought) the cors NPM package.
Lesson learnt from this one should anyone else make the same rookie mistake I just made is be careful what you name your files and where you put them!!!

Related

Cors Origin Error. Works on local but not when I deploy on heroku

I am using the code below to run my nodejs backend server. Angular front end has to communicate with the server. While I am using it on localhost everything works fine. However when I deploy my code on heroku I keep getting
Access to XMLHttpRequest at 'heroku app link' from origin 'https:https://iprocopiou.com/.com' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
Does anyone know what I am missing here?
const express = require("express");
const app = express();
const cors = require("cors");
const bodyParser = require("body-parser");
const corsOptions = {
origin: "*",
methods: ["GET","HEAD","PUT","PATCH","POST","DELETE"],
credentials: true,
preflightContinue:false
}
require("./startup/logging")();
require("./startup/routes")(app);
require("./startup/db")();
require("./startup/config")();
require("./startup/validation")();
require("./startup/prod")(app);
app.use(cors(corsOptions))
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
const port = process.env.PORT || 3000;
app.listen(port, () =\> console.log(`Listening on port ${port}`));
I have tried almost every solution that I found...
For security reasons you need to specify the exact URL or URLS origin (protocol + domain + port) when you want to allow and share credentials, you cannot use *.
const corsOptions = {
origin: "https://iprocopiou.com", // or your exact URL you allow to make request
methods: ["GET","HEAD","PUT","PATCH","POST","DELETE"],
credentials: true,
preflightContinue:false
}
//...
app.use(cors(corsOptions))
you can also see more detail in this threat CORS: Cannot use wildcard in Access-Control-Allow-Origin when credentials flag is true

I am having problem using http-proxy-middleware

I have two servers running in my backend, because of that I have to use the http-proxy-middleware package but I am encountering some problems.
This is my code in the frontend which is running on localhost:3000
axios("/api2/login",data)
.then((res) => {
});
This is my code in the backend which is running on localhost:5001
const { createProxyMiddleware } = require('http-proxy-middleware');
app.use(createProxyMiddleware('/api2', {target: 'http://localhost:5001', changeOrigin: true}))
app.post("/login", (req, res, next) => {
res.send("Logged In");
});
This code is no working showing this error in the browser's console
GET http://localhost:3000/api2/login 404 (Not Found)
Uncaught (in promise) Error: Request failed with status code 404
at createError (createError.js:16)
at settle (settle.js:17)
at XMLHttpRequest.handleLoad (xhr.js:61)
I am not able to understand where I am going wrong.
Looks like it's hitting localhost:3000 instead of localhost:5001 which is where your server is running from.
axios("http://localhost:5001/api2/login",data)
.then((res) => {
});
You can also set the baseURL in axios. HTTP get request with Axios gets sent with the local host IP at the beginning of the URL
If I understand correctly your server is listening on port 5001. So, you need to proxy your requests from 3000 to 5001. You can do that in the react application by setting the proxy value in package.json:
"proxy": "http://localhost:5001",
For more information about this subject, check the docs.
Edit for the configuration explained in the comment section
First in package.json:
"proxy": "http://localhost:5002",
Create a new server (proxyserver) which will be listening in port 5002:
const express = require('express');
const { createProxyMiddleware } = require('http-proxy-middleware');
const app = express();
// redirection for first server 5000
app.use('/api1', createProxyMiddleware({ target: 'http://localhost:5000', changeOrigin: true }));
// redirection for second server 5001
app.use('/api2', createProxyMiddleware({ target: 'http://localhost:5001', changeOrigin: true }));
app.listen(5002);
For the other servers (5000 and 5001) you don't need to redirect the requests. Just make sure they're listening on the right ports (5000 and 5001), for example:
const express = require('express');
const app = express();
app.post("/api2/login", (req, res, next) => {
res.send("Logged In");
});
app.listen(5001);
I followed the steps mentioned in this post along with some changes,
I changed my Axios request code to:
axios({
method: "POST",
data: user,
withCredentials: true,
url: "/api2/login",
}).then((res) => {})
Otherwise, the proxy server was treating it as a GET request.
Secondly, I changed the proxy endpoint code int the proxy server as:
app.use('/api2', createProxyMiddleware({
target: 'http://localhost:5001',
changeOrigin: true,
pathRewrite: {
[`^/api2`]: '',
},
}));
Further information about the proxy endpoint change can be found here.

Socket io communication blocked by CORS policy in a Node js + Angular application

So I use a simple node.js server with express and socket.io
When I try to communicate with a simple client written in javascript, it works perfectly, but when I try to create the communication with an Angular app (using ngx-socket-io), I get the following error message :
Access to XMLHttpRequest at 'http://localhost:5000/socket.io/?EIO=3&transport=polling&t=NQFEnVV' from origin 'http://localhost:4200' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
This is the nodejs server :
var express = require('express');
var app = express();
const http = require('http').Server(app);
const io = require('socket.io')(http);
const port = process.env.PORT || 5000;
app.set(port, process.env.PORT);
app.use(express.static('./client/'));
io.on('connection', socket => {
socket.emit('connection', 'data from server!');
});
http.listen(port, () => {
console.log('App listening on port ' + port);
});
And this is how I implement socket.io on Angular client :
app.module.ts :
import { SocketIoModule, SocketIoConfig } from 'ngx-socket-io';
const hostname = window.location.hostname;
const url = (hostname === 'localhost') ? `${window.location.protocol}//${hostname}:5000` : undefined;
const config: SocketIoConfig = { url, options: {} };
#NgModule({
declarations: [...],
imports: [
...
SocketIoModule.forRoot(config)
class that use socket io :
constructor(private socket: Socket) { }
this.socket.on('connection', (data) => {
console.log('Working ' + data);
});
I tried to fix the CORS error with headers in server side such as :
const io = require('socket.io')(server, {
cors: {
origin: '*',
}
});
or
app.use(function(request, response, next) {
response.header("Access-Control-Allow-Origin", "*");
response.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
next();
});
but it still display the same error.
I use of course the command ng serve to run my application (running on port 4200) and it was perfectly working 3 months ago. (Working with the ng serve, and the ng build prod as well).
Verify socket.io-client version on the angular packaje.json file. If it's lower than 3.1.2 you could try to upgrade it by
npm install socket.io-client#3.1.2 --save
Also you could verify the serverside once again looking at this
const app = require('express')();
const http = require('http').createServer(app);
const io = require('socket.io')(http, {
cors: {
origins: ['http://localhost:4200']
}
});
Replace http://localhost:4200 by your current environmment on the Angular App
try this
const io = require('socket.io')(server, {
cors: {
origin: "http://localhost:4200",
methods: ["GET", "POST"]
}
});
you can add or remove mothods
also try adding this
var cors = require('cors');
app.use(cors());
Adding fix from angular side (no changes in Node server required).
That cors: { origins: ['http://localhost:4200']} didn't work for me so I sat up a proxy file in angular project to tackle CORS.
add file in src/proxy.config.js file
{
"/api": { // this attaches /api/ in api url
"target": "http://localhost:3000",
"secure": false,
"logLevel": "debug"
},
"/": { // use this as second entry
"target": "http://localhost:3000",
"secure": false,
"logLevel": "debug"
}
}
in angular.json, add this;
"serve": {
"options": {
"browserTarget": "move-safe:build",
"proxyConfig": "src/proxy.config.json"
},
and re-build the angular app
It worked on the local machine but didn't on production.
I was confused why is that happening but suddenly i noticed that the HEROKU deployed it on something like
https://dummydomain.herokkuapp.com
but i was trying to connect it from
http://dummydomain.herokkuapp.com
that may be the reason for your app as well.
:D

getting CORS and network error while calling axios post request using Vue js

I am getting error while calling axios post request. But it works properly on postman.
The code I used for calling the request is
methods : {
displayData(){
var config = {
method: 'post',
url: 'http://localhost:5000/api/request/displayRequest',
headers: {
'Content-Type': 'application/json'
},
data : JSON.parse(JSON.stringify(this.user._id))
};
axios(config)
.then(function (response) {
console.log(JSON.stringify(response.data));
})
.catch(function (error) {
console.log(error);
});
},
async mounted(){
this.displayData()
}
I have already implemented CORS on the back-end in server.js
// Cors Middleware
const cors = require('cors');
app.use(cors());
app.options("*", cors());
app.use(
cors({
origin: (origin, callback) => callback(null, true), // you can control it based on condition.
credentials: true, // if using cookie sessions.
})
);
in your backend use this :
npm i cors
and in your express backend entrypoint:
const cors = require("cors");
app.use(cors());
app.options("*", cors());
You are running your front-end on localhost and using some port. Also, your back-end is running on localhost, port 5000. But your front-end application can not access any other port due to CORS policy. You can solve this problem in the back-end if you are using Node JS.
Install cors by the following command:
npm i cors
Then on your server file, change your app by
app.use(cors());
N.B. If you used React js, you could use http-proxy-middleware. Just create a file inside the src directory named "setupProxy.js". and add the following lines.
const { createProxyMiddleware } = require("http-proxy-middleware");
module.exports = function (app) {
app.use(
"/api",
createProxyMiddleware({
target: "http://localhost:5000/",
})
);
};
Don't forget to change the port in this file into the port of your server.

Socket.io cors error by using node, react and socket.io

We are using CORS to allow all origins
app.use(cors());
server running on port 4000, and client running on 3000
here is my server.js code
const cors = require("cors");
const http = require("http");
const socketIO = require("socket.io");
app.use(cors());
const port = process.env.PORT || process.env.DEFAULT_PORT;
console.log("port: ", port);
app.listen(port, () => {
console.log(`App listening at ${port}...`);
});
const server = http.createServer(app);
const io = new socketIO(server, {
transports: ["websocket"],
});
React js code
constructor(props) {
super(props);
try {
this.socket = io("http://localhost:4000", { transport: ["websocket"] });
this.socket.on("Chat-event", data => {
console.log("socketdata", data);
});
} catch (error) {
console.log("hiterror", error)
}
}
I am continuously getting this error on the client side after allowing origin for all.
Access to XMLHttpRequest at 'http://localhost:4000/socket.io/?EIO=3&transport=polling&t=Mv-SSIc' from origin 'http://localhost:3000' has been blocked by CORS policy: 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'. The credentials mode of requests initiated by the XMLHttpRequest is controlled by the withCredentials attribute
For socket.io version 3.x.x cors configuration has changed, I managed to fix it by adding options to the socket creation.
Tried on the version 2.x.x also and it worked.
const io = socketio(httpServer, {
cors: {
origin: "http://localhost:3000",
methods: ["GET", "POST"],
credentials: true
}
});
Here is the resource https://socket.io/docs/v3/handling-cors/
Bonus: In case you encounter Bad Request make sure you have the same version of socket.io for the client and the server.
By following these steps you can get rid of these error.
// 1) on server side
const cors = require('cors');
const socketio = require('socket.io')
const http = require('http');
const server = http.createServer(app);
const io = socketio(server, {
cors: {
origin: localhost:3000/, //your website origin
methods: ["GET", "POST"],
credentials: true
}
});
// 2) add these middlewares
app.use(cors())
app.options('*', cors());
// 3) on client-side
import io from 'socket.io-client'
let socket = io.connect(localhost:8080, { transports: ['websocket'] }) // your local server
try using the cors credentials config:
app.use(cors({credentials: true}));
Please allow all to socket.io at server side
const socketIO = require('socket.io')(server, { origins: '*:*'});
Or you can set socketIO origins as *
socketIO.set('origins', '*:*');
#user4860402 Gave me solution, thing is that by default npm is installing socket.io client v 2.X.X but on server I'm using latest verion (also provided by npm) 3.0.5
So all problems including 400 error comes because client and server verion doesnot match.
const express = require("express");
const app = express();
const http = require("http").createServer(app);
const socketio = require("socket.io");
const cors = require("cors");
const io = socketio(http, {cors:{origin:"*"}});

Resources