Skip to content

Instantly share code, notes, and snippets.

@marclar
Created June 23, 2013 15:14
Show Gist options
  • Save marclar/5845371 to your computer and use it in GitHub Desktop.
Save marclar/5845371 to your computer and use it in GitHub Desktop.
Node.js sockets; under construction and assumes lo-dash, AngularJS and jQuery; maybe more.
//Assuming "app.io" is your socket.io object....
app.io.configure(function (){
//On handshake,
app.io.set('authorization', function (handshake, accept) {
//Require headers
if(handshake.headers){
//Try to get the cookie and the session ID (connect.sid)
var cookie = (function(pairs, obj){
pairs.forEach(function(pair){
var nv = pair.split('=');
obj[nv[0].trim()] = nv[1].trim();
});
return obj;
})(handshake.headers.cookie.split(';'), {});
if(cookie['connect.sid'] && cookie['connect.sid'].length){
//Store the sessionId
handshake.sessionId = decodeURIComponent(cookie['connect.sid']);
//Try to get this session
app.store.get(handshake.sessionId, function(err, sesh){
if(err){
app.page.socketSessionReady.reject('NO GOT SESH :( (7129882)', err).always(function(){
accept(err.message, false);
});
}
else{
handshake.user = sesh['user'];
app.page.socketSessionReady.resolve().always(function(){
accept(null, true);
});
}
});
}
else{
accept('no cookie.connect.sid found (4427087)', false);
}
}
else{
accept('handshake.headers not found (1089619)', false);
}
});
});
app.io.sockets.on('connection', function(socket){
//Initialize app.page with socket
app.page.init(socket).done(function(){
//Set an interval for the batphone
// setInterval(function(){
// app.page.batphone('Now it is: ' + (new Date()).toString());
// }, 5000);
});
});
//Assumes AngularJS; requires that the channels from server-page.js are embedded in the HTML...
_.each(config.page.channels, function(channel){
//log.note('Registering $rootScope.on("' + channel + '") (7688737)')
$rootScope.$on(channel, function(e, response){
if(channel === 'err'){
log('ng-app heard "err" (2659364)');
log.err(response);
}
else{
log.quiet('ng-app heard "' + channel + '", response: (8631102)');
}
});
});
//"app.page" -- interface to client-side page
var exports = {
//Will be initialized with socket connection
socket: null,
socketSessionReady: $.Deferred(function($d){
$d.timeout = setTimeout(function(){
$d.reject('socketSessionReady timed out (4985264)');
}, 20000);
}).fail(function(msg, err){
// console.log('app.page.socketSessionReady failed (2415067)', {msg: msg, err: err});
})
};
//Gets session data for passing to API calls
exports.getSession = function(){
var me = exports;
var $this = $.Deferred().fail(function(m){log(m);});
if(me.socket){
//Try to get this session
app.store.get(me.socket.handshake.sessionId, function(err, sesh){
if(err){
$this.reject('NO GOT SESH :( (1881765) + ' + err.toString());
}
else{
$this.resolve(sesh);
}
});
}
else{
$this.reject('app.page.socket isn\'t ready yet (4550832)');
}
//Return
return $this;
};
//Formats info from a client request + the socket headers
exports.getPostInfo = function(data){
var me = exports;
var result = null;
//Validate input
if(data.route && me.socket.handshake && me.socket.handshake.headers){
//Get HTTP request options
var o = (function(headers, hostpair){
return {
path: data.route,
headers: headers,
protocol: headers.referer.split(':')[0],
host: hostpair[0],
port: (hostpair.length > 1) ? parseInt(hostpair[1], 10) : 80
};
})(me.socket.handshake.headers, me.socket.handshake.headers.host.split(':'));
//Add POST data?
if(data.params){
if(_.isString(data.params) && data.params.length){
o.form = JSON.parse(data.params);
}
else if(_.isObject(data.params)){
o.form = data.params;
}
}
//Make URL
o.url = [o.protocol, '://', o.host, ':', o.port, o.path].join('');
//Set result
result = o;
}
//Return
return result;
};
//Format the data before sending via socket
exports.emit = function(name, data){
var me = exports;
if(me.socket){
me.socket.emit(name, _.extend(data, {_user: me.socket.handshake['user']}));
}
else{
log('ERROR: app.page.emit() -- socket is null (9691543)');
}
};
//Add listeners
exports.listeners = {
//Just reply to the client
echo: {
on: function(data){
var me = this;
setTimeout(function(){
me.echo(_.extend(data, {handshake: me.socket.handshake, time: Date.now(), ref: '8498763'}));
}, 1000);
}
},
hello: {
on: function(data){
var me = this;
setTimeout(function(){
me.hello({msg: 'Hi! It\'s ' + Date.now(), ref: '3966626'});
}, 1000);
}
},
//Just reply to the client
batphone: {
on: function(data){
var me = this;
// setTimeout(function(){
// me.ping(_.extend(data, {handshake: me.socket.handshake, time: Date.now(), ref: '8498763'}));
// }, 1000);
}
},
err: {
on: function(data){
var me = this;
log('app.page.err called (6830097)');
log(data);
}
},
callApi: {
on: function(data){
var me = this;
//Get POST info
var info = me.getPostInfo(data);
if(info){
//POST
me.post(info.url, info.headers, info.form).done(function(response){
me.callApi(response);
}).fail(function(err){
me.err(err);
});
}
else{
log(data);
me.err('Couldn\'t get POST info from data (2584945)');
}
}
},
callPrivate: {
on: function(data){
var me = this;
//Get POST info
var info = me.getPostInfo(data);
if(info){
//Also require a private "channel"
if(data.channel && data.channel.length){
//POST
me.post(info.url, info.headers, info.form).done(function(response){
//Call back on the private channel
log('Calling back on the private channel "' + data.channel + '" (2396329)');
me.emit(data.channel, response);
}).fail(function(err){
me.err(err);
});
}
else{
me.err('Need data.channel for private calls (7279067) + ' + JSON.stringify(data));
}
}
else{
me.err('Couldn\'t get POST info from data (6570100) + ' + JSON.stringify(data));
}
}
},
// hello: {
// on: function(data){
// var me = this;
// log('app.page.update() was called from the client! (3659967)');
// log(data);
// }
// },
update: {
on: function(data){
var me = this;
log('app.page.update() was called from the client! (3659967)');
log(data);
}
}
};
exports.init = function(socket){
var me = exports;
// log('in app.page.init(socket) (1462090)');
me.socket = socket;
//Set up all listeners
_(me.listeners).chain().map(function(superfun, key){
//Listen for this event
me.socket.on(key, function(data){
superfun.on.call(me, data);
});
//Also create an "emit" function
me[key] = (function(page, name){
return function(data){
me.emit(name, data);
};
})(me, key);
});
//Return the $Deferred for convenience
return me.socketSessionReady;
};
//Export
module.exports = exports;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment