E04. Receive SSE on the Client
cpp-httplib ships a dedicated sse::SSEClient class. It handles auto-reconnect, per-event-name dispatch, and Last-Event-ID tracking for you — so receiving SSE is painless.
Basic usage
#include <httplib.h> httplib::Client cli("http://localhost:8080"); httplib::sse::SSEClient sse(cli, "/events"); sse.on_message([](const httplib::sse::SSEMessage &msg) { std::cout << "data: " << msg.data << std::endl; }); sse.start(); // blocking
#include <httplib.h> httplib::Client cli("http://localhost:8080"); httplib::sse::SSEClient sse(cli, "/events"); sse.on_message([](const httplib::sse::SSEMessage &msg) { std::cout << "data: " << msg.data << std::endl; }); sse.start(); // blocking
Build an SSEClient with a Client and a path, register a callback with on_message(), and call start(). The event loop kicks in and automatically reconnects if the connection drops.
Dispatch by event name
When the server sends events with an event: field, register a handler per name via on_event().
sse.on_event("message", [](const auto &msg) { std::cout << "chat: " << msg.data << std::endl; }); sse.on_event("join", [](const auto &msg) { std::cout << msg.data << " joined" << std::endl; }); sse.on_event("leave", [](const auto &msg) { std::cout << msg.data << " left" << std::endl; });
sse.on_event("message", [](const auto &msg) { std::cout << "chat: " << msg.data << std::endl; }); sse.on_event("join", [](const auto &msg) { std::cout << msg.data << " joined" << std::endl; }); sse.on_event("leave", [](const auto &msg) { std::cout << msg.data << " left" << std::endl; });
on_message() is the generic fallback: it receives every event that has no handler registered through on_event(). With on_event("message", ...) registered as above, message events go there instead.
Connection lifecycle and errors
sse.on_open([] { std::cout << "connected" << std::endl; }); sse.on_error([](httplib::Error err) { std::cerr << "error: " << httplib::to_string(err) << std::endl; });
sse.on_open([] { std::cout << "connected" << std::endl; }); sse.on_error([](httplib::Error err) { std::cerr << "error: " << httplib::to_string(err) << std::endl; });
Hook into connection open and error events. Even when the error handler fires, SSEClient keeps trying to reconnect in the background. The exceptions are a 204, 403, or 404 response, after which it stops.
Run asynchronously
If you don't want to block the main thread, use start_async().
sse.start_async(); // main thread continues to do other things do_other_work(); // when you're done, stop it sse.stop();
sse.start_async(); // main thread continues to do other things do_other_work(); // when you're done, stop it sse.stop();
start_async() spawns a background thread to run the event loop. Use stop() to shut it down cleanly.
Configure reconnection
You can tune the reconnect interval and maximum retries.
sse.set_reconnect_interval(5000); // 5 seconds sse.set_max_reconnect_attempts(10); // up to 10 (0 = unlimited)
sse.set_reconnect_interval(5000); // 5 seconds sse.set_max_reconnect_attempts(10); // up to 10 (0 = unlimited)
If the server sends a retry: field, that takes precedence.
Automatic Last-Event-ID
SSEClient tracks the id of each received event internally and sends it back as Last-Event-ID on reconnect. As long as the server sends events with id:, this all works automatically.
std::cout << "last id: " << sse.last_event_id() << std::endl;
std::cout << "last id: " << sse.last_event_id() << std::endl;
Use last_event_id() to read the current value.
Note:
SSEClient::start()blocks, which is fine for a one-off command-line tool. For GUI apps or embedded in a server, thestart_async()+stop()pair is the usual pattern.
For the server side, see E01. Implement an SSE server.