Skip to content

Instantly share code, notes, and snippets.

@stretchgz

stretchgz/README.md Secret

Last active Aug 29, 2015
Embed
What would you like to do?
realtime chatroom using socket.io

Install and Running

Run the commands in Terminal

$ npm install
$ node app.js

Nginx Proxy Config File

chat.example.com.conf

map $http_upgrade $connection_upgrade {
	default upgrade;
	''      close;
}

upstream chatroom {
	server 127.0.0.1:8033;
}

server {
	listen       80;
	server_name example.com;
	location / {
		proxy_pass http://chatroom;
		proxy_redirect off;
		proxy_cache off;
		# Socket.IO Support
		proxy_http_version 1.1;
		proxy_set_header Upgrade $http_upgrade;
		proxy_set_header Connection $connection_upgrade;
	}

	access_log off;
	error_log /dev/null crit;
}

/*jslint node: true */
'use strict';
var app = require('http').createServer(handler);
var io = require('socket.io')(app);
var fs = require('fs');
var validator = require('validator');
// Index page
function handler(req, res) {
fs.readFile(__dirname + '/index.html',
function(err, data) {
if (err) {
res.writeHead(404);
return res.end('Error loading index.html');
}
res.writeHead(200);
res.end(data);
});
}
// ---------- WEBSOCKET ----------
var userOnline = 0;
io.on('connection', function(socket) {
userOnline += 1;
// broadcast to everyone, new user wont see this
socket.broadcast.emit('new user');
socket.on('add chat', function(data) {
var now = new Date(),
nowJSON = now.toJSON(),
userName,
msg,
randomColor = Math.floor(Math.random() * 16777215).toString(16);
userName = validator.trim(validator.escape(data.uname.slice(0, 20)));
// keep the first 50 chars and escape all inputs (prevents XSS)
if (data.msg.length > 50)
msg = validator.trim(validator.escape(data.msg.slice(0, 50)));
else
msg = validator.trim(validator.escape(data.msg));
// send the msg to all people
io.sockets.emit('update chat', {
'timestamp': nowJSON,
'uname': userName,
'color': randomColor,
'msg': msg
});
});
// track new visitor URL, IP, timestamp
io.sockets.emit('gg', {
'con': userOnline
});
socket.on('disconnect', function() {
userOnline -= 1;
io.sockets.emit('gg', {
'con': userOnline
});
});
});
// NODE is listening on port #
app.listen(8033, function() {
console.log('Listening on port %d', app.address().port);
});
<!doctype html>
<html lang="en">
<head>
<title>chatroom</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1">
<script src="https://cdn.socket.io/socket.io-1.0.6.js"></script>
<style>
body {
padding: 2em;
}
#new_con, #new_bad {
background: #f1da36;
display: none;
left:0;
padding:.5em;
position: fixed;
text-align: center;
top:0;
width:100%;
}
#new_bad {
background-color: #FF6A62;
}
li {
border-bottom: 1px solid #ccc;
display: block;
list-style: none;
padding: 1em;
position: relative;
-webkit-animation: slideIn .5s;
animation: slideIn .5s;
transition: all .5s;
-webkit-transform-origin: 100% 200%;
transform-origin: 100% 200%;
}
@-webkit-keyframes slideIn {
0% {
-webkit-transform: translateY(-5em) rotateX(90deg);
transform: translateY(-5em) rotateX(90deg);
opacity: 0;
background-color: rgba(252, 210, 9, .6);
}
}
@keyframes slideIn {
0% {
-webkit-transform: translateY(-5em) rotateX(90deg);
transform: translateY(-5em) rotateX(90deg);
opacity: 0;
background-color: rgba(252, 210, 9, .6);
}
}
li span, li b {
margin-right: 1em;
}
</style>
</head>
<body>
<noscript>Please enable JavaScript.</noscript>
<h1>work. work.
<span id="online">1</span>
</h1>
<form autocomplete="off">
<p>Send message to channel:</p>
<p>
<input type="text" id="username" placeholder="John Doe" max="20">
</p>
<p>
<input type="text" id="text" placeholder="Type a message" max="150" required autofocus>
<button>Submit</button>
</p>
</form>
<div id="talk"></div>
<div id="new_con">A user joined.</div>
<div id="new_bad">Bad connection.</div>
<script src="//cdnjs.cloudflare.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/moment.js/2.6.0/moment.min.js" async></script>
<script>
$(function() {
var socket = io();
var input = $('#text'),
form = $('form'),
talk = $('#talk'),
username = $('#username');
// send chat message to server
form.on('submit', function() {
if (input.val().length == 0)
return false;
socket.emit('add chat', {
uname: username.val(),
msg: input.val()
});
input.val('');
return false;
});
// receive something from server
socket.on('all new usr', function() {
$('#new_con').show();
setTimeout(function() {
$('#new_con').fadeOut();
}, 1000);
});
socket.on('update chat', function(data) {
var listTemplate = $('<li>'),
timeHumanReadable = moment(data.timestamp).format('lll'),
timeDynamic = moment(data.timestamp).fromNow();
if (!data.uname)
data.uname = username.attr('placeholder');
talk.prepend(
listTemplate
.append(
'<span class="time" data-timestamp="' + data.timestamp + '" title="' + timeHumanReadable + '">[' +
timeDynamic + ']</span> ' +
'<b style="color:#' + data.color + ';">' + data.uname + '</b>' + data.msg
)
);
});
// update chat timestamp at 10sec inteveral using Moment.js
setInterval(function() {
$('.time').each(function() {
$(this).text(
'[' + moment($(this).data('timestamp')).fromNow() + ']'
);
});
}, 10000);
// clean up the chat if too much
var clearUpChatDaemon = setInterval(function() {
if ($('#talk li').length > 100) {
$('#talk li').slice(-5).remove();
console.log("Cleaning up the chat box...")
}
}, 2000);
/** hello server */
socket.on('gg', function(data) {
$('#online').text(data.con);
});
});
</script>
</body>
</html>
{
"name": "realtime-chat-example",
"description": "realtime chat using socket.io and express",
"version": "0.0.1",
"private": true,
"main": "app.js",
"scripts": {
"start": "node app.js"
},
"engines": {
"node": "0.10.x"
},
"dependencies": {
"socket.io": "*",
"validator": "*"
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.