Last active
May 19, 2016 12:33
-
-
Save jdrydn/58c2ee4d8a15c407316e4925f0d3d309 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!doctype html> | |
<html> | |
<head> | |
<title>Socket.IO chat</title> | |
<style> | |
* { margin: 0; padding: 0; box-sizing: border-box; } | |
body { font: 13px Helvetica, Arial; } | |
form { background: #000; padding: 3px; position: fixed; bottom: 0; width: 100%; } | |
form input { border: 0; padding: 10px; width: 90%; margin-right: .5%; } | |
form button { width: 9%; background: rgb(130, 224, 255); border: none; padding: 10px; } | |
#messages { list-style-type: none; margin: 0; padding: 0; } | |
#messages li { padding: 5px 10px; } | |
#messages li:nth-child(odd) { background: #eee; } | |
</style> | |
</head> | |
<body> | |
<ul id="messages"></ul> | |
<form action=""> | |
<input id="m" autocomplete="off" /><button>Send</button> | |
</form> | |
<script src="https://cdn.socket.io/socket.io-1.2.0.js"></script> | |
<script src="//code.jquery.com/jquery-1.11.1.js"></script> | |
<script> | |
var successFn = function (res) { | |
if (!res || !res.token) throw new Error('NO TOKEN'); | |
console.log('Thanks for logging in, ' + name); | |
var socket = io(); | |
socket.on('connect', function () { | |
socket.emit('authenticate', { | |
token: res.token | |
}); | |
}); | |
socket.on('error', function(err) { | |
if (err.type == 'UnauthorizedError' || err.code == 'invalid_token') { | |
// redirect user to login page perhaps? | |
console.log('User\'s token has expired'); | |
} | |
console.log(err); | |
}); | |
socket.on('authenticated', function () { | |
console.log('Thanks for authenticating, ' + name); | |
$('form').submit(function() { | |
socket.emit('send', { | |
text: $('#m').val() | |
}); | |
appendMessage({ | |
author: name, | |
text: $('#m').val() | |
}); | |
$('#m').val(''); | |
return false; | |
}); | |
socket.on('message', function (data) { | |
appendMessage(data); | |
}); | |
$.ajax({ | |
dataType: 'json', | |
url: '/messages', | |
success: function (res) { | |
if (res && Array.isArray(res.messages)) { | |
$('#messages').html(''); | |
res.messages.forEach(function (data) { | |
appendMessage(data); | |
}); | |
} | |
} | |
}); | |
}); | |
var appendMessage = function (data) { | |
$('#messages').append($('<li>').text((data.author || 'Anon') + ': ' + data.text)); | |
}; | |
}; | |
$(document).ready(function () { | |
var name = prompt('ENTER YOUR NAME'); | |
if (!name) { | |
alert('Without a name, you cannot chat'); | |
throw new Error('No name provided'); | |
} | |
console.log('HEY ' + name); | |
$.ajax({ | |
method: 'POST', | |
url: '/login', | |
headers: { | |
'Content-Type': 'application/json' | |
}, | |
dataType: 'json', | |
data: JSON.stringify({ | |
name: name | |
}), | |
success: successFn | |
}); | |
}); | |
</script> | |
</body> | |
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"env": { | |
"DEBUG": "SOCKET:*", | |
"NODE_ENV": "development" | |
}, | |
"ext": "js json hbs yml", | |
"ignore": [ | |
"coverage", | |
"node_modules" | |
] | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"name": "SOCKET-MOFO", | |
"version": "0.1.0", | |
"main": "sockets.js", | |
"dependencies": { | |
"body-parser": "^1.15.1", | |
"connect-redis": "^3.0.2", | |
"debug": "^2.2.0", | |
"express": "^4.13.4", | |
"express-session": "^1.13.0", | |
"hiredis": "^0.4.1", | |
"morgan": "^1.7.0", | |
"redis": "^2.6.0-2", | |
"socket.io": "^1.4.6", | |
"socketio-jwt": "^4.3.4" | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var bodyParser = require('body-parser'); | |
var debug = require('debug')('SOCKET:Server'); | |
var express = require('express'); | |
var http = require('http'); | |
var jwt = require('jsonwebtoken'); | |
var morgan = require('morgan'); | |
var path = require('path'); | |
var redis = require('redis'); | |
var socketIO = require('socket.io'); | |
var socketioJwt = require('socketio-jwt'); | |
var app = express(); | |
var redisClient = redis.createClient(); | |
var redisSubscriber = redis.createClient(); | |
var server = http.createServer(app); | |
var io = socketIO(server); | |
//app.use(bodyParser.json({ limit: '1mb' })); | |
//app.use(bodyParser.urlencoded({ extended: true })); | |
app.use(morgan('tiny')); | |
app.get('/', function (req, res) { | |
res.sendFile(path.join(__dirname, 'index.html')); | |
}); | |
app.post('/login', bodyParser.json({ limit: '1mb' }), function (req, res, next) { | |
var token = jwt.sign(req.body, 'window-between-diameter-expression', { | |
algorithm: 'HS256', | |
noTimestamp: true | |
}); | |
res.json({ | |
token: token, | |
payload: req.body | |
}); | |
}); | |
app.get('/messages', function (req, res, next) { | |
redisClient.lrange('chat:messages', 0, -1, function (err, messages) { | |
if (err) return next(err); | |
res.json(messages.map(function (message) { | |
return JSON.parse(message); | |
})); | |
}); | |
}); | |
io.sockets.on('connection', socketioJwt.authorize({ | |
algorithm: 'HS256', | |
secret: 'window-between-diameter-expression', | |
timeout: 15000, // 15 seconds to send the authentication message | |
// additional_auth: function (token, resolveFn, rejectFn) { | |
// console.log('Hooray!', token); | |
// resolveFn(); | |
// } | |
})); | |
io.sockets.on('authenticated', function (socket) { | |
// Subscribe to the Redis channel | |
redisSubscriber.subscribe('ChatChannel'); | |
console.log(socket.decoded_token); | |
// Handle incoming messages | |
socket.on('send', function (data) { | |
debug('IN', socket.decoded_token, data); | |
data.author = socket.decoded_token.name || 'Anon'; | |
// Publish it | |
redisClient.publish('ChatChannel', JSON.stringify(data)); | |
// Persist it to a Redis list | |
redisClient.rpush('chat:messages', JSON.stringify(data)); | |
}); | |
// Handle receiving messages from the PubSub-pipe | |
var newMessage = function (channel, data) { | |
debug('OUT', socket.decoded_token, channel, data); | |
data = JSON.parse(data); | |
// If this data is for this user, then send it to them | |
if (data.author !== socket.decoded_token.name) { | |
socket.emit('message', data); | |
} | |
}; | |
redisSubscriber.on('message', newMessage); | |
socket.on('disconnect', function () { | |
redisSubscriber.removeListener('message', newMessage); | |
}); | |
}); | |
server.listen(4000, '0.0.0.0', function () { | |
console.log('Listening on %s:%d', server.address().address, server.address().port); | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment