Reputation: 1162
I have express/nodejs api. I am adding socket.io feature to it. Currently all of my routes are in separate folders and I include them in server.js file and use them as app.use() function.
In server.js file, I also start the express server by listening to a particular port such as 3000 as below.
let server = app.listen(3000);
According to all google searches what I found is that I need to pass server variable to initialize socket.io like following.
let io = require('socket.io')(server);
Now the question is that since it needs this variable then how can I use socket.io in my routes files which are in different folder to emit and receive events from client?
UPDATE
in server.js file
let route = require('./routes/route');
let app = express();
let server = app.listen(3000);
console.log('Listening to port');
let io = require('socket.io')(server);
app.use('/api/1.0/events', route(io));
in route.js file
let express = require('express');
module.exports = (io) => {
console.log('IO: ', io);
};
UPDATE 2
server.js file
let express = require('express');
let events = require('./routes/events');
let app = express();
let server = app.listen(3000);
let io = require('socket.io')(server);
app.use(function(request, response, next) {
request.io = io;
next();
});
app.use('/events', events);
events.js file
let express = require('express');
let Events = require('../models/events');
apiRoutes.post('/new', function(request, response) {
let newEvent = new Events(request.body);
newEvent.save((error, result) => {
if (error) {
response.json(error);
} else {
// console.log('ELSE');
// request.io.on('connect', socket => {
// console.log('LISTENING TO SOCKET...');
request.io.on('EventCreated', data => {
console.log('DATA ON Server: ', data);
});
// });
response.json({
success: true,
message: 'New event created'
});
}
});
});
Upvotes: 40
Views: 25850
Reputation: 917
For using a custom path with Socket.io, here is an implementation I tried :
const app = express();
const server = app.listen(port)
const io = new Server(server, {
path: "/my-custom-path/"
});
On the frontend, it can be done like:
import { io } from "socket.io-client";
const socket = io('BACKEND_ENDPOINT', { path: '/my-custom-path/' });
Upvotes: 0
Reputation: 783
The middleware solution that worked for me —
index.js
:
import express from 'express'
import mongoose from 'mongoose'
import cors from 'cors'
import http from 'http'
import { Server } from 'socket.io'
import staticRouter from './staticRouter.js'
import liveRouter from './liveRouter.js'
// Necessary for using 'require' for socket.io
import { createRequire } from 'module'
const require = createRequire(import.meta.url)
const startServer = async () => {
const app = express()
app.use(express.json())
app.use('/static', staticRouter)
app.use(cors())
const server = http.createServer(app)
const io = new Server(server, {
cors: {
origin: "origin-url",
methods: ["GET", "POST", "PUT", "DELETE"],
},
})
app.use(function(req, res, next) {
req.io = io
next()
})
app.use('/live', liveRouter)
await mongoose.connect('your-mongo-endpoint') //Connecting to mongoose
server.listen(3000)
}
startServer()
liveRouter.js
:
import express from 'express'
import { liveConnection } from './live.js'
// Routes
const liveRouter = express.Router()
// Live Updates
liveRouter.route('/live-connection')
.put(liveConnection)
export default liveRouter
and live.js
:
export const liveEventConnection = async (req, res) => {
console.log('req.io ->', req.io)
// In any express route handler, you can use req.io.emit(...)
}
Upvotes: 0
Reputation: 442
Sharing my Solution that I've used
Another solution for this problem (that I actually used) is that we can make our io
(socket.io
object) object global.
Simply assign io
to the global.io
.
The io
object is in index.js
, after creating and setting up the io
object simply do global
(i-e global.io = io;
), now this io
object is accessible in any route that we are working within our project.
Upvotes: 6
Reputation: 707318
There are multiple ways to share the io
variable with route files.
When you require()
in your route file, pass it the io
variable as a constructor argument.
Use app.set("io", io)
so you can then use let io = app.get("io")
in any file that has access to the app
object.
Create a middleware that puts the io
object on every req
object so you can access it from there any time.
Here's an example of passing it as a constructor argument to the router file:
let server = app.listen(3000);
let io = require('socket.io')(server);
// load other routers
app.use(require("./someRouterFile.js")(io));
// in someRouterFile.js
const express = require('express');
module.exports = function(io) {
let router = express.Router()
// define routes
// io is available in this scope
router.get(...)
return router;
}
Here's an example of the app.set()
scheme:
let server = app.listen(3000);
let io = require('socket.io')(server);
app.set("io", io);
Then, anywhere in your routes that you have access to the app
object, you can get it with:
let io = app.get("io");
Here's an example of using a middleware to set the io
object onto every req
object so it's available from all routes.
let server = app.listen(3000);
let io = require('socket.io')(server);
// place this middleware before any other route definitions
// makes io available as req.io in all request handlers
app.use(function(req, res, next) {
req.io = io;
next();
});
// then in any express route handler, you can use req.io.emit(...)
Here's an example of using an argument to the module constructor without middleware:
// in mysocket.js
module.exports = (io) => {
console.log('IO: ', io);
io.on('connect', socket => {
// handle various socket connections here
});
// put any other code that wants to use the io variable
// in here
};
Then, in your main file:
let server = app.listen(3000);
let io = require('socket.io')(server);
// initialize my socketio module and pass it the io instance
require('./mysocket.js')(io);
Upvotes: 66
Reputation: 3576
In server.js:
module.exports.getIO = function(){
return io;
}
In your route file:
var theServer = require('<path to server.js>');
var iovar = theServer.getIO(); //your io var
Upvotes: 5