Skip to content

Instantly share code, notes, and snippets.

@yogurt1
Last active December 14, 2016 08:15
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save yogurt1/fe53e27bca3ad92894a3db96090b4099 to your computer and use it in GitHub Desktop.
Save yogurt1/fe53e27bca3ad92894a3db96090b4099 to your computer and use it in GitHub Desktop.
Chat in pure Node.js at backend and Vanilla.js at frontend
var http = require("http");
var msgs = []; // All messages array
var subscribers = []; // All subscribers array
var PORT = process.env.PORT || 8080;
// Create HTTP server
var server = http.createServer(function(req, res) {
// Small router
switch(req.url) {
case "/":
// If got index request send chat html page
res.writeHead(200, {"Content-Type":"text/html"});
return res.end(html());
default:
// If request is unknown send 404
res.writeHead(404)
return res.end()
case "/subscribe": return subscribe(req, res);
case "/publish": return publish(req, res);
}
}).listen(PORT);
// Subscribe client for server-sent events
function subscribe(req, res) {
// Get index of subscriber
var id = subscribers.push(res) - 1
// Send HTTP headers
res.writeHead(200, {
"Content-Type": "text/event-stream",
"Cache-Control": "no-cache"
});
// Remove client from array
req.on("close", function() {
// unsubscribe
subscribers.splice(id, 1)
});
}
// Publish message to all clients
function publish(req, res) {
req.on("data", function(data) {
// Format message
var msg = formatMessage(data.toString(),
req.socket.remoteAddress,
req.socket.remotePort)
msgs.push(msg)
subscribers.forEach(function(s) {
s.write("data: " + msg + '\n\n');
})
});
}
function formatMessage(msg, remoteAddress, remotePort) {
var date = new Date();
var hour = date.getHours();
hour = (hour < 10 ? "0" : "") + hour;
var min = date.getMinutes();
min = (min < 10 ? "0" : "") + min;
var sec = date.getSeconds();
sec = (sec < 10 ? "0" : "") + sec;
// var year = date.getFullYear();
// var mont = date.getMonth() + 1;
// month = (month < 10 ? "0" : "") + month;
// var day = date.getDate();
// day = (day < 10 ? "0" : "") + day;
var formattedDate = hour + ":" + min + ":" + sec;
var meta = " - (" + remoteAddress + ":" + remotePort + "): ";
return formattedDate + meta + msg
}
// HTML template
function html(){
return ""
+ "<!DOCTYPE html><html><head></head><body>"
+ "<textarea id=\"msg\" rows=\"3\" cols=\"100\"></textarea><br>"
+ "<input type=\"button\" id=\"send\" value=\"Send\"><br>"
+ "<textarea disabled id=\"chat\" rows=\"30\" cols=\"100\"></textarea>"
+ "<script>"
+ "var chat = document.getElementById(\"chat\");/* Inject messages to document */"
+ "var msgs = " + JSON.stringify(msgs) + ";"
+ "chat.innerHTML = msgs.join('\\n');"
+ "/* Subscribe */"
+ "var es = new EventSource(\"subscribe\");"
+ "es.onmessage = function(msg) {"
+ "chat.innerHTML += \"\\n\";"
+ "chat.innerHTML += msg.data;"
+ "}"
+ "/* Publish */\n"
+ "document.getElementById(\"send\")"
+ ".addEventListener(\"click\", function() {"
+ "var textarea = document.getElementById(\"msg\");"
+ "var msg = textarea.value;"
+ "if (msg.length) {"
+ "var xhr = new XMLHttpRequest();"
+ "xhr.open(\"POST\", \"/publish\", true);"
+ "xhr.setRequestHeader(\"Content-Type\", \"text/plain\");"
+ "xhr.send(msg);"
+ "}"
+ "textarea.value = \"\";"
+ "textarea.focus();"
+ "});"
+ "</script></body></html>";
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment