node.js and juggernaut pub/sub - node.js

I'm using express framework and juggernaut. I looked at many examples about juggernaut, all examples using this method(client side):
var jug = new Juggernaut;
jug.subscribe("channel_name", function(data){
console.log("Got data: " + data);
});
Is it secure? I don't think so, everybody can subscribe to a channel from javascript console. Is there a way to subscribe a channel from server side?

Use security through obscurity, use a random channel name (HMAC).

I don't know how Juggernaut works, but I know that Faye supports extensions that can include authentication, so that subscribe operations require a valid token. See: http://faye.jcoglan.com/node.html
It would be worth checking whether Juggernaut supports a similar extension/intercept model.

Related

Websocket vs SSE to implement a real time friend invitation system on React/Node

I would like to implement a system that allows users to add each other as friends and share data between them. I have gotten the authentication done and currently researching ways to do this real time. This project of mine is purely a learning experience so I am looking for many ways to perform this task to grow my knowledge.
I have experience using Websockets on a previous project and it was easy to use. Websockets seems like the best solution to my problem as it allows the user to send and receive invites through the open socket. However I have also learnt that the downside would be a long open socket connection that might be potentially performance taxing(?) Since I'm only sending/receiving information only when an invite is sent/received, websockets might be overutilized for a simple function.
At the same time I would like to learn about new technologies and I found out about Server Sent Events that would be less performance heavy(?) Using SSE would be much efficient as it only sends HTTP requests to the clients/server whenever the user send the invite.
Please correct me if I'm wrong for what I typed out above as this is what I gathered through my reading online. So now I'm having a hard time understanding whether SSE is better than websocket for my project. If there are other technologies please do let me know too! Thank you
how you doing ?
The best advise would be always to use websocket in this context, cuz your project can grow and need some feature that would be better using websocket
But you got another options, one of the is Firebase, Yes, FIREBASE!
You can do a nice reactive application with firebase, becouse the its observers update data in realtime, just like the websockets do.
But here go some cons and pros.
Websocket: Can make your project escalable, its more complete, you can use it in any context, BUT: is hard to implement and takes more time to be learned and understood.
Firebase, Easy and fast to implement, you can do a chat in 20 minuts, and surelly would help you with your problem, There is Firestore and Reatime database.. even the firestore updates in realtime.. BUT: Firebase costs in a big project can be expensive, i dont think is a good option for a big project.
Thats it.. the better options to do a real time data application to me.
A little bit more about. Firebase vs Websocket
https://ably.com/compare/firebase-vs-socketio
to send a friend invitation, you just send an API request. WebSocket is used for real time communication. From react.js, get the email and send the email to the server
export const sendFriendInvitation = async (data) => {
try {
return axios.post("/friend-invitation", data);
} catch (exception) {
console.error(error)
}
};
On node.js side, write a controller to control this request:
const invitationRequest = async (req, res) => {
// get the email
const { targetMail } = req.body;
// write code to handle that same person is not sending req to himself
// get the details of user who sent the email
const targetUser = await User.findOne({
mail: targetMail.toLowerCase(),
});
if (!targetUser) {
return res
.status(404)
.send("send error message");
}
// you should have Invitations model
// check if invitation already sent.
// check if the user we would like to invite is our friend
// now create a new invitation
// if invitation has been successfully created, update the user's friend
return res.status(201).send("Invitation has been sent");
};

FCM XMPP: no 'success' response

I am using nodejs to implement a server application with XMPP. I am following the guide to authorize an XMPP connection. My problem is exactly when I expect a
<success xmlns="urn:ietf:params:xml:ns:xmpp-sasl"/>
when I send the server key, a SASL PLAIN authentication. It is made this way
const key = Buffer('\x00' + senderId + '#gcm.googleapis.com\x00' + serverKey).toString('base64');
const message = `<auth mechanism="PLAIN"
xmlns="urn:ietf:params:xml:ns:xmpp-sasl">${key}</auth>`;
Where senderID is that number that is in "Cloud Messaging" tag and
serverKey is one of the server keys from the "Cloud Messaging" tag. There are two server keys types: one is the "normal" and the other one is inherited; I've used both types without success.
I don't really know what I am doing wrong, or what I am missing.
The first two steps of the connection, the 'hello' and the list of mechanisms response from FCM are done. However, after this, FCM closes the connection. I suspect is related with this problem.
I would appreciate a help. Thanks.
I've contacted with the Firebase support team and they have solved my problem (thanks a lot).
The thing, with nodejs, is you have to avoid to implement the event 'end' on the socket because this seems to force to close the socket, and use the same socket. Another thing is to avoid set up the socket encoding. You can convert the buffer with another encoding though.
With all this I can mark this question as solved.

Connecting to socket.io 1.x manually using websockets, capacity testing

I am working with a nodejs express server which uses socket.io to communicate an iOS client, and am having a little trouble trying to test how many clients can connect and exchange data at any one time.
My goal is to be able to run a script which connects to socket.io with thousands of different sessions, as well as send and receive data to understand our system's scale. Currently we are using a single dyno on Heroku but will likely be considering other options on AWS soon.
I have found code which should do what I am trying to do for earlier versions of socket.io, such as this, but have had issues since it seems v1.x has a very different handshake protocol. I tried out using the socket.io-client package, but trying to connect multiple times only simulates use of one session, I need to simulate many in independent users.
I have been picking apart the socket.io-client code, but have only gotten so far as creating a connection - I am stuck on the sending data part. If anyone has any knowledge or could point to some written resources on how data is sent between a client and a socket.io server, it would help me out a lot.
Here's what I have so far:
var needle = require('needle'),
WebSocket = require('ws'),
BASE_URL = 'url-to-socket-host:5002';
var connectionNo = 0;
needle.get('http://' + BASE_URL + '/socket.io/?EIO=3&transport=polling&t=1416506501335-0', function (err, resp) {
// parse the sid
var resp = JSON.parse(resp.body.toString().substring(5, resp.body.toString().length));
// use the sid to connect using websockets
var url = 'ws://' + BASE_URL + '/socket.io/?EIO=3&transport=websocket&sid=' + resp.sid;
console.log(connectionNo + ' with sid: ' + resp.sid);
var socket = new WebSocket(url, void(0), {
agent: false
});
socket.on('open', function () {
console.log('Websocket connected: ' + connectionNo);
// I don't understand how to send data to the server here,
// from looking at the source code it should use some kind
// of binary encoding, any ideas?
socket.on('message', function (msg) {
console.log(msg);
});
});
});
I will continue deconstructing the socket.io-client code but if anyone has any clues or recourses that may help, let me know. Thanks.
I ended up setting for using the socket.io-client npm package which has the ability to connect to a new session on every connection. I found an example benchmark in this issue.
There is not so much need for me to manually connect to socket.io using pure websockets and HTTP, but thanks to Yannik for pointing out the parser in use. The spec of the inner workings of v1.x can be found here.
Thanks!
The problem my reside in the fact that you are not using socket.io in your client code. You have imported ('ws') which is another module whose docs are here: https://www.npmjs.org/package/ws.
You probably want to ws.send('something');. When you receive a message in ws, it also comes with an object with a property indicating whether it is binary data or not. If it is, you will need to concatenate the chunks incrementally. There is a canonical way to do this which you can find via google. But it looks a little like this:
var message;
socketConnection.on('data', function(chunk){ message += chunk});

DNode implementation for websocket communication in node.js

I don't understand the way DNode uses websocket communication.
Some say it uses socket.io others say sockjs.
Which one is it? Or is it possible to choose?
I'm trying to use DNode, but I also need access to the connections for (semi-)broadcasting in reaction to RPC calls. How do I do this?
Is there a more extensive manual on dnode somewhere?
Your question is kind of vague. I'm not exactly sure whether DNode uses socket.io or sockjs, not sure it even uses one of those based on their dependencies list, but that is not really important when you program it.
As for using connections with DNode, it is pretty straight forward. Here's an example:
var server = dnode({
pushMessageNotification: function(message, cb) {
contact = getClientFromId(message.receiver);
contact.socket.emit('messageNotification', {
message: message.message,
sender: message.sender,
time: message.time
});
cb('success');
}
});
So as you can see, pushMessageNotification is a method that I binded with DNode-PHP and the message is encoded in JSON through PHP. Afterward, all you need is a method to find the socket of the client based on its id.

Differences between socket.io and websockets

What are the differences between socket.io and websockets in
node.js?
Are they both server push technologies?
The only differences I felt was,
socket.io allowed me to send/emit messages by specifying an event name.
In the case of socket.io a message from server will reach on all clients, but for the same in websockets I was forced to keep an array of all connections and loop through it to send messages to all clients.
Also,
I wonder why web inspectors (like Chrome/firebug/fiddler) are unable to catch these messages (from socket.io/websocket) from server?
Please clarify this.
Misconceptions
There are few common misconceptions regarding WebSocket and Socket.IO:
The first misconception is that using Socket.IO is significantly easier than using WebSocket which doesn't seem to be the case. See examples below.
The second misconception is that WebSocket is not widely supported in the browsers. See below for more info.
The third misconception is that Socket.IO downgrades the connection as a fallback on older browsers. It actually assumes that the browser is old and starts an AJAX connection to the server, that gets later upgraded on browsers supporting WebSocket, after some traffic is exchanged. See below for details.
My experiment
I wrote an npm module to demonstrate the difference between WebSocket and Socket.IO:
https://www.npmjs.com/package/websocket-vs-socket.io
https://github.com/rsp/node-websocket-vs-socket.io
It is a simple example of server-side and client-side code - the client connects to the server using either WebSocket or Socket.IO and the server sends three messages in 1s intervals, which are added to the DOM by the client.
Server-side
Compare the server-side example of using WebSocket and Socket.IO to do the same in an Express.js app:
WebSocket Server
WebSocket server example using Express.js:
var path = require('path');
var app = require('express')();
var ws = require('express-ws')(app);
app.get('/', (req, res) => {
console.error('express connection');
res.sendFile(path.join(__dirname, 'ws.html'));
});
app.ws('/', (s, req) => {
console.error('websocket connection');
for (var t = 0; t < 3; t++)
setTimeout(() => s.send('message from server', ()=>{}), 1000*t);
});
app.listen(3001, () => console.error('listening on http://localhost:3001/'));
console.error('websocket example');
Source: https://github.com/rsp/node-websocket-vs-socket.io/blob/master/ws.js
Socket.IO Server
Socket.IO server example using Express.js:
var path = require('path');
var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);
app.get('/', (req, res) => {
console.error('express connection');
res.sendFile(path.join(__dirname, 'si.html'));
});
io.on('connection', s => {
console.error('socket.io connection');
for (var t = 0; t < 3; t++)
setTimeout(() => s.emit('message', 'message from server'), 1000*t);
});
http.listen(3002, () => console.error('listening on http://localhost:3002/'));
console.error('socket.io example');
Source: https://github.com/rsp/node-websocket-vs-socket.io/blob/master/si.js
Client-side
Compare the client-side example of using WebSocket and Socket.IO to do the same in the browser:
WebSocket Client
WebSocket client example using vanilla JavaScript:
var l = document.getElementById('l');
var log = function (m) {
var i = document.createElement('li');
i.innerText = new Date().toISOString()+' '+m;
l.appendChild(i);
}
log('opening websocket connection');
var s = new WebSocket('ws://'+window.location.host+'/');
s.addEventListener('error', function (m) { log("error"); });
s.addEventListener('open', function (m) { log("websocket connection open"); });
s.addEventListener('message', function (m) { log(m.data); });
Source: https://github.com/rsp/node-websocket-vs-socket.io/blob/master/ws.html
Socket.IO Client
Socket.IO client example using vanilla JavaScript:
var l = document.getElementById('l');
var log = function (m) {
var i = document.createElement('li');
i.innerText = new Date().toISOString()+' '+m;
l.appendChild(i);
}
log('opening socket.io connection');
var s = io();
s.on('connect_error', function (m) { log("error"); });
s.on('connect', function (m) { log("socket.io connection open"); });
s.on('message', function (m) { log(m); });
Source: https://github.com/rsp/node-websocket-vs-socket.io/blob/master/si.html
Network traffic
To see the difference in network traffic you can run my test. Here are the results that I got:
WebSocket Results
2 requests, 1.50 KB, 0.05 s
From those 2 requests:
HTML page itself
connection upgrade to WebSocket
(The connection upgrade request is visible on the developer tools with a 101 Switching Protocols response.)
Socket.IO Results
6 requests, 181.56 KB, 0.25 s
From those 6 requests:
the HTML page itself
Socket.IO's JavaScript (180 kilobytes)
first long polling AJAX request
second long polling AJAX request
third long polling AJAX request
connection upgrade to WebSocket
Screenshots
WebSocket results that I got on localhost:
Socket.IO results that I got on localhost:
Test yourself
Quick start:
# Install:
npm i -g websocket-vs-socket.io
# Run the server:
websocket-vs-socket.io
Open http://localhost:3001/ in your browser, open developer tools with Shift+Ctrl+I, open the Network tab and reload the page with Ctrl+R to see the network traffic for the WebSocket version.
Open http://localhost:3002/ in your browser, open developer tools with Shift+Ctrl+I, open the Network tab and reload the page with Ctrl+R to see the network traffic for the Socket.IO version.
To uninstall:
# Uninstall:
npm rm -g websocket-vs-socket.io
Browser compatibility
As of June 2016 WebSocket works on everything except Opera Mini, including IE higher than 9.
This is the browser compatibility of WebSocket on Can I Use as of June 2016:
See http://caniuse.com/websockets for up-to-date info.
Its advantages are that it simplifies the usage of WebSockets as you described in #2, and probably more importantly it provides fail-overs to other protocols in the event that WebSockets are not supported on the browser or server. I would avoid using WebSockets directly unless you are very familiar with what environments they don't work and you are capable of working around those limitations.
This is a good read on both WebSockets and Socket.IO.
http://davidwalsh.name/websocket
tl;dr;
Comparing them is like comparing Restaurant food (maybe expensive sometimes, and maybe not 100% you want it) with homemade food, where you have to gather and grow each one of the ingredients on your own.
Maybe if you just want to eat an apple, the latter is better. But if you want something complicated and you're alone, it's really not worth cooking and making all the ingredients by yourself.
I've worked with both of these. Here is my experience.
SocketIO
Has autoconnect
Has namespaces
Has rooms
Has subscriptions service
Has a pre-designed protocol of communication
(talking about the protocol to subscribe, unsubscribe or send a message to a specific room, you must all design them yourself in websockets)
Has good logging support
Has integration with services such as redis
Has fallback in case WS is not supported (well, it's more and more rare circumstance though)
It's a library. Which means, it's actually helping your cause in every way. Websockets is a protocol, not a library, which SocketIO uses anyway.
The whole architecture is supported and designed by someone who is not you, thus you dont have to spend time designing and implementing anything from the above, but you can go straight to coding business rules.
Has a community because it's a library (you can't have a community for HTTP or Websockets :P They're just standards/protocols)
Websockets
You have the absolute control, depending on who you are, this can be very good or very bad
It's as light as it gets (remember, its a protocol, not a library)
You design your own architecture & protocol
Has no autoconnect, you implement it yourself if yo want it
Has no subscription service, you design it
Has no logging, you implement it
Has no fallback support
Has no rooms, or namespaces. If you want such concepts, you implement them yourself
Has no support for anything, you will be the one who implements everything
You first have to focus on the technical parts and designing everything that comes and goes from and to your Websockets
You have to debug your designs first, and this is going to take you a long time
Obviously, you can see I'm biased to SocketIO. I would love to say so, but I'm really really not.
I'm really battling not to use SocketIO. I dont wanna use it. I like designing my own stuff and solving my own problems myself.
But if you want to have a business and not just a 1000 lines project, and you're going to choose Websockets, you're going to have to implement every single thing yourself. You have to debug everything. You have to make your own subscription service. Your own protocol. Your own everything. And you have to make sure everything is quite sophisticated. And you'll make A LOT of mistakes along the way. You'll spend tons of time designing and debugging everything. I did and still do. I'm using websockets and the reason I'm here is because they're unbearable for a one guy trying to deal with solving business rules for his startup and instead dealing with Websocket designing jargon.
Choosing Websockets for a big application ain't an easy option if you're a one guy army or a small team trying to implement complex features. I've wrote more code in Websockets than I ever wrote with SocketIO in the past, for ten times simpler things than I did with SocketIO.
All I have to say is ... Choose SocketIO if you want a finished product and design. (unless you want something very simple in functionality)
Im going to provide an argument against using socket.io.
I think using socket.io solely because it has fallbacks isnt a good idea. Let IE8 RIP.
In the past there have been many cases where new versions of NodeJS has broken socket.io. You can check these lists for examples... https://github.com/socketio/socket.io/issues?q=install+error
If you go to develop an Android app or something that needs to work with your existing app, you would probably be okay working with WS right away, socket.io might give you some trouble there...
Plus the WS module for Node.JS is amazingly simple to use.
Using Socket.IO is basically like using jQuery - you want to support older browsers, you need to write less code and the library will provide with fallbacks. Socket.io uses the websockets technology if available, and if not, checks the best communication type available and uses it.
https://socket.io/docs/#What-Socket-IO-is-not (with my emphasis)
What Socket.IO is not
Socket.IO is NOT a WebSocket implementation. Although Socket.IO indeed uses WebSocket as a transport when possible, it adds some metadata to each packet: the packet type, the namespace and the packet id when a message acknowledgement is needed. That is why a WebSocket client will not be able to successfully connect to a Socket.IO server, and a Socket.IO client will not be able to connect to a WebSocket server either. Please see the protocol specification here.
// WARNING: the client will NOT be able to connect!
const client = io('ws://echo.websocket.org');
I would like provide one more answer in 2021. socket.io has become actively maintained again since 2020 Sept. During 2019 to 2020 Aug(almost 2 years) there was basically no activity at all and I had thought the project may be dead.
Socket.io also published an article called Why Socket.IO in 2020?, except for a fallback to HTTP long-polling, I think these 2 features are what socket.io provides and websocket lacks of
auto-reconnection
a way to broadcast data to a given set of clients (rooms/namespace)
One more feature I find socket.io convenient is for ws server development, especially I use docker for my server deployment. Because I always start more than 1 server instances, cross ws server communication is a must and socket.io provide https://socket.io/docs/v4/redis-adapter/ for it.
With redis-adapter, scaling server process to multiple nodes is easy while load balance for ws server is hard. Check here https://socket.io/docs/v4/using-multiple-nodes/ for further information.
Even if modern browsers support WebSockets now, I think there is no need to throw SocketIO away and it still has its place in any nowadays project. It's easy to understand, and personally, I learned how WebSockets work thanks to SocketIO.
As said in this topic, there's a plenty of integration libraries for Angular, React, etc. and definition types for TypeScript and other programming languages.
The other point I would add to the differences between Socket.io and WebSockets is that clustering with Socket.io is not a big deal. Socket.io offers Adapters that can be used to link it with Redis to enhance scalability. You have ioredis and socket.io-redis for example.
Yes I know, SocketCluster exists, but that's off-topic.
Socket.IO uses WebSocket and when WebSocket is not available uses fallback algo to make real time connections.
TLDR:
'Socket.io' is an application layer specification that can be implemented on top of/using the application layer specification 'websockets'.
websocket spec
socket.io spec
I think the simple answer here is in basic web technology definitions:
Specification: A documented standard detailing the requirements for a program to achieve in order to be labeled as "an implimentation of some sepc." It is important to achieve this rubber stamp when building programs, because any program is only as good at the machine executing the code. Programming is fundamentally built upon specifications, and if, they are not followed code will not execute correctly. However, a specification does nothing. It is just a text document.
Implementation: This is actual, executable code that accomplishes what the specification says to do.
Application Layer - System that defines messages and handshakes sent over transport. This is the stuff you have to know when working with HTTP/Websockets/Socketio. It defines how the connections will be made, authenticated, data will be sent, and how it will arrive.

Resources