mirror of
https://github.com/yhirose/cpp-httplib.git
synced 2026-10-19 11:19:36 +00:00
A retry or redirect after an early answer to Expect: 100-continue now opens a new connection, interim responses are also skipped while waiting for 100 Continue, and a URL Client cannot use, such as one with userinfo, gives an invalid client. Only a 407 is passed on from a refused CONNECT, WebSocket::close() sends only a valid payload, and the SSE client stops on an oversized event rather than reconnect to it. Media type parameter names and user extension mappings are matched without case, file content is read in larger chunks from a buffer of its own, the streaming decompression limit reports ExceedMaxPayloadSize, and the tests use the existing single-response server helpers. Comments and the README are brought in line.
4.6 KiB
4.6 KiB
SSEClient - Server-Sent Events Client
A simple, EventSource-like SSE client for C++11.
Features
- Auto-reconnect: Automatically reconnects on connection loss
- Last-Event-ID: Sends last received ID on reconnect for resumption
- retry field: Respects server's reconnect interval
- Event types: Supports custom event types via
on_event() - Async support: Run in background thread with
start_async() - C++11 compatible: No C++14/17/20 features required
Quick Start
httplib::Client cli("http://localhost:8080");
httplib::sse::SSEClient sse(cli, "/events");
sse.on_message([](const httplib::sse::SSEMessage &msg) {
std::cout << "Event: " << msg.event << std::endl;
std::cout << "Data: " << msg.data << std::endl;
});
sse.start(); // Blocking, with auto-reconnect
API Reference
SSEMessage
struct SSEMessage {
std::string event; // Event type (default: "message")
std::string data; // Event payload
std::string id; // Event ID
};
SSEClient
Constructor
// Basic
SSEClient(Client &client, const std::string &path);
// With custom headers
SSEClient(Client &client, const std::string &path, const Headers &headers);
Event Handlers
// Called for all events (or events without a specific handler)
sse.on_message([](const SSEMessage &msg) { });
// Called for specific event types
sse.on_event("update", [](const SSEMessage &msg) { });
sse.on_event("delete", [](const SSEMessage &msg) { });
// Called when connection is established
sse.on_open([]() { });
// Called on connection errors
sse.on_error([](httplib::Error err) { });
Configuration
// Set reconnect interval (default: 3000ms, minimum: 100ms)
sse.set_reconnect_interval(5000);
// Set max reconnect attempts (default: 0 = unlimited)
sse.set_max_reconnect_attempts(10);
// Update headers at any time (thread-safe)
sse.set_headers({{"Authorization", "Bearer new_token"}});
An event, or a line still waiting for its end, longer than CPPHTTPLIB_SSE_MAX_EVENT_LENGTH (16MB by default, 0 for no limit) ends the connection with Error::ExceedMaxPayloadSize, and the client stops rather than reconnect to the same event. The whole stream also counts against the client's set_payload_max_length() (100MB by default), so set it to 0 for a long-lived stream.
Control
// Blocking start with auto-reconnect
sse.start();
// Non-blocking start (runs in background thread)
sse.start_async();
// Stop the client (thread-safe)
sse.stop();
State
bool connected = sse.is_connected();
const std::string &id = sse.last_event_id();
Examples
Basic Usage
httplib::Client cli("http://localhost:8080");
httplib::sse::SSEClient sse(cli, "/events");
sse.on_message([](const httplib::sse::SSEMessage &msg) {
std::cout << msg.data << std::endl;
});
sse.start();
With Custom Event Types
httplib::sse::SSEClient sse(cli, "/events");
sse.on_event("notification", [](const httplib::sse::SSEMessage &msg) {
std::cout << "Notification: " << msg.data << std::endl;
});
sse.on_event("update", [](const httplib::sse::SSEMessage &msg) {
std::cout << "Update: " << msg.data << std::endl;
});
sse.start();
Async with Stop
httplib::sse::SSEClient sse(cli, "/events");
sse.on_message([](const httplib::sse::SSEMessage &msg) {
std::cout << msg.data << std::endl;
});
sse.start_async(); // Returns immediately
// ... do other work ...
sse.stop(); // Stop when done
With Custom Headers (e.g., Authentication)
httplib::Headers headers = {
{"Authorization", "Bearer token123"}
};
httplib::sse::SSEClient sse(cli, "/events", headers);
sse.start();
Refreshing Auth Token on Reconnect
httplib::sse::SSEClient sse(cli, "/events",
{{"Authorization", "Bearer " + get_token()}});
// Preemptively refresh token on each successful connection
sse.on_open([&sse]() {
sse.set_headers({{"Authorization", "Bearer " + get_token()}});
});
// Or reactively refresh on auth failure (401 triggers reconnect)
sse.on_error([&sse](httplib::Error) {
sse.set_headers({{"Authorization", "Bearer " + refresh_token()}});
});
sse.start();
Error Handling
sse.on_error([](httplib::Error err) {
std::cerr << "Error: " << httplib::to_string(err) << std::endl;
});
sse.set_reconnect_interval(1000);
sse.set_max_reconnect_attempts(5);
sse.start();
SSE Protocol
The client parses SSE format according to the W3C specification:
event: custom-type
id: 123
data: {"message": "hello"}
data: simple message
: this is a comment (ignored)