mirror of
https://github.com/yhirose/cpp-httplib.git
synced 2026-10-20 11:29:38 +00:00
Bring the READMEs and the docs pages (en and ja) in line with the current header: - Fix the client sample that does not compile, the Transfer-Encoding statement for default headers, the verifier callback comment, the thread pool spawn rule, the sanitize_filename description, and the inverted Accept-Encoding sentence. - Describe recent behaviour: TLS errors behind Read/Write failures, Host validation, Connection: close for a body without length, content_reader rules, refused CONNECT, WebSocketClient proxies, CPPHTTPLIB_INTERIM_RESPONSE_MAX_COUNT, the SSE event size limit, and the payload limit of the Stream API. - Complete the API references of WebSocket, WebSocketClient and the stream:: helpers, and the SSE reconnect rules. - Fix cookbook pages: keychain loading on every backend, received Close status, a multipart sample that trusted the client's file name, an echo sample that sent binary as text, SNI, pre-request handler scope, stop() with WebSocket handlers, and the thread pool notes. - Restore the mutex in the LLM app's Chapter 5 code.
104 lines
3.5 KiB
Markdown
104 lines
3.5 KiB
Markdown
---
|
|
title: "E04. Receive SSE on the Client"
|
|
order: 51
|
|
status: "draft"
|
|
---
|
|
|
|
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
|
|
|
|
```cpp
|
|
#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()`.
|
|
|
|
```cpp
|
|
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
|
|
|
|
```cpp
|
|
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. It stops after a 204, 403, or 404 response, or once the attempts set with `set_max_reconnect_attempts()` run out.
|
|
|
|
It also stops when an event, or a line still waiting for its end, grows past `CPPHTTPLIB_SSE_MAX_EVENT_LENGTH` (16MB by default, 0 for no limit). The error handler then gets `Error::ExceedMaxPayloadSize`. The client's `set_payload_max_length()` doesn't apply to the stream as a whole, since an event stream has no end.
|
|
|
|
## Run asynchronously
|
|
|
|
If you don't want to block the main thread, use `start_async()`.
|
|
|
|
```cpp
|
|
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.
|
|
|
|
```cpp
|
|
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.
|
|
|
|
An empty `id:` clears the stored id. An `id:` that can't be sent as a header value (one with NUL or other control characters, or with leading or trailing whitespace) is ignored, and the previous id stays.
|
|
|
|
```cpp
|
|
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, the `start_async()` + `stop()` pair is the usual pattern.
|
|
|
|
> For the server side, see [E01. Implement an SSE server](../e01-sse-server).
|