Reputation: 446
I'm working on a chat app in socketio. The issue i'm stuck in is that if i put my io.on('connection', ..})
block outside the express route app.get('/chat')
, everything works fine but when i put it inside the route /chat
. everything inside the connection is firing twice.
server.js
// On new connection
io.on("connection", socket => {
console.log('Socket ID: ' + socket.id);
// I want the user object (inside /chat route) to be available here..
})
// @route:chat
app.get("/chat", auth, async (req, res) => {
const user = User.findbyId(req.userId);
// socket.io part moved outside the route
res.render('chat', {})
})
Output on first request to /chat
:
Socket ID: 5e82d1a21c9d4400003e9bce
Output on second request to /chat
:
Socket ID: 5e82d1a21c9d4400003e9bce --> this is repeating
Socket ID: 5e82d1a21c9d4400003e9bc4
And so on if i keep requesting /chat
.
Any idea how to solve this issue?
Upvotes: 0
Views: 418
Reputation: 4603
Generally, socketIO operations shouldn't depend on an express route. If you want a user to join the socketIO connection, it should be done via SocketIO's event handlers. Your front-end should initiate the connection, and pass some identity to SocektIO, if you want to associate a "user" to that socket.
I don't know how your application handles auth, but a common practice is to pass a token to the SocketIO connection establishment:
const socket = IO.connect('http://localhost:8000', {
query: {
token//This token will be available on the server.
}
});
So then in your server:
const middleware = async (socket,next)=>{
const token = socket.handshake.query.token;//Now you have the user token, which presumably contains the user ID.
const verifiedUser = await getUserByToken(token);//Let's say this returns a user object, if the token is valid, false if not.
// Let's assume that behind the scenes this function also calls User.findbyId(id);
if(verifiedUser){
socket.userObject = verifiedUser;//You can place the userObject on the token object, to be used later.
next()//Will allow the "connection" event to proceed.
}else{
next(new Error('INVALID_CREDENTIALS'))//Will cause the on("error") event to fire in the front-end, passing this error.
//The on("connection") event here will not fire.
}
}
io.use(middleware)
io.on('connection', async (socket) => {
//This runs only if middleware is "successful".
})
I don't know if this really answers your questions, but it's an example for how a socket-user relationship might look like.
Upvotes: 1