mirror of
https://github.com/yhirose/cpp-httplib.git
synced 2026-10-01 05:02:29 +07:00
Ignore an SSE retry field that is not all digits (#2591)
parse_sse_line checked only the error code of from_chars, which accepts a leading '-' and stops at the first non-digit, so retry: -1 made the client reconnect without waiting and retry: 10s set 10 ms. The SSE spec ignores a retry value that is not all ASCII digits.
This commit is contained in:
@@ -4914,7 +4914,8 @@ inline bool SSEClient::parse_sse_line(const std::string &line, SSEMessage &msg,
|
||||
msg.id = value;
|
||||
} else if (field == "retry") {
|
||||
// Parse retry interval in milliseconds
|
||||
{
|
||||
// Per the SSE spec, a value that is not all ASCII digits is ignored.
|
||||
if (detail::is_numeric(value)) {
|
||||
int v = 0;
|
||||
auto res =
|
||||
detail::from_chars(value.data(), value.data() + value.size(), v);
|
||||
|
||||
@@ -22647,6 +22647,64 @@ TEST_F(SSEIntegrationTest, AutoReconnectAfterDisconnect) {
|
||||
EXPECT_GE(message_count.load(), 2);
|
||||
}
|
||||
|
||||
// Test: A retry field that is not all ASCII digits is ignored
|
||||
TEST_F(SSEIntegrationTest, NonDigitRetryFieldIgnored) {
|
||||
std::atomic<int> connection_count{0};
|
||||
|
||||
server_->Get("/bad-retry",
|
||||
[&connection_count](const Request &, Response &res) {
|
||||
connection_count.fetch_add(1);
|
||||
res.set_chunked_content_provider(
|
||||
"text/event-stream", [](size_t offset, DataSink &sink) {
|
||||
if (offset == 0) {
|
||||
std::string event = "retry: -1\ndata: hello\n\n";
|
||||
sink.write(event.data(), event.size());
|
||||
}
|
||||
return false;
|
||||
});
|
||||
});
|
||||
|
||||
Client client("localhost", get_port());
|
||||
sse::SSEClient sse(client, "/bad-retry");
|
||||
|
||||
sse.set_reconnect_interval(10000);
|
||||
sse.start_async();
|
||||
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(500));
|
||||
sse.stop();
|
||||
|
||||
EXPECT_EQ(connection_count.load(), 1);
|
||||
}
|
||||
|
||||
// Test: A retry field of all ASCII digits sets the reconnection time
|
||||
TEST_F(SSEIntegrationTest, DigitRetryFieldApplied) {
|
||||
std::atomic<int> connection_count{0};
|
||||
|
||||
server_->Get("/zero-retry",
|
||||
[&connection_count](const Request &, Response &res) {
|
||||
connection_count.fetch_add(1);
|
||||
res.set_chunked_content_provider(
|
||||
"text/event-stream", [](size_t offset, DataSink &sink) {
|
||||
if (offset == 0) {
|
||||
std::string event = "retry: 0\ndata: hello\n\n";
|
||||
sink.write(event.data(), event.size());
|
||||
}
|
||||
return false;
|
||||
});
|
||||
});
|
||||
|
||||
Client client("localhost", get_port());
|
||||
sse::SSEClient sse(client, "/zero-retry");
|
||||
|
||||
sse.set_reconnect_interval(10000);
|
||||
sse.start_async();
|
||||
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(500));
|
||||
sse.stop();
|
||||
|
||||
EXPECT_GE(connection_count.load(), 2);
|
||||
}
|
||||
|
||||
// Test: Last-Event-ID sent on reconnect
|
||||
TEST_F(SSEIntegrationTest, LastEventIdSentOnReconnect) {
|
||||
std::atomic<int> connection_count{0};
|
||||
|
||||
Reference in New Issue
Block a user