2020-05-19 11:43:42 +03:00

171 lines
4.9 KiB
JavaScript

var PORT1 = 8004;
var PORT2 = 8003;
var http = require("http");
var fs = require("fs");
var url = require("url");
var util = require("util");
var EventEmitter = require("events").EventEmitter;
util.puts("Version: " + process.version);
util.puts("Starting server at http://localhost:" + PORT1);
process.on("uncaughtException", function (e) {
try {
util.puts("Caught exception: " + e + " " + (typeof e === "object" ? e.stack : ""));
} catch (ignore) {
}
});
var emitter = new EventEmitter();
var history = [];
var heartbeatTimeout = 9000;
var firstId = Number(new Date());
setInterval(function () {
emitter.emit("message");
}, heartbeatTimeout / 2);
function eventStream(request, response) {
var parsedURL = url.parse(request.url, true);
var lastEventId = Number(request.headers["last-event-id"]) || Number(parsedURL.query.lastEventId) || 0;
var authorization = request.headers["authorization"];
if (parsedURL.query.authorization !== undefined && !authorization) {
response.writeHead(401, {
"WWW-Authenticate": "Basic realm=\"EventSource" + (1 + Math.random()).toString().slice(2) + "\"",
"Access-Control-Allow-Origin": "*"
});
response.end("");
return;
}
function sendMessages() {
lastEventId = Math.max(lastEventId, firstId);
while (lastEventId - firstId < history.length) {
response.write("id: " + (lastEventId + 1) + "\n" + "data: " + (history[lastEventId - firstId]).replace(/[\r\n\x00]/g, "\ndata: ") + "\n\n");
lastEventId += 1;
}
response.write(":\n");
}
response.on("close", function () {
emitter.removeListener("message", sendMessages);
response.end();
});
response.socket.setTimeout(0); // see http://contourline.wordpress.com/2011/03/30/preventing-server-timeout-in-node-js/
var estest = parsedURL.query.estest;
if (estest !== undefined) {
var i = estest.indexOf("\n\n");
var headers = {};
estest.slice(0, i).replace(/[^\n]*/g, function (line) {
var header = line.split(":");
if (header[0].trim() !== "") {
headers[header[0].trim()] = header.slice(1).join(":").trim();
}
});
response.writeHead(200, headers);
var body = estest.slice(i + 2);
body = body.replace(/<random\(\)>/g, function () {
return Math.random();
});
body = body.replace(/<lastEventId\((\d+)\)>/g, function (p, increment) {
return lastEventId + Number(increment);
});
body = body.replace(/<authorization>/g, function () {
return authorization;
});
body = body.split(/<delay\((\d+)\)>/);
i = -1;
var next = function () {
++i;
if (body[i] !== "") {
response.write(body[i]);
}
if (++i < body.length) {
setTimeout(next, Number(body[i]));
} else {
response.end();
}
};
next();
return;
}
response.writeHead(200, {
"Content-Type": "text/event-stream",
"Cache-Control": "no-cache",
"Access-Control-Allow-Origin": "*"
});
response.write(":" + Array(2049).join(" ") + "\n"); // 2kB padding for IE
response.write("retry: 1000\n");
response.write("heartbeatTimeout: " + heartbeatTimeout + "\n");//!
emitter.addListener("message", sendMessages);
emitter.setMaxListeners(0);
sendMessages();
}
function onRequest(request, response) {
var parsedURL = url.parse(request.url, true);
var query = parsedURL.query;
var pathname = parsedURL.pathname;
var time = "";
var data = "";
if (query.message) {
time = new Date();
data = "[" + time.toISOString() + "][IP: " + request.connection.remoteAddress + "] " + query.message;
response.writeHead(200, {
"Content-Type": "text/plain"
});
response.end(String(firstId + history.push(data)));
emitter.emit("message");
return;
}
if (pathname === "/events") {
eventStream(request, response);
} else {
var files = [
"/example.html",
"/nodechat.css",
"/eventsource.js",
"/nodechat.js",
"/tests.html",
"/qunit.css",
"/qunit.js",
"/tests.js",
"/stop.js"
];
if (files.indexOf(pathname) === -1) {
pathname = files[0];
}
fs.stat(__dirname + pathname, function (error, stats) {
if (error) {
response.writeHead(404);
response.end();
} else {
var mtime = Date.parse(request.headers["if-modified-since"]) || 0;
if (stats.mtime <= mtime) {
response.writeHead(304);
response.end();
} else {
var raw = fs.createReadStream(__dirname + pathname);
response.writeHead(200, {
"Content-Type": (pathname.indexOf(".js") !== -1 ? "text/javascript" : (pathname.indexOf(".css") !== -1 ? "text/css" : "text/html")),
"Last-Modified": stats.mtime.toUTCString()
});
raw.pipe(response);
}
}
});
}
}
http.createServer(onRequest).listen(PORT1);
http.createServer(onRequest).listen(PORT2);