Skip to content

Commit 51a92d6

Browse files
kzhdevCopilot
andcommitted
Refactor HTTP examples and tests to use updated SSE endpoint; normalize CRLF in SSE chunk parsing
Co-authored-by: Copilot <copilot@github.com>
1 parent af28905 commit 51a92d6

5 files changed

Lines changed: 30 additions & 9 deletions

File tree

CHANGELOG.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,12 @@
1-
# [v2.0.1] - 2026-04-27
1+
# [v2.0.1] - 2026-04-29
2+
3+
## Chaged
4+
- updated SSE endpoint in excamples and tests
25

36
## Fixed
47
- WebSocket `co_spawn` completion handler now guards `on_error_()` with a `run_` check, suppressing spurious error callbacks after shutdown.
58
- Fixed use-after-free in WebSocket tests where `[&]` lambda captures referenced destroyed stack variables when async callbacks fired via IOCP after the test function returned. Affected tests (`ConnectToEchoServer`, `InvalidHostnameError`, `MultipleErrorCallbacks`, `ReconnectAfterError`, `PlainWebsocket_UrlParsing`) now use `shared_ptr` captures to extend captured variable lifetimes.
9+
- normalize CRLF in SSE chunk parsing
610

711
## Tests
812
- Added 10 comprehensive `Reconnect_*` tests verifying correct behavior when reconnecting by creating a new `Websocket` instance during normal operation (service thread always running):

examples/http_awaitable_client.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1+
#include <slick/logger.hpp>
12
#include <slick/net/http.hpp>
23
#include <slick/net/logging.hpp>
34
#include <nlohmann/json.hpp>
4-
#include <slick/logger.hpp>
55
#include <boost/asio.hpp>
66

77
using namespace slick::net;

examples/http_stream_client.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ int main()
3939
// Create HTTP stream connection
4040
// This example uses a test SSE endpoint that sends time updates
4141
auto stream = std::make_shared<HttpStream>(
42-
"https://sse.dev/test",
42+
"https://stream.wikimedia.org/v2/stream/recentchange",
4343
[]() {
4444
LOG_INFO("Stream connected");
4545
},

src/http_stream.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -421,6 +421,20 @@ void HttpStream::parse_sse_chunk(const char* data, size_t size) {
421421
// Append new data to buffer
422422
sse_buffer_.append(data, size);
423423

424+
// Normalize CRLF and bare CR to LF so event/line splitting is uniform
425+
for (size_t i = 0; i < sse_buffer_.size(); ) {
426+
if (sse_buffer_[i] == '\r') {
427+
if (i + 1 < sse_buffer_.size() && sse_buffer_[i + 1] == '\n') {
428+
sse_buffer_.erase(i, 1); // remove \r, keep \n
429+
} else {
430+
sse_buffer_[i] = '\n'; // bare \r -> \n
431+
++i;
432+
}
433+
} else {
434+
++i;
435+
}
436+
}
437+
424438
// Process complete events (separated by double newline)
425439
size_t pos = 0;
426440
while ((pos = sse_buffer_.find("\n\n")) != std::string::npos) {

tests/http_tests.cpp

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -251,9 +251,12 @@ TEST_F(HttpTest, SyncDelete_WithBody) {
251251

252252
EXPECT_TRUE(response.is_ok()) << "Status: " << response.result_code << ", Response: " << response.result_text;
253253
EXPECT_EQ(response.result_code, 200);
254+
EXPECT_FALSE(response.result_text.empty());
254255

255-
EXPECT_TRUE(response.is_ok());
256-
EXPECT_EQ(response.result_code, 200);
256+
EXPECT_NO_THROW({
257+
auto json = nlohmann::json::parse(response.result_text);
258+
EXPECT_TRUE(json.contains("json") || json.contains("data"));
259+
});
257260
}
258261

259262
// ======================== Asynchronous GET Tests ========================
@@ -530,7 +533,7 @@ TEST_F(HttpTest, HttpStream_BasicConnection) {
530533
std::string last_error;
531534

532535
auto stream = std::make_shared<HttpStream>(
533-
"https://sse.dev/test",
536+
"https://stream.wikimedia.org/v2/stream/recentchange",
534537
[&]() {
535538
connected.store(true);
536539
},
@@ -573,7 +576,7 @@ TEST_F(HttpTest, HttpStream_CustomHeaders) {
573576

574577
std::vector<std::pair<std::string, std::string>> headers = {{"X-Custom-Header", "test"}};
575578
auto stream = std::make_shared<HttpStream>(
576-
"https://sse.dev/test",
579+
"https://stream.wikimedia.org/v2/stream/recentchange",
577580
[&]() { connected.store(true); },
578581
[&]() { disconnected.store(true); },
579582
[&](const char* data, size_t size) {
@@ -637,7 +640,7 @@ TEST_F(HttpTest, HttpStream_MultipleStreams) {
637640
// Create 3 concurrent streams
638641
for (int i = 0; i < 3; ++i) {
639642
auto stream = std::make_shared<HttpStream>(
640-
"https://sse.dev/test",
643+
"https://stream.wikimedia.org/v2/stream/recentchange",
641644
[&]() { connected_count++; },
642645
[&]() { disconnected_count++; },
643646
[&](const char*, size_t) { data_count++; },
@@ -671,7 +674,7 @@ TEST_F(HttpTest, HttpStream_StatusCheck) {
671674
std::atomic<bool> disconnected{false};
672675

673676
auto stream = std::make_shared<HttpStream>(
674-
"https://sse.dev/test",
677+
"https://stream.wikimedia.org/v2/stream/recentchange",
675678
[&]() { connected.store(true); },
676679
[&]() { disconnected.store(true); },
677680
[](const char*, size_t) {},

0 commit comments

Comments
 (0)