Such a long title huh?
Well, this is a demo app showing the interaction between a NodeJS application and the browser on different ways: Twitter (OAuth) and Sockets (Socket.IO).
When the client (browser) hits the home page, a middleware function checks if the user’s session contains OAuth information. If there is no OAuth session, then the middleware starts what I call the “OAuth dance”, that is, get tokens, redirect the user to authorize the application, get authorization tokens, store them somewhere and finally perform a request on users’ behalf (fetch the timeline).
// Middleware to detect if the client is or not authenticated to Twitter
// if not, start the OAuth process; if so, just let the normal flow continue
exports.auth = function(req, res, next) {
if (req.session.oauth && req.session.oauth.access_token && req.session.oauth.access_token_secret) {
next();
} else {
oa.getOAuthRequestToken(function(error, oauth_token, oauth_token_secret, results) {
if (error) {
res.send('yeah no. didn\'t work.');
} else {
req.session.oauth = {};
req.session.oauth.token = oauth_token;
req.session.oauth.token_secret = oauth_token_secret;
res.redirect('https://twitter.com/oauth/authenticate?oauth_token=' + oauth_token);
}
});
}
}
// Middleware to keep the /callback route clean.
// Handles the redirect url and saves tokens to session.
exports.callback = function(redirect) {
return function(req, res, next) {
if (req.session.oauth) {
req.session.oauth.verifier = req.query.oauth_verifier;
var oauth = req.session.oauth;
oa.getOAuthAccessToken(oauth.token, oauth.token_secret, oauth.verifier, function(error, oauth_access_token, oauth_access_token_secret, results) {
if (error) {
res.send('yeah something broke.');
} else {
req.session.oauth.access_token = oauth_access_token;
req.session.oauth.access_token_secret = oauth_access_token_secret;
res.redirect(redirect);
}
});
} else {
next(new Error('you\'re not supposed to be here.'));
}
}
}
Once the timeline was displayed on the browser it connects and starts a loop to check for new tweets; that is not new, but instead of doing it on the browser, we can do it on the server and just push the updates to the client
// ### Socket listeners
io.sockets.on('connection', function(socket) {
var session = socket.handshake.session;
var interval = setInterval(function() {
// Send our controller the required data to connect to Twitter
twitter_controller.since({
consumer_key: app.set('oauth consumer key'),
consumer_secret: app.set('oauth consumer secret'),
access_token: session.oauth.access_token,
access_token_secret: session.oauth.access_token_secret,
since_id: session.since_id
}, function(err, res) {
// TODO: Handle the error
if (err) {
console.log(err);
} else {
// Save last id
var since_id = _.max(res, function(tweet) {
return tweet.id;
});
if (since_id) {
session.since_id = since_id.id + 1;
session.touch().save();
}
// Send found tweets to the client
socket.emit('tweets', res);
}
});
}, 15 * 1000);
socket.on('disconnect', function() {
if (interval) {
clearInterval(interval);
}
});
});
As always you are free to read and use the full source of this example to start something even more interesting.
Thanks to Matt Hill and Daniel Baulig for their awesome examples!