mirror of
https://github.com/yhirose/cpp-httplib.git
synced 2026-04-12 03:38:30 +00:00
Add links to other topics in Cookbook documents
This commit is contained in:
@@ -57,4 +57,4 @@ Return `false` from the callback to abort the download. In the example above, if
|
||||
>
|
||||
> The `ResponseHandler` is called after headers arrive but before the body. Return `false` to skip the download entirely.
|
||||
|
||||
> To show download progress, see C11. Use the progress callback.
|
||||
> To show download progress, see [C11. Use the progress callback](c11-progress-callback).
|
||||
|
||||
@@ -31,6 +31,6 @@ if (res && res->status == 200) {
|
||||
|
||||
`res->body` is a `std::string`, so you can pass it straight to your JSON library.
|
||||
|
||||
> **Note:** Servers sometimes return HTML on errors. Check the status code before parsing to be safe. Some APIs also require an `Accept: application/json` header. If you're calling a JSON API repeatedly, C03. Set default headers can save you some boilerplate.
|
||||
> **Note:** Servers sometimes return HTML on errors. Check the status code before parsing to be safe. Some APIs also require an `Accept: application/json` header. If you're calling a JSON API repeatedly, [C03. Set default headers](c03-default-headers) can save you some boilerplate.
|
||||
|
||||
> For how to receive and return JSON on the server side, see S02. Receive JSON requests and return JSON responses.
|
||||
> For how to receive and return JSON on the server side, see [S02. Receive JSON requests and return JSON responses](s02-json-api).
|
||||
|
||||
@@ -52,4 +52,4 @@ auto res = cli.Get("/users", headers);
|
||||
|
||||
Per-request headers are **added** on top of the defaults. Both are sent to the server.
|
||||
|
||||
> For details on Bearer token auth, see C06. Call an API with a Bearer Token.
|
||||
> For details on Bearer token auth, see [C06. Call an API with a Bearer token](c06-bearer-token).
|
||||
|
||||
@@ -35,4 +35,4 @@ Many sites redirect HTTP traffic to HTTPS. With `set_follow_location(true)` on,
|
||||
|
||||
> **Warning:** To follow redirects to HTTPS, you need to build cpp-httplib with OpenSSL (or another TLS backend). Without TLS support, redirects to HTTPS will fail.
|
||||
|
||||
> **Note:** Following redirects adds to the total request time. See C12. Set Timeouts for timeout configuration.
|
||||
> **Note:** Following redirects adds to the total request time. See [C12. Set timeouts](c12-timeouts) for timeout configuration.
|
||||
|
||||
@@ -43,4 +43,4 @@ For the more secure Digest authentication scheme, use `set_digest_auth()`. This
|
||||
cli.set_digest_auth("alice", "s3cret");
|
||||
```
|
||||
|
||||
> To call an API with a Bearer token, see C06. Call an API with a Bearer Token.
|
||||
> To call an API with a Bearer token, see [C06. Call an API with a Bearer token](c06-bearer-token).
|
||||
|
||||
@@ -47,4 +47,4 @@ if (res && res->status == 401) {
|
||||
|
||||
> **Warning:** A Bearer token is itself a credential. Always send it over HTTPS, and never hard-code it into source or config files.
|
||||
|
||||
> To set multiple headers at once, see C03. Set Default Headers.
|
||||
> To set multiple headers at once, see [C03. Set default headers](c03-default-headers).
|
||||
|
||||
@@ -49,4 +49,4 @@ The arguments to `make_file_provider()` are `(form name, file path, file name, c
|
||||
|
||||
> **Note:** You can mix `UploadFormDataItems` and `FormDataProviderItems` in the same request. A clean split is: text fields in `UploadFormDataItems`, files in `FormDataProviderItems`.
|
||||
|
||||
> To show upload progress, see C11. Use the progress callback.
|
||||
> To show upload progress, see [C11. Use the progress callback](c11-progress-callback).
|
||||
|
||||
@@ -31,4 +31,4 @@ If the file can't be opened, `make_file_body()` returns `size` as `0` and `provi
|
||||
|
||||
> **Warning:** `make_file_body()` needs to fix the Content-Length up front, so it reads the file size ahead of time. If the file size might change mid-upload, this API isn't the right fit.
|
||||
|
||||
> To send the file as multipart form data instead, see C07. Upload a File as Multipart Form Data.
|
||||
> To send the file as multipart form data instead, see [C07. Upload a file as multipart form data](c07-multipart-upload).
|
||||
|
||||
@@ -44,4 +44,4 @@ With a known size, the request carries a Content-Length header — so the server
|
||||
|
||||
> **Detail:** `sink.write()` returns a `bool` indicating whether the write succeeded. If it returns `false`, the connection is gone — return `false` from the lambda to stop.
|
||||
|
||||
> If you're just sending a file, `make_file_body()` is easier. See C08. POST a File as Raw Binary.
|
||||
> If you're just sending a file, `make_file_body()` is easier. See [C08. POST a file as raw binary](c08-post-file-body).
|
||||
|
||||
@@ -48,5 +48,5 @@ Accumulate into a buffer, then pull out and parse one line each time you see a n
|
||||
|
||||
> **Warning:** When you pass a `ContentReceiver`, `res->body` stays **empty**. Store or process the body inside the callback yourself.
|
||||
|
||||
> To track download progress, combine this with C11. Use the Progress Callback.
|
||||
> For Server-Sent Events (SSE), see E04. Receive SSE on the Client.
|
||||
> To track download progress, combine this with [C11. Use the progress callback](c11-progress-callback).
|
||||
> For Server-Sent Events (SSE), see [E04. Receive SSE on the client](e04-sse-client).
|
||||
|
||||
@@ -56,4 +56,4 @@ auto res = cli.Get("/large-file",
|
||||
|
||||
> **Note:** `ContentReceiver` and the progress callback can be used together. When you want to stream to a file and show progress at the same time, pass both.
|
||||
|
||||
> For a concrete example of saving to a file, see C01. Get the Response Body / Save to a File.
|
||||
> For a concrete example of saving to a file, see [C01. Get the response body / save to a file](c01-get-response-body).
|
||||
|
||||
@@ -47,4 +47,4 @@ cli.set_connection_timeout(3s);
|
||||
cli.set_read_timeout(10s);
|
||||
```
|
||||
|
||||
> **Warning:** The read timeout covers a single receive call — not the whole request. If data keeps trickling in during a large download, the request can take half an hour without ever hitting the timeout. To cap the total request time, use C13. Set an Overall Timeout.
|
||||
> **Warning:** The read timeout covers a single receive call — not the whole request. If data keeps trickling in during a large download, the request can take half an hour without ever hitting the timeout. To cap the total request time, use [C13. Set an overall timeout](c13-max-timeout).
|
||||
|
||||
@@ -4,7 +4,7 @@ order: 13
|
||||
status: "draft"
|
||||
---
|
||||
|
||||
The three timeouts from C12. Set Timeouts all apply to a single `send` or `recv` call. To cap the total time a request can take, use `set_max_timeout()`.
|
||||
The three timeouts from [C12. Set timeouts](c12-timeouts) all apply to a single `send` or `recv` call. To cap the total time a request can take, use `set_max_timeout()`.
|
||||
|
||||
## Basic usage
|
||||
|
||||
|
||||
@@ -38,7 +38,7 @@ cli.set_proxy_digest_auth("user", "password");
|
||||
|
||||
## Combine with end-server authentication
|
||||
|
||||
Proxy authentication is separate from authenticating to the end server (C05, C06). When both are needed, set both.
|
||||
Proxy authentication is separate from authenticating to the end server ([C05. Use Basic authentication](c05-basic-auth), [C06. Call an API with a Bearer token](c06-bearer-token)). When both are needed, set both.
|
||||
|
||||
```cpp
|
||||
cli.set_proxy("proxy.internal", 8080);
|
||||
|
||||
@@ -60,4 +60,4 @@ std::cout << res->body << std::endl;
|
||||
|
||||
Keep them separated in your head: network-layer errors go through `res.error()`, HTTP-level errors through `res->status`.
|
||||
|
||||
> To dig deeper into SSL-related errors, see C18. Handle SSL Errors.
|
||||
> To dig deeper into SSL-related errors, see [C18. Handle SSL errors](c18-ssl-errors).
|
||||
|
||||
@@ -50,4 +50,4 @@ if (res.ssl_backend_error() != 0) {
|
||||
|
||||
> **Note:** `ssl_backend_error()` was previously called `ssl_openssl_error()`. The old name is deprecated — use `ssl_backend_error()` now.
|
||||
|
||||
> To change certificate verification settings, see T02. Control SSL Certificate Verification.
|
||||
> To change certificate verification settings, see [T02. Control SSL certificate verification](t02-cert-verification).
|
||||
|
||||
@@ -56,7 +56,7 @@ svr.Get("/time", [](const httplib::Request &req, httplib::Response &res) {
|
||||
});
|
||||
```
|
||||
|
||||
When the client disconnects, call `sink.done()` to stop. Details in S16. Detect When the Client Has Disconnected.
|
||||
When the client disconnects, call `sink.done()` to stop. Details in [S16. Detect client disconnection](s16-disconnect).
|
||||
|
||||
## Heartbeats via comment lines
|
||||
|
||||
@@ -80,8 +80,8 @@ svr.new_task_queue = [] {
|
||||
};
|
||||
```
|
||||
|
||||
See S21. Configure the Thread Pool.
|
||||
See [S21. Configure the thread pool](s21-thread-pool).
|
||||
|
||||
> **Note:** When `data:` contains newlines, split it into multiple `data:` lines — one per line. This is how the SSE spec requires multiline data to be transmitted.
|
||||
|
||||
> For event names, see E02. Use Named Events in SSE. For the client side, see E04. Receive SSE on the Client.
|
||||
> For event names, see [E02. Use named events in SSE](e02-sse-event-names). For the client side, see [E04. Receive SSE on the client](e04-sse-client).
|
||||
|
||||
@@ -52,7 +52,7 @@ auto send_event = [](httplib::DataSink &sink,
|
||||
send_event(sink, "message", "Hello!", "42");
|
||||
```
|
||||
|
||||
The ID format is up to you. Monotonic counters or UUIDs both work — just pick something unique and orderable on the server side. See E03. Handle SSE Reconnection for details.
|
||||
The ID format is up to you. Monotonic counters or UUIDs both work — just pick something unique and orderable on the server side. See [E03. Handle SSE reconnection](e03-sse-reconnect) for details.
|
||||
|
||||
## JSON payloads in data
|
||||
|
||||
|
||||
@@ -96,4 +96,4 @@ 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.
|
||||
> For the server side, see [E01. Implement an SSE server](e01-sse-server).
|
||||
|
||||
@@ -61,6 +61,6 @@ svr.Get("/me", [](const httplib::Request &req, httplib::Response &res) {
|
||||
|
||||
To add a response header, use `res.set_header("Name", "Value")`.
|
||||
|
||||
> **Note:** `listen()` is a blocking call. To run it on a different thread, wrap it in `std::thread`. If you need non-blocking startup, see S18. Control Startup Order with `listen_after_bind`.
|
||||
> **Note:** `listen()` is a blocking call. To run it on a different thread, wrap it in `std::thread`. If you need non-blocking startup, see [S18. Control startup order with `listen_after_bind`](s18-listen-after-bind).
|
||||
|
||||
> To use path parameters like `/users/:id`, see S03. Use Path Parameters.
|
||||
> To use path parameters like `/users/:id`, see [S03. Use path parameters](s03-path-params).
|
||||
|
||||
@@ -69,6 +69,6 @@ svr.Get("/api/health", [&](const auto &req, auto &res) {
|
||||
});
|
||||
```
|
||||
|
||||
> **Note:** A large JSON body ends up entirely in `req.body`, which means it all sits in memory. For huge payloads, consider streaming reception — see S07. Receive Multipart Data as a Stream.
|
||||
> **Note:** A large JSON body ends up entirely in `req.body`, which means it all sits in memory. For huge payloads, consider streaming reception — see [S07. Receive multipart data as a stream](s07-multipart-reader).
|
||||
|
||||
> For the client side, see C02. Send and Receive JSON.
|
||||
> For the client side, see [C02. Send and receive JSON](c02-json).
|
||||
|
||||
@@ -52,4 +52,4 @@ svr.set_file_extension_and_mimetype_mapping("wasm", "application/wasm");
|
||||
|
||||
> **Warning:** The static file server methods are **not thread-safe**. Don't call them after `listen()` — configure everything before starting the server.
|
||||
|
||||
> For download-style responses, see S06. Return a File Download Response.
|
||||
> For download-style responses, see [S06. Return a file download response](s06-download-response).
|
||||
|
||||
@@ -60,4 +60,4 @@ Call `sink.done()` to signal the end.
|
||||
|
||||
> **Note:** The provider lambda is called multiple times. Watch out for the lifetime of captured variables — wrap them in a `std::shared_ptr` if needed.
|
||||
|
||||
> To serve the file as a download, see S06. Return a File Download Response.
|
||||
> To serve the file as a download, see [S06. Return a file download response](s06-download-response).
|
||||
|
||||
@@ -68,4 +68,4 @@ Only a small chunk sits in memory at any moment, so gigabyte-scale files are no
|
||||
|
||||
> **Warning:** When you use `HandlerWithContentReader`, `req.body` stays **empty**. Handle the body yourself inside the callbacks.
|
||||
|
||||
> For the client side of multipart uploads, see C07. Upload a File as Multipart Form Data.
|
||||
> For the client side of multipart uploads, see [C07. Upload a file as multipart form data](c07-multipart-upload).
|
||||
|
||||
@@ -50,4 +50,4 @@ svr.Get("/events", [](const httplib::Request &req, httplib::Response &res) {
|
||||
|
||||
> **Note:** Tiny responses barely benefit from compression and just waste CPU time. cpp-httplib skips compression for bodies that are too small to bother with.
|
||||
|
||||
> For the client-side counterpart, see C15. Enable Compression.
|
||||
> For the client-side counterpart, see [C15. Enable compression](c15-compression).
|
||||
|
||||
@@ -49,6 +49,6 @@ If auth fails, return `Handled` to respond with 401 immediately. If it passes, r
|
||||
|
||||
## For per-route auth
|
||||
|
||||
If you want different auth rules per route rather than a single global check, `set_pre_request_handler()` is a better fit. See S11. Authenticate Per Route with a Pre-Request Handler.
|
||||
If you want different auth rules per route rather than a single global check, `set_pre_request_handler()` is a better fit. See [S11. Authenticate per route with a pre-request handler](s11-pre-request).
|
||||
|
||||
> **Note:** If all you want is to modify the response, `set_post_routing_handler()` is the right tool. See S10. Add Response Headers with a Post-Routing Handler.
|
||||
> **Note:** If all you want is to modify the response, `set_post_routing_handler()` is the right tool. See [S10. Add response headers with a post-routing handler](s10-post-routing).
|
||||
|
||||
@@ -4,7 +4,7 @@ order: 30
|
||||
status: "draft"
|
||||
---
|
||||
|
||||
The `set_pre_routing_handler()` from S09 runs **before routing**, so it has no idea which route matched. When you want per-route behavior, `set_pre_request_handler()` is what you need.
|
||||
The `set_pre_routing_handler()` from [S09. Add pre-processing to all routes](s09-pre-routing) runs **before routing**, so it has no idea which route matched. When you want per-route behavior, `set_pre_request_handler()` is what you need.
|
||||
|
||||
## Pre-routing vs. pre-request
|
||||
|
||||
@@ -44,4 +44,4 @@ Same as pre-routing — return `HandlerResponse`.
|
||||
|
||||
## Passing auth info to the route handler
|
||||
|
||||
To pass decoded user info into the route handler, use `res.user_data`. See S12. Pass Data Between Handlers with `res.user_data`.
|
||||
To pass decoded user info into the route handler, use `res.user_data`. See [S12. Pass data between handlers with `res.user_data`](s12-user-data).
|
||||
|
||||
@@ -48,4 +48,4 @@ svr.set_error_handler([](const httplib::Request &req, httplib::Response &res) {
|
||||
|
||||
Now every error comes back in a consistent JSON shape.
|
||||
|
||||
> **Note:** `set_error_handler()` also fires for 500 responses caused by exceptions thrown from a route handler. To get at the exception itself, combine it with `set_exception_handler()`. See S14. Catch Exceptions.
|
||||
> **Note:** `set_error_handler()` also fires for 500 responses caused by exceptions thrown from a route handler. To get at the exception itself, combine it with `set_exception_handler()`. See [S14. Catch exceptions](s14-exception-handler).
|
||||
|
||||
@@ -59,6 +59,6 @@ svr.set_logger([](const auto &req, const auto &res) {
|
||||
});
|
||||
```
|
||||
|
||||
For more on `user_data`, see S12. Pass Data Between Handlers with `res.user_data`.
|
||||
For more on `user_data`, see [S12. Pass data between handlers with `res.user_data`](s12-user-data).
|
||||
|
||||
> **Note:** The logger runs synchronously on the same thread as request processing. Heavy work inside it hurts throughput — push it to a queue and process asynchronously if you need anything expensive.
|
||||
|
||||
@@ -49,4 +49,4 @@ Because the port is assigned at runtime, parallel test runs don't collide.
|
||||
|
||||
> **Note:** `bind_to_any_port()` returns `-1` on failure (permission errors, no available ports, etc.). Always check the return value.
|
||||
|
||||
> To stop the server, see S19. Shut Down Gracefully.
|
||||
> To stop the server, see [S19. Shut down gracefully](s19-graceful-shutdown).
|
||||
|
||||
@@ -54,4 +54,4 @@ if (!svr.bind_to_port("0.0.0.0", 8080)) {
|
||||
|
||||
`listen_after_bind()` blocks until the server stops and returns `true` on a clean shutdown.
|
||||
|
||||
> **Note:** To auto-pick a free port, see S17. Bind to Any Available Port. Under the hood, that's just `bind_to_any_port()` + `listen_after_bind()`.
|
||||
> **Note:** To auto-pick a free port, see [S17. Bind to any available port](s17-bind-any-port). Under the hood, that's just `bind_to_any_port()` + `listen_after_bind()`.
|
||||
|
||||
@@ -52,6 +52,6 @@ Set `set_keep_alive_max_count(1)` and every request gets its own connection. Mos
|
||||
|
||||
## Relationship with the thread pool
|
||||
|
||||
A Keep-Alive connection holds a worker thread for its entire lifetime. If `connections × concurrent requests` exceeds the thread pool size, new requests wait. For thread counts, see S21. Configure the Thread Pool.
|
||||
A Keep-Alive connection holds a worker thread for its entire lifetime. If `connections × concurrent requests` exceeds the thread pool size, new requests wait. For thread counts, see [S21. Configure the thread pool](s21-thread-pool).
|
||||
|
||||
> **Note:** For the client side, see C14. Understand Connection Reuse and Keep-Alive Behavior. Even when the server closes the connection on timeout, the client reconnects automatically.
|
||||
> **Note:** For the client side, see [C14. Understand connection reuse and Keep-Alive behavior](c14-keep-alive). Even when the server closes the connection on timeout, the client reconnects automatically.
|
||||
|
||||
@@ -42,8 +42,8 @@ The usual approach is to treat each backend as a build variant and recompile the
|
||||
|
||||
Certificate verification control, standing up an SSLServer, reading the peer certificate — these all share the same API across backends:
|
||||
|
||||
- T02. Control SSL Certificate Verification
|
||||
- T03. Start an SSL/TLS Server
|
||||
- T05. Access the Peer Certificate on the Server Side
|
||||
- [T02. Control SSL certificate verification](t02-cert-verification)
|
||||
- [T03. Start an SSL/TLS server](t03-ssl-server)
|
||||
- [T05. Access the peer certificate on the server](t05-peer-cert)
|
||||
|
||||
> **Note:** On macOS with an OpenSSL-family backend, cpp-httplib automatically loads root certificates from the system keychain (via `CPPHTTPLIB_USE_CERTS_FROM_MACOSX_KEYCHAIN`, on by default). To disable this, define `CPPHTTPLIB_DISABLE_MACOSX_AUTOMATIC_ROOT_CERTIFICATES`.
|
||||
|
||||
@@ -48,6 +48,6 @@ The certificate itself is still validated, so this is safer than fully disabling
|
||||
|
||||
On most Linux distributions, root certificates live in a single file like `/etc/ssl/certs/ca-certificates.crt`. cpp-httplib reads the OS default store at startup, so for most servers you don't need to configure anything.
|
||||
|
||||
> The same APIs work on the mbedTLS and wolfSSL backends. For choosing between backends, see T01. Choosing Between OpenSSL, mbedTLS, and wolfSSL.
|
||||
> The same APIs work on the mbedTLS and wolfSSL backends. For choosing between backends, see [T01. Choosing between OpenSSL, mbedTLS, and wolfSSL](t01-tls-backends).
|
||||
|
||||
> For details on diagnosing failures, see C18. Handle SSL Errors.
|
||||
> For details on diagnosing failures, see [C18. Handle SSL errors](c18-ssl-errors).
|
||||
|
||||
@@ -34,7 +34,7 @@ httplib::SSLServer svr("cert.pem", "key.pem",
|
||||
nullptr, nullptr, "password");
|
||||
```
|
||||
|
||||
The third and fourth arguments are for client certificate verification (mTLS, see T04). For now, pass `nullptr`.
|
||||
The third and fourth arguments are for client certificate verification (mTLS, see [T04. Configure mTLS](t04-mtls)). For now, pass `nullptr`.
|
||||
|
||||
## Load PEM data from memory
|
||||
|
||||
@@ -73,6 +73,6 @@ openssl req -x509 -newkey rsa:2048 -days 365 -nodes \
|
||||
|
||||
In production, use certificates from Let's Encrypt or your internal CA.
|
||||
|
||||
> **Warning:** Binding an HTTPS server to port 443 requires root. For a safe way to do that, see the privilege-drop pattern in S18. Control Startup Order with `listen_after_bind`.
|
||||
> **Warning:** Binding an HTTPS server to port 443 requires root. For a safe way to do that, see the privilege-drop pattern in [S18. Control startup order with `listen_after_bind`](s18-listen-after-bind).
|
||||
|
||||
> For mutual TLS (client certificates), see T04. Configure mTLS.
|
||||
> For mutual TLS (client certificates), see [T04. Configure mTLS](t04-mtls).
|
||||
|
||||
@@ -59,7 +59,7 @@ Note you're using `SSLClient` directly, not `Client`. If the private key has a p
|
||||
|
||||
## Read client info from a handler
|
||||
|
||||
To see which client connected from inside a handler, use `req.peer_cert()`. Details in T05. Access the Peer Certificate on the Server Side.
|
||||
To see which client connected from inside a handler, use `req.peer_cert()`. Details in [T05. Access the peer certificate on the server](t05-peer-cert).
|
||||
|
||||
## Use cases
|
||||
|
||||
|
||||
@@ -77,7 +77,7 @@ svr.set_pre_request_handler(
|
||||
});
|
||||
```
|
||||
|
||||
Combined with a pre-request handler, you can keep all authorization logic in one place. See S11. Authenticate Per Route with a Pre-Request Handler.
|
||||
Combined with a pre-request handler, you can keep all authorization logic in one place. See [S11. Authenticate per route with a pre-request handler](s11-pre-request).
|
||||
|
||||
## SNI (Server Name Indication)
|
||||
|
||||
@@ -85,4 +85,4 @@ cpp-httplib handles SNI automatically. If one server hosts multiple domains, SNI
|
||||
|
||||
> **Warning:** `req.peer_cert()` only returns a meaningful value when mTLS is enabled and the client actually presented a certificate. For plain TLS, you get an empty `PeerCert`. Always do the `bool` check before using it.
|
||||
|
||||
> To set up mTLS, see T04. Configure mTLS.
|
||||
> To set up mTLS, see [T04. Configure mTLS](t04-mtls).
|
||||
|
||||
@@ -71,7 +71,7 @@ ws.send("Hello"); // text frame
|
||||
ws.send(binary_data, binary_data_size); // binary frame
|
||||
```
|
||||
|
||||
The `std::string` overload sends as **text**; the `const char*` + size overload sends as **binary**. A bit subtle, but once you know it, it's intuitive. See W04. Send and Receive Binary Frames for details.
|
||||
The `std::string` overload sends as **text**; the `const char*` + size overload sends as **binary**. A bit subtle, but once you know it, it's intuitive. See [W04. Send and receive binary frames](w04-websocket-binary) for details.
|
||||
|
||||
## Thread pool implications
|
||||
|
||||
@@ -83,6 +83,6 @@ svr.new_task_queue = [] {
|
||||
};
|
||||
```
|
||||
|
||||
See S21. Configure the Thread Pool.
|
||||
See [S21. Configure the thread pool](s21-thread-pool).
|
||||
|
||||
> **Note:** To run WebSocket over HTTPS, use `httplib::SSLServer` instead of `httplib::Server` — the same `WebSocket()` handler just works. On the client side, use a `wss://` URL.
|
||||
|
||||
@@ -57,4 +57,4 @@ Too short wastes bandwidth; too long and connections get dropped. As a rule of t
|
||||
|
||||
> **Warning:** A very short ping interval spawns background work per connection and increases CPU usage. For servers with many connections, keep the interval modest.
|
||||
|
||||
> For handling a closed connection, see W03. Handle Connection Close.
|
||||
> For handling a closed connection, see [W03. Handle connection close](w03-websocket-close).
|
||||
|
||||
@@ -56,7 +56,7 @@ Binary frames still come back in a `std::string`, but treat its contents as raw
|
||||
|
||||
## Ping is binary-ish, but hidden
|
||||
|
||||
WebSocket Ping/Pong frames are close cousins of binary frames at the opcode level, but cpp-httplib handles them automatically — you don't touch them. See W02. Set a WebSocket Heartbeat.
|
||||
WebSocket Ping/Pong frames are close cousins of binary frames at the opcode level, but cpp-httplib handles them automatically — you don't touch them. See [W02. Set a WebSocket heartbeat](w02-websocket-ping).
|
||||
|
||||
## Example: send an image
|
||||
|
||||
|
||||
Reference in New Issue
Block a user