Reputation: 480
In this example a client connects to a Node Express server by creating a new EventSource. The server sends an SSE event upon initial connection, and then on a 30 second interval after that. The problem is that the client's onmessage handler is not triggered by the initial SSE event sent upon connection, but it is triggered by all subsequent events. If I stop the server immediately after a connection is made, this actually will trigger an event in the client which shows that the data was in fact received without being handled a moment earlier (or the initial res.write is only triggered by the server being shutdown):
Server:
let data = {mydata: 123};
function eventsHandler(req, res, next) {
const headers = {
"Content-Type": "text/event-stream",
Connection: "keep-alive",
"Cache-Control": "no-cache",
};
res.writeHead(200, headers);
// After client opens connection we send data string, but client doesn't handle this correctly
// Event is only triggered on client if I stop the server after sending this message
res.write(`data: ${JSON.stringify(data)}\n\n`);
console.log("sent SSE");
const clientId = Date.now();
console.log(clientId, " connected");
const newClient = {
id: clientId,
res,
};
clients.push(newClient);
req.on("close", () => {
console.log(`${clientId} Connection closed`);
clients = clients.filter((c) => c.id !== clientId);
});
}
// these events are received and handled correctly on client
function sendEventsToAll(datadict) {
clients.forEach((c) => c.res.write(`data: ${JSON.stringify(datadict)}\n\n`));
}
// Route to open SSE connection
app.get("/events", eventsHandler);
// Loop to send SSE every 30 seconds - these are all received and handled correctly
async function wait() {
sendEventsToAll(data);
setTimeout(wait, 30000);
}
wait();
Browser:
const events = new EventSource(url)
// This handles every SSE event except the one that is written immediately upon connection
// If I stop the server after connection, this will trigger and reveal the data was received but not handled
events.onmessage = event => {
const newData = JSON.parse(event.data)
console.log("newData", newData)
}
Edit: I should also add I'm using nginx for a reverse proxy - could this be buffering the first res.write instead of sending it immediately for some reason?
Upvotes: 4
Views: 628
Reputation: 480
This was caused by proxy_buffering in nginx which is "on" by default.
Turning this off in the nginx config resolved the issue:
server {
# server config here...
location / {
# proxy config here...
proxy_buffering off; # resolves issue
}
}
Upvotes: 2