Ignore an SSE id that cannot be sent as Last-Event-ID

SSEClient stored any id it received, but the client rejects a request
whose header value is invalid. An id with a NUL, a control character or
surrounding whitespace therefore made every reconnect fail with
Error::InvalidHeaders before reaching the server, and the id could
never be replaced.

Accept an id only if it is a valid header value, so that the previous
id stays in effect. The SSE spec asks for this for NUL only; the rest
follows from what this client can send.
This commit is contained in:
yhirose committed 2026-10-11 23:05:38 -04:00
1 parent fee592c2c2
commit 5189edc52e
2 files changed
+28 -3

No files matched your search

+22
View File
@@ -22869,6 +22869,28 @@ TEST_F(SSEParsingTest, EmptyEventIdClearsLastEventId) {
EXPECT_EQ(msgs[2].data, "not sent");
}
TEST_F(SSEParsingTest, UnsendableEventIdKeepsLastEventId) {
// The first connection sets an id and then sends ids that cannot be carried
// in a header; the second echoes back the Last-Event-ID it was reconnected
// with
std::atomic<int> connection_count{0};
server_->Get("/id-unsendable", [&](const Request &req, Response &res) {
if (connection_count++ == 0) {
res.set_content(std::string("id: 42\n\nid: a") + '\0' +
"b\n\nid: \x01\n\nid: 7\n\nid: 7 \n\n",
"text/event-stream");
} else {
res.set_content("data: " + req.get_header_value("Last-Event-ID") +
"\n\nevent: end\ndata: end\n\n",
"text/event-stream");
}
});
auto msgs = collect("/id-unsendable");
ASSERT_EQ(msgs.size(), 1u);
EXPECT_EQ(msgs[0].data, "42");
}
TEST_F(SSEParsingTest, CompleteEventParsing) {
auto msgs = parse("event: notification\nid: evt-42\n"
"data: {\"type\":\"alert\"}\nretry: 1000\n\n");