socket.io: Is is possible to intercept a join namespace request? - node.js

My Node.js knowledge is fairly basic. I'm using socket.io to create a server and socket.io-client-swift in an iOS app.
I would like the server to create a dynamic namespace depending on the users selection on the client app. The idea being that all users with a specific selection join the same namespace on the server. This allows messages to be broadcast to all of those users within the namespace.
The problem is that the socket.io documentation and code appears to assume that you will be hardcoding the namespace name in the node.js code and that the namespace will be defined before the client iOS code attempts to join it.
Here's what i would like to occur:
Client requests to join a namespace called 'abc'.
Server receives request.
Something on the server checks the request, figures out there is no current namespace for 'abc' and dynamically allocates one.
Server finishes processing the join request, connecting the socket to the newly created namespace.
It's step #3 that I'm having problems with. I've tried using io.use(function(socket, next){...} to intercept the incoming request, but it appears that occurs after the server has determined whether there is a matching namespace for the request.
Does anyone have any idea how to intercept an incoming namespace request?

I think I figured it out. I added some code to my server.js like this:
// Lets Swizzle in some wrapper code.
//var originalConnection = Client.prototype.connect;
Client.prototype.originalConnect = Client.prototype.connect;
Client.prototype.connect = function(name){
var nsp = io.nsps[name];
if (!nsp) {
io.of(name);
}
this.originalConnect(name);
};
Effectively I swizzled in a wrapper function that does the dynamic namespace creation.

Related

How to use existing socket for a NodeJS HTTP server?

I made a proof of concept Reverse HTTP implementation using NodeJS.
However reusing client's socket required me to set a private member property; is there a correct way to do it?
server._socket = socket;
server.emit('connection', server._socket);
NodeJS HTTP docs tell about server.listen(socket), but it didn't work; it threw an exception about illegal parameter.
Full sample code for both client & server available at: https://github.com/norjs/portal-service/blob/12-reverse-http-support/samples/reverse-http/client.js#L57

How to remove io.on('connection') listener?

I have some code for a socket.io server along the lines of:
var io = require("socket.io");
io = io(server);
io.on('connection', connectionHandler);
This all works great. I'm wondering how I can remove that connection listener - unlike socket, it appears that
io.removeListener('connection', connectionHandler);
doesn't work (I get "io.removeListener is not a function"). How do I remove that on('connection') listener?
If it matters, I'm working on a socket.io room managing library, and am writing a reset function. I'm using the reset function between test suites with Mocha. I'd like the reset function to remove the on connection listener.
Socket.io version is 1.3.7
If you work through how socket.io processes .on(), one can figure out that it's using the default top-level namespace as the EventEmitter and io.on() just forwards the function call to the top-level namespace object. So, you can get the top level namespace object and then just call any EventEmitter method on it like this:
var nsp = io.of('/');
nsp.removeListener('connection', connectionHandler);
I have verified that this works in my own test app and stepped through it in the debugger to verify it was working as expected.

Socket.IO define namespace in runtime

In socket.IO there are 2 ways to send message to users separately: rooms and namespaces. In my project I need both of them - namespaces to divide users of different applications and rooms for each namespace for private messages and other specific stuff.
It's quite easy to create rooms directly in runtime. But is it possible to do the same trick with namespaces? I'd like to do something like this:
io.of(*someFunctionToCreateNameSpaceInRuntime*)
.on('connection', function (socket) {
socket.emit(***);
});
There is very similar question, but id doesn't work now. Is it possible to send namespace name with params and store it somewhere before connection event fires?
Thanks for any advise.

Overwriting Backbone.sync for socket.io

Im working on a socket.io based server/client connection instead of ajax.
Client uses Backbone and I overwritten the Backbone.sync function with one
half assed of my own:
Backbone.sync = function (method, collection, options) {
// use the window.io variable that was attached on init
var socket = window.io.connect('http://localhost:3000');
// emit the collection/model data with standard ajax method names and options
socket.emit(method,{collection:collection.name,url:collection.url});
// create a model in the collection for each frame coming in through that connection
socket.on(collection.url,function(socket_frame){
collection.create(socket_frame['model']);
})
};
Instead of ajax calls I simply emit through socket attached to window.io
global var. Server listens to those emits and based on the model url, I don't want to change that behaviour and I use the default crud method names (read,patch...) inside each emited frame. The logic behind it (its a bit far thought, but who knows) that in case the client doesn't support Websockets I can easily fallback to default jQuery ajax. I attached the orginal Backbone.sync to a var so I can pass the same arguments to it when no websocket is available.
All it that greatness behalves properly and the server answers to the client events. The server emits then each model data as a seperate websocket frames in one connection.
I see the frames in the Network/Websocket filter as one (concurrent/established) connection
and things seems to be working
Currently the function assumes I pass a collection and not a model.
Questions:
Is that approach ok with you?
How can I use the socket.io callbacks on 'success' and 'failure' etc in Backbone the right way so I don't have to call the collection.create function 'by-hand'?
Is it better to establish different concurrent connections for models/collections or use the one already established instead?

Get a static request to push some data to clients using Node.js and Socket.io

I'm new to Node.js, and I've been playing with the "chat" example provided with the Socket.io install package. Is shows in a few lines of code how you can push some data to several clients (browsers) in a push-fashion (no pulling).
Here is the code on the server side : http://pastie.org/1537175
I get how you can send a message to a client with client.broadcast(msg), but I don't get how you can do it outside of the
io.on('connection', function(client){
... }
loop
I would like to invoke a client.broadcast(msg) when someone hits a particular url (like '/test.html'), see line #32. The device asking for the '/test.html' is not a typical "ajax-enabled" browser, but a mere text-based browser, so I cannot initialize an asynchronous request with the server. Any idea?
Thank you.
you can use .broadcast on your io object
case '/test.html':
io.broadcast('test'); // This is where I would like to invoke a client.broadcast(msg);
break;

Resources