Support server-sent events

This commit is contained in:
Raphaël Jakse 2020-04-04 16:17:23 +02:00
parent 915c99da38
commit 772646d940
2 changed files with 46 additions and 16 deletions

View File

@ -112,8 +112,12 @@ function Game() {
this.pendingEvents = [];
}
function writeResponse(response, data, terminate) {
response[terminate ? "end" : "write"](data.length + data);
function writeResponse(responseAndIsES, data, terminate) {
responseAndIsES[0][terminate ? "end" : "write"](
responseAndIsES[1]
? "data:" + data + "\n\n"
: data.length + data
);
}
function newBoard() {
@ -212,13 +216,13 @@ Game.prototype.playerJoined = function (playerName) {
);
};
Game.prototype.addListeningPlayer = function (playerName, response) {
Game.prototype.addListeningPlayer = function (playerName, responseAndIsES) {
var that = this;
that.listeningPlayers.push(response);
that.listeningPlayers.push(responseAndIsES);
response.on("close", function () {
var index = that.listeningPlayers.indexOf(response);
responseAndIsES[0].on("close", function () {
var index = that.listeningPlayers.indexOf(responseAndIsES);
if (index !== -1) {
that.listeningPlayers[index] = that.listeningPlayers[that.listeningPlayers.length - 1];
that.listeningPlayers.pop();
@ -616,18 +620,16 @@ function handleCommand(cmd, gameNumber, playerName, response) {
}
}
function handleCommands(cmds, response) {
function handleCommands(cmds, responseAndIsES) {
if (!cmds.cmds || !cmds.cmds.length) {
var game = games[cmds.gameNumber];
if (!game) {
writeResponse(response, '{"error":1,"reason":"Missing or bad game number"}', true);
writeResponse(responseAndIsES, "{\"error\":1,\"reason\":\"Missing or bad game number\"}", true);
return;
}
writeResponse(response,
JSON.stringify(
{
writeResponse(responseAndIsES,
"playerName": cmds.playerName,
"gameNumber": cmds.gameNumber,
"letterValues": game.letterValues,
@ -639,10 +641,12 @@ function handleCommands(cmds, response) {
)
);
game.addListeningPlayer(cmds.playerName, response);
game.addListeningPlayer(cmds.playerName, responseAndIsES);
return;
}
var response = responseAndIsES[0];
response.write("[");
for (var i = 0; i < cmds.cmds.length; i++) {
@ -674,11 +678,21 @@ function handleRequest(request, response) {
});
request.on("end", function () {
response.setHeader("Content-Type", "text/plain");
response.setHeader("Transfer-Encoding", "chunked");
var isEventSource = false;
var eventSourceMatch = request.url.match(/\/:[^/]+\/sse\/(?<data>[\s\S]+)$/u);
if (eventSourceMatch) {
response.setHeader("Content-Type", "text/event-stream");
post = decodeURIComponent(eventSourceMatch.groups.data);
isEventSource = true;
} else {
response.setHeader("Content-Type", "text/plain");
response.setHeader("Transfer-Encoding", "chunked");
}
dateNow = Date.now();
console.log("RECEIVED", post);
handleCommands(post && JSON.parse(post), response);
console.log("RECEIVED", request.url, post, isEventSource);
handleCommands(post && JSON.parse(post), [response, isEventSource]);
});
}

View File

@ -705,6 +705,22 @@
blockMove++;
}
if (thisRequestIsPolling && window.EventSource) {
var es = new EventSource('/:trivabble/sse/' + JSON.stringify(data));
es.onopen = function () {
pollingReady = true;
};
es.onmessage = function (e) {
pollingReady = true;
handleReceivedData(JSON.parse(e.data));
};
es.onerror = retryPolling;
return;
}
var xhr = new XMLHttpRequest();
xhr.open("POST", "/:trivabble", true);