Socket io instance/middleware in express - javascript

var http = require("http").Server(express);
var io = require("socket.io")(http);
server.listen(8080);
Above code work if I put in different route. But how to create an instance of it so that I don't have to declare many times?

you are not clear with your question but i think you want to you io object in different files
you can do this using
app.all("*",function(req,res,next){
req.io=io;
next();
});
define this middleware before the routing in you server file
and where you want to use this you can get this object as
function(req,res,next){
var io = req.io;
}

Related

Linking Socket IO to Express routes

I'm been looking around everywhere for the last few days for a way to access my socket IO instance running in Express from my routes and have not found a working solution.
The problem here is that I only run my socket IO instance at run-time and my routes and defined before that obviously.
The most promising solution I have found is one that wraps my routes in a function and requires it in my app.js file with whilst passing in the IO instance as an argument like so var routes = require('routes')(io)
Here is my setup:
app.js
const express = require('express');
const app = express();
const server = require('http').Server(app);
const io = require('socket.io')(server);
io.on('connection', function(client) {
console.log(io.sockets.sockets)
});
app.set('port', 7777);
const routes = require('./routes/index')(io);
app.use('/', routes);
app.listen('7777');
routes.js
module.exports = function(io) {
const express = require('express');
const router = express.Router();
router.get('/test', (req, res) => {
console.log(io.sockets.sockets);
});
return router;
}
If I connect to the WebSocket, my io.on event fires and I get a console log of the connected sockets in the form of a fairly large object that contains the socket id's etc.
If however, I get to the route '/test' I get a console log of a blank object: {}. I would imagine this is because the instance of the socket I am passing down to the routes does not have anyone connected to it at the time hence the blank object is returned, but this is just my best guess.
Where I'm a little stuck is how to get the full instance with all live connections to the route.
Alternatively, I've thought of attaching the io instance to the request object like so in order to have access to it in the routes:
server.on('request', function(req, res){
req.io = io;
}
but couldn't quite get it to work, nor am I sure this is the correct approach.
I imagine this must be a common issue so I would love a clear answer on how to work around this and the correct approach to tackle the issue.
EDIT
So I eventually got my above code working, I hit the '/test' endpoint from an AJAX GET request within the chrome extension instead of my just visiting the URL localhost:7777/test. What I can't understand here is why it works with an AJAX request but not page navigation? (The page navigation is done after I make the socket connection in the extension)

How can I emit Socket.io events from a router file?

I am working on a socket.io project in which I need to emit an event when the / page is requested. But all my routings are in a separate file router/index.js. Now, I want to emit a socket event on the page request from the router file.
I can't find a way to sort this out. Can anyone help?
put your socket object in separate file and export it.
//let io.js
var http = require('http').Server(app);
var io = require('socket.io')(http);
module.export.io = io;
now in route/index.js;
var io = require('io.js')
app.get('/', function(req, res){
io.sockets.emit('home.accessed');
})
simlarly if socket code was in server.js
require it from io.js likewise.

Make a cookie when a user connects with socket. io - node js

have a server that uses socket.io. When a user connects it will assign them the user id thats made on the server then increment it by 1 so the next user with have a different id.
I want to use cookies for this, to check if they have previously logged in, if so, use that id, if not, use the one on the server.
the way to create a cookie is by using
res.cookie('cookie', 'monster')
but im not where i would put it, i tried putting it in the connect function but res wouldnt exist. and if i put it outside the function, how would i call it? Here is my code. This is the start of my server:
//Require npm modules
var express = require('express');
var http = require('http');
var events = require('events');
var io = require('socket.io');
var ejs = require('ejs');
var app = express();
//Set the default user Id to 1 and the default username to Guest
exports.Server = Server = function()
{
this.userId = 1;
this.userName = "Guest";
};
app.set('view engine', 'ejs');
app.get('/game/:id', function (req, res)
{
res.render('game', {game: req.params.id});
});
Server.prototype.initialise = function(port)
{
//Create the server using the express module
this.server = http.createServer(app);
//Declare the 'public' folder and its contents public
app.use(express.static('public'));
//Listen to any incoming connections on the declared port and start using websockets
this.server.listen(port);
this.startSockets();
this.em = new events();
consoleLog('SERVER', 'Running on port: ' + port);
};
Server.prototype.startSockets = function()
{
//When a user connects to the server on the 'game' socket
this.socket = io.listen(this.server);
this.socket.of('game').on('connection', function(user)
{
res.cookie('cookie', 'monster')
//Set their usedId and username
user.userId = this.userId;
user.userName = this.userName + " " + this.userId;
//Increment the user id by 1 so each user with get a unique id
this.userId++;
//Send a response back to the client with the assigned username and user id and initialise them
user.emit('connected', user.userId, user.userName);
this.em.emit('initialiseUser', user.userId, user.userName);
So where i have the res.cookie is where i want to be able to read and write cookies, any help is appriciated
I think what you are looking for is the middleware pattern employed by express. You can define as many of these middleware calls as you wish, and they are the perfect scope for calling any other functions which may need the res instance (or the req instance for that matter).
app.use(function (req, res, next) {
// call function, passing in res here
next();
})
Reference: https://expressjs.com/en/guide/using-middleware.html
EDIT:
This answer is not correct for your situation. In a node/express server not using socket connections, then yes, you could easily use the above pattern anywhere you need the request and response objects in scope.
However, once you setup the socket io server, the game changes. During the socket communications, there are no express request and response objects in scope anymore, everything is handled directly between your socket handling code and the client. So the answer is you need to handle the situation in a socket io way, not in an express way.
Please see: Adding a cookie value on Socket.IO

Using socket.io with express 4 generator

New to node, so my apologies.
I'm working on my app and I want to send the location using socket.io. I've found 1000 examples, but all refer to when express had no routes, and it all was at the app.js. All examples refer to chat applications.
I was able to run an example piecing together several questions I searched but, I don't understand how to get the io that I finally got working on my app.js to interact with my index.js so I can use it with multiple emit parameters. express.io is outdated and I can't find anything current.
On bin/www
/**
* Socket.io
*/
var io = app.io
io.attach( server );
My app.js
var socket_io = require('socket.io');
var app = express();
var io = socket_io();
app.io = io;
So I can use:
io.on('connection', function (socket) {
console.log('IO Ready');
});
I don't know how to use the sockets on my index.js (routes), I can't modularize it.
Thanks in advance.
I have to say, I think the default generated project is bad for a socket.io setup. The node http.Server var is all the way in bin/www and not in app.js.
So the first thing is to move all the relevant stuff from bin/www to app.js. Mainly you just need
var app = require('express')();
var server = require('http').Server(app);
var io = require('socket.io')(server);
just like in the socket.io docs.
Now with io in app.js, we can use that when the routes are required. I forgot how exactly the default routes are set up, but I think they set up an app and just export it. Instead, you can set up something like
module.exports = function(app, io) {
io.on('connection', function(socket) {
console.log('connected!');
}
app.get('/foo', function() {
...
}
}
And now when you require the routes, instead of having the default
var index = require('./routes/index');
app.use(index);
or something of that accord, you can just do
require('./routes/index')(app, io);
And that's how you get io into your routes. Or at least how I do it anyway.

How to change URL for users using socket.io?

I am making a game for TWO players with node.js, socket.io and express.
In order to avoid effect from the third person that come to play, i want to generate specific URL for the two who are ready to play.
So my question is, how to change the URL when two people have come?
I am now testing it in local. In the server side, i have server listen to a port.
var express = require('express');
var SocketIO = require('socket.io');
var http = require('http');
var path = require('path');
var app = express({
views: path.join(__dirname, 'views')
});
app.use('/assert', express.static(path.join(__dirname, 'assert')));
app.engine('html', require('ejs').renderFile);
app.get('/', function (req, res) {
res.render('home.html', {layout: false});
});
var server = http.createServer(app);
var sio = SocketIO.listen(server);
server.listen(8080);
function(...){...}
In the client side, i have socket connected to somewhere.
var socket = io.connect('http://' + location.host);
var ....
i guess what i need to do is to provide a button when i detect that two clients come in.
When they clicked it, it direct them to a generated new URL.
So there is an old URL and many new ones...
Then how can i set different URLs in both server and client??
Any help is appreciated^ ^
There are many ways for generating a UNIQUE random url
1) Use Timestamp and append it to a predefined url of yours
2) Use random number generators. This can be done either by pure javascript function Math.Random() or even the one provided by node
Eg.
var url = "http://www.yourHostName.com/"+(Math.Random()*(UpperLimit-LowerLimit)+(LowerLimit));
Supply Large UpperLimit Like 100000 (According to your need and expected traffic) and LowerLimit = 0;
or by using the time stamp like this:
var url = "http://www.yourHostName.com/"+ new Date.getTime();
Beside this as I said you can also use the node to do the same task. There is a module called node-uuid which can do the similar task Refer to this Question: generate URL on node.js server
Once you have the unique URL and the reference to the clients to whom you want to send to a same Generated URL. Then Just Redirect them using the following:
response.writeHead(301,
{Location: url}; //one you generated
);
response.end();

Categories

Resources