Reputation: 929
I'm having this weird problem with socket.io. I have an express app which I run on port 5000. I have configured socket.io like this:
const app = require('../index');
const http = require('http');
const server = http.Server(app);
const io = require('socket.io')(server);
io.on('connection', function (socket) {
console.log('User has connected');
socket.emit('connect', {
message: 'Hello World'
});
});
Then I import this piece of code into my index.js file like this:
const express = require('express');
const app = module.exports = express();
const bodyParser = require('body-parser');
const cors = require('cors');
const request = require('request');
const boxRoutes = require('./routes/v1/boxRoutes');
const bidRoutes = require('./routes/v1/bidRoutes');
// use body parser so we can get info from POST and/or URL parameters
app.use(bodyParser.urlencoded({ limit: '10mb', extended: true }));
app.use(bodyParser.json({ limit: '10mb' }));
require('./services/usersClass');
// cors set up
app.use(cors());
app.use(function (req, res, next) {
console.log('Headers Middleware Called');
// Website you wish to allow to connect
res.setHeader('Access-Control-Allow-Origin', 'http://localhost:3000');
// Request methods you wish to allow
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, DELETE');
// Request headers you wish to allow
res.setHeader('Access-Control-Allow-Headers', 'origin, x-requested-with, content-type, accept, x-xsrf-token', 'token');
// Set to true if you need the website to include cookies in the requests sent
// to the API (e.g. in case you use sessions)
res.setHeader('Access-Control-Allow-Credentials', true);
// Request headers you wish to expose
res.setHeader('Access-Control-Expose-Headers', false);
next();
});
// Middleware to authenticate the requests to this service
app.use(function(req, res, next) {
console.log('Auth Middleware Called');
if(!req || !req.headers['authorization']) return res.sendStatus(401);
const token = req.headers['authorization'].split(' ')[1];
request.post(
'http://localhost:4000/api/v1/users/auth',
{
headers: {
'Authorization': `Bearer ${token}`
}
},
function (error, response, body) {
if (!error && response.statusCode == 200) {
const data = JSON.parse(body);
res.locals.user = data.user;
next();
} else {
console.log('Request has failed. Please make sure you are logged in');
res.sendStatus(401);
}
}
);
});
app.use('/api/v1/boxes/', boxRoutes);
app.use('/api/v1/bids/', bidRoutes);
// disable 'powered by'
app.disable('x-powered-by');
app.listen(5000, () => {
console.log('Trading service is running on port 5000');
});
Now, in my client code, I try to establish socket.io connection when the user logs in. Everytime I try to connect to the server, I get the following error:
Failed to load http://localhost:5000/socket.io/?EIO=3&transport=polling&t=MA_9wXE: 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.
I don't understand why the connection fails. I have configured Access-Control-Allow-Origin
to my client domain but it still fails.
Upvotes: 1
Views: 2470
Reputation: 707238
I've seen this problem before, but never seen it manifested as a cross origin issue. You are creating two separate http servers. One you are making your express server and the other you are making your socket.io server. The code you show only actually starts the express server and you show no code that actually starts your socket.io server.
Here's where you create these two separate servers:
const server = http.Server(app); // creates the http server you use for socket.io
app.listen(5000, () => {...}); // creates the http server you use with Express
Inside of app.listen()
, it creates it's own new server and starts it. Your other server is never started (at least per the code you show here).
When you probably want to do is to make your socket.io server use the same server as your express server and then you should be able to connect just fine without any CORs issues.
If you want to use app.listen()
, it will return the server
object that it created and you need to use that to initialize socket.io.
If you want to use the other server, then you need to share that with your express initialization code so it can use that one.
Upvotes: 0
Reputation: 485
You can use cors npm module. It will fix your problem.
var cors = require('cors')
var app = express()
app.use(cors({origin: '*'}))
start '*' means allow every origins. You can type spesific origin too.
Upvotes: 1