mirror of
https://github.com/yhirose/cpp-httplib.git
synced 2026-10-13 10:24:47 +00:00
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:
@@ -4918,9 +4918,12 @@ inline bool SSEClient::parse_sse_line(const std::string &line, SSEMessage &msg,
|
||||
msg.data += value;
|
||||
has_data = true;
|
||||
} else if (field == "id") {
|
||||
// Empty id is valid (clears the last event ID)
|
||||
msg.id = value;
|
||||
has_id = true;
|
||||
// An id that cannot be sent back as Last-Event-ID is ignored. Empty id is
|
||||
// valid (clears the last event ID)
|
||||
if (detail::fields::is_field_value(value)) {
|
||||
msg.id = value;
|
||||
has_id = true;
|
||||
}
|
||||
} else if (field == "retry") {
|
||||
// Parse retry interval in milliseconds
|
||||
// Per the SSE spec, a value that is not all ASCII digits is ignored.
|
||||
|
||||
@@ -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");
|
||||
|
||||
Reference in New Issue
Block a user