How to use socket.io in app route - node.js

I develop my first project with nodejs. I use express 3 as framework and socket.io for the client server communication. At the moment I’m trying to create a register form. It works quite well, but I’m not sure how to use socket.io and express together correctly.
I check if the email and the password are valid, if they are not, I would like to push a json object the client.
I use this app route:
app.post('/user', function (req, res) {
var user = new User(req.body.user),
errors;
function userSaveFailed() {
res.render('index');
}
errors = user.validation(req.body.user.confirm);
user.save(errors, function (err) {
if (err) {
// Here I would like to send the Object to the client.
io.sockets.on('connection', function (socket) {
socket.emit('registration', {
errors : errors
});
});
return userSaveFailed();
}
res.render('user/new.jade');
});
});
Well, the client gets the json object, but if another client connects to '/' he also gets the object. I guess I use the socket.io wrong. What’s the common way to use a .emit() in an app route? Is it necessary to use a global authorization for socket.io and express for this test?

one way to do that (if you really want to use socket.io to reply to a post, which you probably shouldn't), is to use one room per user session.
so on the on("connection", ...) do something like so:
socket.join(room) where room is something unique to the session (like the session id for example).
then to send back to only one user:
socketio.of('/')['in'](room).emit(...);, room being that same unique id used above.

Related

How to use Express with Socket.io?

I have the Express code in server JS file:
app.post('/confirm', function (req, res) {
// Here I need to send socket with emit()
});
Below mentioned code I have Socket.io:
io.on('connection', function (client) {
// All methods
});
Problem is that I can not get access to socket in express method app.post() and can not send data by POST action.
How can I use that?
You can emit data to specific connected sockets using the following:
io.to(socket_id).emit('something', {"bar":"foo"});
The "socket_id" variable is, as probably guessed, the socket.id from the connected socket.
You will probably have to store them along with some other identification in an array or object to send data to the correct clients later using express routes.
PS: As your code is
io.on('connection', function (client) {
// All methods
});
you would use client.id to get the socket id.

How do I emit data over socket io every time the database is updated?

I am building a system where I have a standalone administrative dashboard with a client interface. The front end is built on angularjs, and I'm using a boilerplate Node.js/Express server on the backend, which I have connected to a MySql database.
Every time a client submits new information from the client interface, it is submitted to the server, routed by the router to a controller, which passes the data to a model and uploads it to the database.
What I would like to do is every time the controller is called that handles the request, after the request has completed, I want to emit the new data over socket.io to the administrative dashboard.
My challenge is I have no idea how to access the socket from within the controller??? Any help would be greatly appreciated!
Yeah it's tricky. Like Express, Socket.io a request handling library of its own. They both work separately and independently, so there's no easy way to "switch" from Express to Socket.
However if you can identify a client uniquely, you can store its socket.id somewhere and then you can use the io from your Express controller to emit to that client's socket.
You can do io.to(socket.id).emit which is same as socket.emit, so as long as you have socket.id you can emit to it using io which is globally available.
I use Passport authentication in most apps so I find that using req.user is a great way to uniquely identify a client. It can even be a behind-the-scenes "pseudo" authentication by generating random userid/pass for each client.
Then there's this passport.socketio module to Access passport.js user information from a socket.io connection. Here's an article from the author that goes into the details of it all.
Using them together you can use the user object to store and access socket.id and use it to communicate to the client via socket.io
io.on('connection', function(socket){
var user = socket.request.user; // from socketio.passport
// store the socket.id inside the user so it can be retrieved from Express
user.socketid = socket.id;
});
app.post('/form', function(req, res, next){
var user = req.user; // from Passport
var socketid = user.socket.id // from socket above
var data = req.body;
doStuff(data);
io.to(socketid).emit('done');
});

socket.io: Is it safe to store sensitive data inside the handshake object?

I would like to save some user sensitive data in the handshake object. The server side code looks something like this:
io.configure(function (){
io.set('authorization', function (handshakeData, callback) {
var objAuthorized = IsUserAuthorized(handshakeData);
if (objAuthorized.authorized) {
handshakeData.password = objAuthorized.password; // Store sensitive data inside handshake
handshakeData.email = objAuthorized.email; // Store sensitive data inside handshake
callback(null, true);
} else {
callback(null, false);
}
});
});
io.sockets.on('connection', function (socket) {
socket.on('do something', function() {
if DoSomething(socket.handshake.password, socket.handshake.email) {
// do something here
}
});
});
The above example was taken from https://github.com/LearnBoost/socket.io/wiki/Authorizing .
Is it safe to save sensitive data in the handshake object? Can a client somehow modify this data during the lifetime of his socket connection?
Thanks
As far as know, there hasn't been any problem with this, a user can't get privileges from the authorization in socket.io .. but its not considered a good way or good practice to do this.
Most of developers won't do this, they handle authentication/authorization in other part of their application and leave to cookies and sessions validation on socket.io. This will also remove an overhead on the socket.io server.
updated
the following examples show how to work with sessions express/socket.io
some useful links :
http://howtonode.org/socket-io-auth
https://github.com/LearnBoost/socket.io/wiki/Authorizing
Note that you have to authenticate the user in a common login form, matching credentials against a database, if you have worked previously with PHP and user authentication you wont have a problem. After matching the user credentials you set the sessionID and any other data, then the rest is handled by express.

How to send a temporary chunk of html and js to a running app on node.js

I just got my first app up and running on Node.js. As of now, it is simply serving up a static file. But I have a few ideas that will be implemented down the road so I'm going ahead and getting Node setup so I'll be ready for it when that time comes.
// get modules
var express = require('express');
var fs = require('fs');
// create app instance
var app = express();
// static files middleware
app.use("/assets", express.static(__dirname + '/assets'));
// main route
app.get('/', function(req, res) {
var html = fs.readFileSync('assets/views/main.html', 'utf8');
res.send(html);
});
// make web server listen on specific port
app.listen(8080);
NOTE: I realize I don't need Express to serve one route, but I figured what's the harm in getting a head start on that as well?! :)
The first idea i had is to make a way to let all users currently using the app that there has been an update and that they must refresh their browser. There is no need to save the current state of the app as it is pretty basic.
So, if I am a user, I'm using the app and boom, I get a pretty little modal-window-alert-notification thingy letting me know that I need to refresh.
Also, if some user loads the app AFTER I have sent the alert, that user should not see the alert at all (because they should already be seeing the new changes).
I have done some googling on the subject and I'm just not satisfied with the examples i found. I do not think I want to have to update a notifications.xml file (which node.js would be watching) to push a new notification.
One solution I can think of would be to make a command that can be executed from the command line that will (somehow) send a new notification to the app. Perhaps using something like Grunt.js (I'm not sure if it would be a good fit for this as I've never used it). Basically, once the notification has been sent, all traces of it should disappear. That's why I think a command line approach would be good.
Here's my question: How (generally speaking) should I implement something like this? I am a Node.js newbie but I am pretty comfortable with javascript and the command line.
Please feel free to offer up any alternative solution you think would be better for me (other than a command line approach), or any tools that you think could help me.
Thanks!
If you want to push updates to a web client, one way is to use something like Socket.io. This creates a two-way pipe between client and server that you can use to asynchronously push updates through.
Sample server:
var app = require('express').createServer()
, io = require('socket.io').listen(app);
app.listen(80);
app.get('/', function (req, res) {
res.sendfile(__dirname + '/index.html');
});
io.sockets.on('connection', function (socket) {
socket.emit('news', { hello: 'world' });
socket.on('my other event', function (data) {
console.log(data);
});
});
Sample client:
<script src="/socket.io/socket.io.js"></script>
<script>
var socket = io.connect('http://localhost');
socket.on('news', function (data) {
alert('New news has come in! Please refresh your page!');
socket.emit('my other event', { my: 'data' });
});
</script>
The other option is to poll from the client using Javascript to actively look for updates. You would need to keep some state on the server for each client that would determine if that client required an update. The client would then make a get request on some timer interval (once a second, for example) to a secondary route and the server would reply with 'Yes, you need an update' or 'No, you don't need an update'. If yes, the client Javascript would then pop up your modal box and tell the user to refresh.

socket.io with express

i have a project and I'm using socket.io with express ,
so what i need (i tried) is broadcasting a message but from an express action.
is this possible i don't know how to get a reference to send or broadcast.
app.get('/', function(req, res) {
//i need to send messages from here
});
Other things like using both express+socket.io is working with me :)
As long as I understand,
Why not use the socket message type as an event instead of a http get or post? On the client side you would send a message via the websocket with let's say an event property.
So in your case:
<script>
// Initialize socket.io ...
// and then
socket.send({event: 'homepage loaded', foo: 'bar'});
</script>
And on the server side:
var io = io.listen(server);
io.on('connection', function (client) {
client.on('message', function (message) {
if (message.event == 'homepage loaded') {
client.broadcast(...);
}
});
});
You might want to have a look at my socket.io + Express primer. What you want is covered in detail there.
// Send to all connected sockets
io.sockets.send('Hello, World!');
// Send to all sockets in a specified room
io.sockets.in('room').send('Hello, Room!');
Where io is the value returned by the call to socketio.listen(). You can place that code anywhere in your application, eg in your app.get callbacks.
Check out my example repo where I use ExpressJS + Juggernaut(pubsub over socket.io):
http://github.com/shripadk/express-juggernaut-demo
This might be overkill for what you need as it uses Publish/Subscribe. But it does, to a certain extent, solve your issue of using regular ExpressJS routes. Checkout the master branch after cloning the repository:
git checkout master
I Found a nice example how to make what i need but with faye it's here http://nodecasts.org/.
I don't know the difference between Juggernaut ,Faye and direct Socket.io but Faye is good
for my case .And i think both of them use Socket.io internally.

Resources