Socket.io - io.to.emit emits to all connected users - javascript

I have a MEAN app setup with npm socket.io with expressjs and btford.socket-io on the client.
angular.module('myApp',['btford.socket-io'])
.factory('socket',function(socketFactory){
return socketFactory();
}
).controller('myAppCtrl',['$scope','socket',
function(a,b){
b.on('test',function(data){
console.log(data);
});
}
]);
Here's the node-express setup:
var app = express(),
server = app.listen(3000);
var socket = require('socket.io'),
io = socket.listen(server);
require('/config/routes/index.js')(app,io);
require('/config/routes/test.js')(app,io);
Routes : (config/routes/index.js)
module.exports = function(app,io){
app.get('/',function(req,res){
io.on('connection',function(socket){
socket.join(req.session._id);
});
res.render('index');
});
};
config/routes/test.js
module.exports = function(app,io){
app.get('/route1',function(req,res){
io.to(req.session._id).emit('test',{
data : 'Works'
});
res.render('route1');
});
};
A) Whenever the user goes to route1, the emit event is being fired and sent to all the users.
B) Is there a better approach to avoid using unique room for each user? This is not a chat application but rather implements push notifications

You have a couple major misunderstandings about how sockets and requests work. They are very separate operations and are not connected the way you appear to think they are. I will try to explain the problems with your code.
In this block of code:
module.exports = function(app,io){
app.get('/',function(req,res){
io.on('connection',function(socket){
socket.join(req.session._id);
});
res.render('index');
});
};
You are processing the / page request and EVERY time that request is hit, you add yet another event handler for io.on('connection', ...), thus you could have many of those.
Further, if the connection event happens BEFORE the user hits the / page, then you will miss it entirely and that socket will not be placed into the proper chat room.
Then, in this block of code:
module.exports = function(app,io){
app.get('/route1',function(req,res){
io.to(req.session._id).emit('test',{
data : 'Works'
});
res.render('route1');
});
};
io.to() takes a string that is the name of a chat room. So, this will send a message to every socket that is in the req.session._id chat room. For this to work, you'd have to make absolutely sure that req.session._id was completely unique to this user and that the desired user had already joined a chat room by this name. This could work, but it depends upon those specific things being correct.

You need to think of the connection from socket.io separately from a request. They are NOT tied together the way that you think they are. Your connection listener is for any connection not just a connection related to a given request... what you are trying to do simply will not work that way.
Imagine that your socket.io portions of your project are completely separate from the http requests in the web/express portions of your application. This is how you should think of passing messages.
Also worth consideration is that if you are using cluster or similar scaling methods, your default socket.io setup in one instance doesn't communicate with other instances.

Related

How to create sockets that particular to user and disposable on Socket.Io

I write a Node.Js app and I use Socket.Io as the data transfer system, so requests should be particular to per user. How can I make this?
My actual code;
node:
io.on('connection', (socket) => {
socket.on('loginP', data => {
console.log(data);
})
})
js:
var socket = io('',{forceNew : false});
$("#loginbutton").click(function() {
var sessionInfo = {
name : $("#login input[name='username']").val(),
pass : $("#login input[name='pass']").val()
}
socket.emit("loginP", sessionInfo)
})
It returns one more data for per request and this is a problem for me. Can I make this on Socket.Io or should I use another module, and If I should, which module?
If I understand your question correctly (It's possible I don't), you want to have just one connection from each user's browser to your nodejs program.
On the nodejs side, your io.on('connection'...) event fires with each new incoming user connection, and gives you the socket for that specific connection. So, keep track of your sockets; you'll have one socket per user.
On the browser side, you should build your code to ensure it only calls
var socket = io(path, ...);
once for each path (your path is ''). TheforceNew option is for situations where you have multiple paths from one program.

Real time notifications node.js

I'm developing a calendar application with Node.js, express.js and Sequelize.
The application is simple, you can create tasks in your calendar, but you can also assign some tasks to others users of the system
I need to create a notification system with socket.io, but I don't have experience with websockets. My big doubt is how can I make my server send a notification to the user that you assign the task?
My ports configurations is on a folder called bin/www, my express routes are defined on a file called server.js
Any Idea?
I want to introduce you to ready to use backend system that enables you to easily build modern web applications with cool functionalities:
Persisted data: store your data and perform advanced searches on it.
Real-time notifications: subscribe to fine-grained subsets of data.
User Management: login, logout and security rules are no more a burden.
With this, you can focus to your main application development.
You can look at Kuzzle, wich is one project I working on:
First, start the service:
http://docs.kuzzle.io/guide/getting-started/#running-kuzzle-automagically
Then in your calendar application you can the javascript sdk
At this point you can create a document:
const
Kuzzle = require('kuzzle-sdk'),
kuzzle = new Kuzzle('http://localhost:7512');
const filter = {
equals: {
user: 'username'
}
}
// Subscribe every changes in calendar collection containing a field `user` equals to `username`
kuzzle
.collection('calendar', 'myproject')
.subscribe(filter, function(error, result) {
// triggered each time a document is updated/created !
// Here you can display a message in your application for instance
console.log('message received from kuzzle:', result)
})
// Each time you have to create a new task in your calendar, you can create a document that represent your task and persist it with kuzzle
const task = {
date: '2017-07-19T16:07:21.520Z',
title: 'my new task',
user: 'username'
}
// Creating a document from another app will notify all subscribers
kuzzle
.collection('calendar', 'myproject')
.createDocument(task)
I think this can help you :)
Documents are served though socket.io or native websockets when available
Don't hesitate to ask question ;)
As far as I can understand you need to pass your socket.io instance to other files, right ?
var sio = require('socket.io');
var io = sio();
app.io = io;
And you simply attach it to your server in your bin/www file
var io = app.io
io.attach(server);
Or what else I like to do, is adding socket.io middleware for express
// Socket.io middleware
app.use((req, res, next) => {
req.io = io;
next();
});
So you can access it in some of your router files
req.io.emit('newMsg', {
success: true
});

Socket.io How to make function io() anonymous?

I'm trying to make an application on node.js using Soket.io
server-side
var server = http.createServer(app);
var io = require('socket.io')(server, {httpCompression: false, cookie: false});
io.on('connection', function(socket) { ... });
client-side
<script src="https://cdn.socket.io/socket.io-1.4.5.js"></script>
<script>
var socket = io('ws://my-ws-server:8000/');
</script>
My problem:
Each client/user can write into console mysocket=io('ws://my-ws-server'); and push new connection, so now he can emit signals with wrong data or spam with new Socket connections
I also tried download socket.io.js code, edit it with $(function(){ /*socket.io code*/ });, and when include ../javascript/socket.io.js to my page, but it doesn't help, io() function still accessed from console
so, is there any solution? Is here any way to hide this function and prepare from spam with new fake socket connections?
tnx, sry for my eng.
One way is to prevent malicious data from your emit by validating input message before you dispatch it. So first check if it's a string your system knows about by comparing it to your dictionary, then correct authority level clearance. If it passes then do the callback which emits the registered action. It's not 100% but it prevents your application from taking malicious information

Where is a good place to put socket.io logic in sails.js

where is a good place to put my logic if I want to use sails.io? Is config/bootstrap.js a good place to put it? Or is there some other file I can create somewhere else?
This code below works:
// config/bootstrap.js
module.exports.bootstrap = function (cb) {
sails.io.sockets.on('connection', function(socket) {
console.log("Got a connected client");
});
cb();
};
It doesn't support this until 0.9.4.
step 1. Get the latest version of sails.js
step 2. Generate sails with the the cli
step 3. See config/sockets.js, customize onConnect function, see below:
module.exports.sockets = {
// This custom onConnect function will be run each time AFTER a new socket connects
// (To control whether a socket is allowed to connect, check out `authorization` config.)
// Keep in mind that Sails' RESTful simulation for sockets
// mixes in socket.io events for your routes and blueprints automatically.
onConnect: function(session, socket) {
// By default: do nothing
// This is a good place to subscribe a new socket to a room, inform other users that
// someone new has come online, or any other custom socket.io logic
console.log("Got a connected client");
},
...
For logic processing, you can put it in the following places:
Controller: if a request should trigger a real-time event
Service: if you want :) but I think Controller is referred
/config/socket.js onConnect(), onDisconnect(): If you want to add or remove the connected socket to/from some rooms, or some initial socket setup, etc.
/policies/sessionAuth.js: for some real-time authen logic
Other places...
Beside, you should consider the resourceful-pubsub feature which may help you save a lot of effort on implementing real-time process with socket. I found that it's very cool :)

Socket.IO Scoping Issue (Node.JS)

I am working on a node.js project that I am leveraging Socket.IO in, and am having an issue getting my head around a scoping issue. Here is what I am trying to do:
var io = require('socket.io').listen(80);
session_manager = require('./includes/session_manager');
// client joins the socket server
io.sockets.on('connection', function(client) {
client.on('X.Session.join', function(session_id, client) {
session_manager.joinSession(session_id, function(err, session) {
// do whatever
});
});
// BRING IN MORE LISTENERS/EMITTERS?
require('someModuleIBuild');
});
As you can see I am basically setting up the initial connection, joining a session via a managing class (so I know who to emit to for which session) and then I am trying to dynamically bring in some custom stuff that ALSO is going to be emitting and listening via the socket connection.
So how do I reference this current connection from within the confines of my custom modules? All the examples I have seen have all the "on" and "emit" functions in one file, which seems like it could get out of control pretty quickly.
I am possibly over-thinking/over-complicating this (this is my first node.js project, first socket-based project, first mostly-javascript project....etc) but any help would be appreciated.
create your modules like this and you can pass the client into the module
module.exports = function(client) {
client.on("whatever", function () {
});
client.on("whenever", function (data) {
});
};
and then do the require like this
require('someModuleIBuild')(client);

Categories