From 772646d940424f6a200341c2e38f6be380c90727 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Rapha=C3=ABl=20Jakse?= Date: Sat, 4 Apr 2020 16:17:23 +0200 Subject: [PATCH] Support server-sent events --- trivabble-server.js | 46 +++++++++++++++++++++++++++++---------------- trivabble.js | 16 ++++++++++++++++ 2 files changed, 46 insertions(+), 16 deletions(-) diff --git a/trivabble-server.js b/trivabble-server.js index 0e77c76..933350c 100644 --- a/trivabble-server.js +++ b/trivabble-server.js @@ -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\/(?[\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]); }); } diff --git a/trivabble.js b/trivabble.js index 2a3f3c3..07748d8 100644 --- a/trivabble.js +++ b/trivabble.js @@ -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); -- 2.30.2