Nav apraksta

yhirose 1c91d54b7c Read no body from an unframed request in builds without TLS too 10 stundas atpakaļ
.github 344aceb446 Run the pong timeout tests in the main test suite 4 dienas atpakaļ
benchmark 6494edd8c0 Add static-file, large-body and TLS workloads to the A/B benchmark 2 mēneši atpakaļ
cmake 0d7d637466 Fix zstd detection in installed httplibConfig.cmake (#2453) 5 mēneši atpakaļ
docker f6aee694e2 Log the response length for static files in the docker server 1 nedēļu atpakaļ
docs-src fc37d3eae1 Add Server::set_compress() to turn off handler response compression 19 stundas atpakaļ
docs-util 9bfd2ddf1c Fix README and docs pages that no longer match the code 4 dienas atpakaļ
example f2b338ae2e Drop the empty Accept entry from the example's invalid list 1 mēnesi atpakaļ
scripts deb520e26b Update version files with sed -i.bak, which GNU sed accepts too 1 mēnesi atpakaļ
test 1c91d54b7c Read no body from an unframed request in builds without TLS too 10 stundas atpakaļ
.clang-format 260422b7d7 Format code 6 gadi atpakaļ
.gitattributes 177d8420a1 Added .gitattributes file to prevent git from changing line endings (#1872) 2 gadi atpakaļ
.gitignore 644cda7032 Update .gitignore 1 mēnesi atpakaļ
.pre-commit-config.yaml f83d06538b Track Homebrew's clang-format version instead of a fixed pin 1 mēnesi atpakaļ
CMakeLists.txt 5a202d3d5f Added a feature test to auto enable/disable CPPHTTPLIB_USE_NON_BLOCKI… (#2578) 3 nedēļas atpakaļ
Dockerfile f4cc542d4b Fix Dockerfile problem with CMD 1 gadu atpakaļ
LICENSE ca7b942196 Changed license to MIT 8 gadi atpakaļ
README-sse.md f17d314979 Send the client's credentials and proxy target on a stream request 3 dienas atpakaļ
README-stream.md f17d314979 Send the client's credentials and proxy target on a stream request 3 dienas atpakaļ
README-websocket.md 9bfd2ddf1c Fix README and docs pages that no longer match the code 4 dienas atpakaļ
README.md b83b385ed4 Match trusted proxies as IP addresses 18 stundas atpakaļ
docker-compose.yml ba638ff38e Update Docker support 2 gadi atpakaļ
generate_module.py 1942e0ef01 Add C++ modules support (#2291) 8 mēneši atpakaļ
httplib.h 1c91d54b7c Read no body from an unframed request in builds without TLS too 10 stundas atpakaļ
justfile 29ceccecd6 Add A/B throughput benchmark for comparing two refs 2 mēneši atpakaļ
meson.build d3ff68d28d Always use meson option non_blocking_getaddrinfo (#2537) 2 mēneši atpakaļ
meson_options.txt c2002f6e06 Make loading system certificates from the Keychain on macOS an opt-out feature (#2377) 8 mēneši atpakaļ
split.py 1942e0ef01 Add C++ modules support (#2291) 8 mēneši atpakaļ

README-sse.md

SSEClient - Server-Sent Events Client

A simple, EventSource-like SSE client for C++11.

Features

  • Auto-reconnect: Automatically reconnects on connection loss or an error status (except 204, 403 and 404)
  • 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 events whose type has no on_event() 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"}});

The client reconnects when it cannot connect or the stream ends. A status other than 200 calls on_error(Error::Connection); a 204, 403 or 404 then stops the client, and any other status, 401 included, reconnects, so an on_error handler can refresh credentials with set_headers(). set_max_reconnect_attempts() counts reconnect attempts in a row: the count starts over after each successful connection. Each attempt that fails to connect is also reported to the Client's error logger.

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 client's set_payload_max_length() does not apply to the stream as a whole, which has no end.

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();

The Client's set_basic_auth() and set_bearer_token_auth() apply too; an Authorization header passed like this takes precedence.

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 WHATWG HTML Living Standard:

event: custom-type
id: 123
data: {"message": "hello"}

data: simple message

: this is a comment (ignored)