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
|
||||
|
||||
|
||||
@@ -57,4 +57,4 @@ auto res = cli.Get("/large-file",
|
||||
>
|
||||
> `ResponseHandler`はヘッダー受信後、ボディ受信前に呼ばれます。`false`を返せばダウンロード自体をスキップできます。
|
||||
|
||||
> ダウンロードの進捗を表示したい場合はC11. 進捗コールバックを使うを参照してください。
|
||||
> ダウンロードの進捗を表示したい場合は[C11. 進捗コールバックを使う](c11-progress-callback)を参照してください。
|
||||
|
||||
@@ -31,6 +31,6 @@ if (res && res->status == 200) {
|
||||
|
||||
`res->body`は`std::string`なので、そのままJSONライブラリに渡せます。
|
||||
|
||||
> **Note:** サーバーがエラー時にHTMLを返すことがあります。ステータスコードを確認してからパースすると安全です。また、APIによっては`Accept: application/json`ヘッダーが必要です。JSON APIを繰り返し呼ぶならC03. デフォルトヘッダーを設定するが便利です。
|
||||
> **Note:** サーバーがエラー時にHTMLを返すことがあります。ステータスコードを確認してからパースすると安全です。また、APIによっては`Accept: application/json`ヘッダーが必要です。JSON APIを繰り返し呼ぶなら[C03. デフォルトヘッダーを設定する](c03-default-headers)が便利です。
|
||||
|
||||
> サーバー側でJSONを受け取って返す方法はS02. JSONリクエストを受け取りJSONレスポンスを返すを参照してください。
|
||||
> サーバー側でJSONを受け取って返す方法は[S02. JSONリクエストを受け取りJSONレスポンスを返す](s02-json-api)を参照してください。
|
||||
|
||||
@@ -52,4 +52,4 @@ auto res = cli.Get("/users", headers);
|
||||
|
||||
リクエスト単位で渡したヘッダーはデフォルトヘッダーに**追加**されます。両方がサーバーに送られます。
|
||||
|
||||
> Bearerトークンを使った認証の詳細はC06. BearerトークンでAPIを呼ぶを参照してください。
|
||||
> Bearerトークンを使った認証の詳細は[C06. BearerトークンでAPIを呼ぶ](c06-bearer-token)を参照してください。
|
||||
|
||||
@@ -35,4 +35,4 @@ auto res = cli.Get("/");
|
||||
|
||||
> **Warning:** HTTPSへのリダイレクトを追従するには、cpp-httplibをOpenSSL(または他のTLSバックエンド)付きでビルドしておく必要があります。TLSサポートがないと、HTTPSへのリダイレクトは失敗します。
|
||||
|
||||
> **Note:** リダイレクトを追従すると、リクエストの実行時間は伸びます。タイムアウトの設定はC12. タイムアウトを設定するを参照してください。
|
||||
> **Note:** リダイレクトを追従すると、リクエストの実行時間は伸びます。タイムアウトの設定は[C12. タイムアウトを設定する](c12-timeouts)を参照してください。
|
||||
|
||||
@@ -43,4 +43,4 @@ auto res = cli.Get("/private", headers);
|
||||
cli.set_digest_auth("alice", "s3cret");
|
||||
```
|
||||
|
||||
> BearerトークンでAPIを呼びたい場合はC06. BearerトークンでAPIを呼ぶを参照してください。
|
||||
> BearerトークンでAPIを呼びたい場合は[C06. BearerトークンでAPIを呼ぶ](c06-bearer-token)を参照してください。
|
||||
|
||||
@@ -47,4 +47,4 @@ if (res && res->status == 401) {
|
||||
|
||||
> **Warning:** Bearerトークンはそれ自体が認証情報です。必ずHTTPS経由で送ってください。また、ソースコードや設定ファイルにトークンをハードコードしないようにしましょう。
|
||||
|
||||
> 複数のヘッダーをまとめて設定したいときはC03. デフォルトヘッダーを設定するも便利です。
|
||||
> 複数のヘッダーをまとめて設定したいときは[C03. デフォルトヘッダーを設定する](c03-default-headers)も便利です。
|
||||
|
||||
@@ -49,4 +49,4 @@ auto res = cli.Post("/upload", httplib::Headers{}, items, provider_items);
|
||||
|
||||
> **Note:** `UploadFormDataItems`と`FormDataProviderItems`は同じリクエスト内で併用できます。テキストフィールドは`UploadFormDataItems`、ファイルは`FormDataProviderItems`、という使い分けがきれいです。
|
||||
|
||||
> アップロードの進捗を表示したい場合はC11. 進捗コールバックを使うを参照してください。
|
||||
> アップロードの進捗を表示したい場合は[C11. 進捗コールバックを使う](c11-progress-callback)を参照してください。
|
||||
|
||||
@@ -31,4 +31,4 @@ auto res = cli.Put("/bucket/backup.tar.gz", size,
|
||||
|
||||
> **Warning:** `make_file_body()`はContent-Lengthを最初に確定させる必要があるため、ファイルサイズをあらかじめ取得します。送信中にファイルサイズが変わる可能性がある場合は、このAPIには向きません。
|
||||
|
||||
> マルチパート形式で送りたい場合はC07. ファイルをマルチパートフォームとしてアップロードするを参照してください。
|
||||
> マルチパート形式で送りたい場合は[C07. ファイルをマルチパートフォームとしてアップロードする](c07-multipart-upload)を参照してください。
|
||||
|
||||
@@ -44,4 +44,4 @@ auto res = cli.Post("/upload", total_size,
|
||||
|
||||
> **Detail:** `sink.write()`は書き込みが成功したかどうかを`bool`で返します。`false`が返ったら回線が切れています。ラムダはそのまま`false`を返して終了しましょう。
|
||||
|
||||
> ファイルをそのまま送るだけなら、`make_file_body()`が便利です。C08. ファイルを生バイナリとしてPOSTするを参照してください。
|
||||
> ファイルをそのまま送るだけなら、`make_file_body()`が便利です。[C08. ファイルを生バイナリとしてPOSTする](c08-post-file-body)を参照してください。
|
||||
|
||||
@@ -48,5 +48,5 @@ auto res = cli.Get("/events",
|
||||
|
||||
> **Warning:** `ContentReceiver`を渡すと、`res->body`は**空のまま**になります。ボディは自分でコールバック内で保存するか処理するかしてください。
|
||||
|
||||
> ダウンロードの進捗を知りたい場合はC11. 進捗コールバックを使うと組み合わせましょう。
|
||||
> Server-Sent Events(SSE)を扱うときはE04. SSEをクライアントで受信するも参考になります。
|
||||
> ダウンロードの進捗を知りたい場合は[C11. 進捗コールバックを使う](c11-progress-callback)と組み合わせましょう。
|
||||
> Server-Sent Events(SSE)を扱うときは[E04. SSEをクライアントで受信する](e04-sse-client)も参考になります。
|
||||
|
||||
@@ -56,4 +56,4 @@ auto res = cli.Get("/large-file",
|
||||
|
||||
> **Note:** `ContentReceiver`と進捗コールバックは同時に使えます。ファイルに書き出しながら進捗を表示したいときは、両方を渡しましょう。
|
||||
|
||||
> ファイル保存と組み合わせる具体例はC01. レスポンスボディを取得する / ファイルに保存するも参照してください。
|
||||
> ファイル保存と組み合わせる具体例は[C01. レスポンスボディを取得する / ファイルに保存する](c01-get-response-body)も参照してください。
|
||||
|
||||
@@ -47,4 +47,4 @@ cli.set_connection_timeout(3s);
|
||||
cli.set_read_timeout(10s);
|
||||
```
|
||||
|
||||
> **Warning:** 読み取りタイムアウトは「1回の受信待ち」に対するタイムアウトです。大きなファイルのダウンロードで途中ずっとデータが流れている限り、リクエスト全体で30分かかっても発火しません。リクエスト全体の時間制限を設けたい場合はC13. 全体タイムアウトを設定するを使ってください。
|
||||
> **Warning:** 読み取りタイムアウトは「1回の受信待ち」に対するタイムアウトです。大きなファイルのダウンロードで途中ずっとデータが流れている限り、リクエスト全体で30分かかっても発火しません。リクエスト全体の時間制限を設けたい場合は[C13. 全体タイムアウトを設定する](c13-max-timeout)を使ってください。
|
||||
|
||||
@@ -4,7 +4,7 @@ order: 13
|
||||
status: "draft"
|
||||
---
|
||||
|
||||
C12. タイムアウトを設定するで紹介した3種類のタイムアウトは、いずれも「1回の`send`や`recv`」に対するものです。リクエスト全体の所要時間に上限を設けたい場合は、`set_max_timeout()`を使います。
|
||||
[C12. タイムアウトを設定する](c12-timeouts)で紹介した3種類のタイムアウトは、いずれも「1回の`send`や`recv`」に対するものです。リクエスト全体の所要時間に上限を設けたい場合は、`set_max_timeout()`を使います。
|
||||
|
||||
## 基本の使い方
|
||||
|
||||
|
||||
@@ -38,7 +38,7 @@ cli.set_proxy_digest_auth("user", "password");
|
||||
|
||||
## エンドのサーバー認証と組み合わせる
|
||||
|
||||
プロキシ認証と、エンドサーバーへの認証(C05やC06)は別物です。両方が必要なら、両方設定します。
|
||||
プロキシ認証と、エンドサーバーへの認証([C05. Basic認証を使う](c05-basic-auth)や[C06. BearerトークンでAPIを呼ぶ](c06-bearer-token))は別物です。両方が必要なら、両方設定します。
|
||||
|
||||
```cpp
|
||||
cli.set_proxy("proxy.internal", 8080);
|
||||
|
||||
@@ -60,4 +60,4 @@ std::cout << res->body << std::endl;
|
||||
|
||||
ネットワーク層のエラーは`res.error()`、HTTPのエラーは`res->status`、と頭の中で分けておきましょう。
|
||||
|
||||
> SSL関連のエラーをさらに詳しく調べたい場合はC18. SSLエラーをハンドリングするを参照してください。
|
||||
> SSL関連のエラーをさらに詳しく調べたい場合は[C18. SSLエラーをハンドリングする](c18-ssl-errors)を参照してください。
|
||||
|
||||
@@ -50,4 +50,4 @@ if (res.ssl_backend_error() != 0) {
|
||||
|
||||
> **Note:** `ssl_backend_error()`は以前は`ssl_openssl_error()`と呼ばれていました。後者はdeprecatedで、現在は`ssl_backend_error()`を使ってください。
|
||||
|
||||
> 証明書の検証設定を変えたい場合はT02. SSL証明書の検証を制御するを参照してください。
|
||||
> 証明書の検証設定を変えたい場合は[T02. SSL証明書の検証を制御する](t02-cert-verification)を参照してください。
|
||||
|
||||
@@ -56,7 +56,7 @@ svr.Get("/time", [](const httplib::Request &req, httplib::Response &res) {
|
||||
});
|
||||
```
|
||||
|
||||
クライアントが切断したら`sink.done()`で終了します。詳しくはS16. クライアントが切断したか検出するを参照してください。
|
||||
クライアントが切断したら`sink.done()`で終了します。詳しくは[S16. クライアントが切断したか検出する](s16-disconnect)を参照してください。
|
||||
|
||||
## コメント行でハートビート
|
||||
|
||||
@@ -80,8 +80,8 @@ svr.new_task_queue = [] {
|
||||
};
|
||||
```
|
||||
|
||||
詳しくはS21. マルチスレッド数を設定するを参照してください。
|
||||
詳しくは[S21. マルチスレッド数を設定する](s21-thread-pool)を参照してください。
|
||||
|
||||
> **Note:** `data:`の後ろに改行が含まれる場合、各行の先頭に`data: `を付けて複数の`data:`行として送ります。SSEの仕様で決まっているフォーマットです。
|
||||
|
||||
> イベント名を使い分けたい場合はE02. SSEでイベント名を使い分けるを、クライアント側はE04. SSEをクライアントで受信するを参照してください。
|
||||
> イベント名を使い分けたい場合は[E02. SSEでイベント名を使い分ける](e02-sse-event-names)を、クライアント側は[E04. SSEをクライアントで受信する](e04-sse-client)を参照してください。
|
||||
|
||||
@@ -52,7 +52,7 @@ auto send_event = [](httplib::DataSink &sink,
|
||||
send_event(sink, "message", "Hello!", "42");
|
||||
```
|
||||
|
||||
IDの付け方は自由です。連番でもUUIDでも、サーバー側で重複せず順序が追えるものを選びましょう。再接続の詳細はE03. SSEの再接続を処理するを参照してください。
|
||||
IDの付け方は自由です。連番でもUUIDでも、サーバー側で重複せず順序が追えるものを選びましょう。再接続の詳細は[E03. SSEの再接続を処理する](e03-sse-reconnect)を参照してください。
|
||||
|
||||
## JSONをdataに乗せる
|
||||
|
||||
|
||||
@@ -96,4 +96,4 @@ std::cout << "last id: " << sse.last_event_id() << std::endl;
|
||||
|
||||
> **Note:** SSEClientの`start()`はブロッキングなので、単発のツールならそのまま使えますが、GUIアプリやサーバーに組み込むときは`start_async()` + `stop()`の組み合わせが基本です。
|
||||
|
||||
> サーバー側の実装はE01. SSEサーバーを実装するを参照してください。
|
||||
> サーバー側の実装は[E01. SSEサーバーを実装する](e01-sse-server)を参照してください。
|
||||
|
||||
@@ -61,6 +61,6 @@ svr.Get("/me", [](const httplib::Request &req, httplib::Response &res) {
|
||||
|
||||
レスポンスヘッダーを追加したいときは`res.set_header("Name", "Value")`です。
|
||||
|
||||
> **Note:** `listen()`はブロックする関数です。別スレッドで動かしたいときは`std::thread`で包むか、ノンブロッキング起動が必要ならS18. `listen_after_bind`で起動順序を制御するを参照してください。
|
||||
> **Note:** `listen()`はブロックする関数です。別スレッドで動かしたいときは`std::thread`で包むか、ノンブロッキング起動が必要なら[S18. `listen_after_bind`で起動順序を制御する](s18-listen-after-bind)を参照してください。
|
||||
|
||||
> パスパラメーター(`/users/:id`)を使いたい場合はS03. パスパラメーターを使うを参照してください。
|
||||
> パスパラメーター(`/users/:id`)を使いたい場合は[S03. パスパラメーターを使う](s03-path-params)を参照してください。
|
||||
|
||||
@@ -69,6 +69,6 @@ svr.Get("/api/health", [&](const auto &req, auto &res) {
|
||||
});
|
||||
```
|
||||
|
||||
> **Note:** 大きなJSONボディを受け取ると、`req.body`がまるごとメモリに載ります。巨大なペイロードを扱うときはS07. マルチパートデータをストリーミングで受け取るのように、ストリーミング受信も検討しましょう。
|
||||
> **Note:** 大きなJSONボディを受け取ると、`req.body`がまるごとメモリに載ります。巨大なペイロードを扱うときは[S07. マルチパートデータをストリーミングで受け取る](s07-multipart-reader)のように、ストリーミング受信も検討しましょう。
|
||||
|
||||
> クライアント側の書き方はC02. JSONを送受信するを参照してください。
|
||||
> クライアント側の書き方は[C02. JSONを送受信する](c02-json)を参照してください。
|
||||
|
||||
@@ -52,4 +52,4 @@ svr.set_file_extension_and_mimetype_mapping("wasm", "application/wasm");
|
||||
|
||||
> **Warning:** 静的ファイル配信系のメソッドは**スレッドセーフではありません**。起動後(`listen()`以降)には呼ばないでください。起動前にまとめて設定しましょう。
|
||||
|
||||
> ダウンロード用のレスポンスを返したい場合はS06. ファイルダウンロードレスポンスを返すも参考になります。
|
||||
> ダウンロード用のレスポンスを返したい場合は[S06. ファイルダウンロードレスポンスを返す](s06-download-response)も参考になります。
|
||||
|
||||
@@ -60,4 +60,4 @@ svr.Get("/events", [](const httplib::Request &req, httplib::Response &res) {
|
||||
|
||||
> **Note:** プロバイダラムダは複数回呼ばれます。キャプチャする変数のライフタイムに気をつけてください。必要なら`std::shared_ptr`などで包みましょう。
|
||||
|
||||
> ファイルダウンロードとして扱いたい場合はS06. ファイルダウンロードレスポンスを返すを参照してください。
|
||||
> ファイルダウンロードとして扱いたい場合は[S06. ファイルダウンロードレスポンスを返す](s06-download-response)を参照してください。
|
||||
|
||||
@@ -68,4 +68,4 @@ svr.Post("/upload",
|
||||
|
||||
> **Warning:** `HandlerWithContentReader`を使うと、`req.body`は**空のまま**です。ボディはコールバック内で自分で処理してください。
|
||||
|
||||
> クライアント側でマルチパートを送る方法はC07. ファイルをマルチパートフォームとしてアップロードするを参照してください。
|
||||
> クライアント側でマルチパートを送る方法は[C07. ファイルをマルチパートフォームとしてアップロードする](c07-multipart-upload)を参照してください。
|
||||
|
||||
@@ -50,4 +50,4 @@ svr.Get("/events", [](const httplib::Request &req, httplib::Response &res) {
|
||||
|
||||
> **Note:** 小さなレスポンスは圧縮しても効果が薄く、むしろCPU時間を無駄にすることがあります。cpp-httplibは小さすぎるボディは圧縮をスキップします。
|
||||
|
||||
> クライアント側の挙動はC15. 圧縮を有効にするを参照してください。
|
||||
> クライアント側の挙動は[C15. 圧縮を有効にする](c15-compression)を参照してください。
|
||||
|
||||
@@ -49,6 +49,6 @@ svr.set_pre_routing_handler(
|
||||
|
||||
## 特定ルートだけに認証をかけたい場合
|
||||
|
||||
全ルート共通ではなく、ルート単位で認証を分けたいときは、S11. Pre-request handlerでルート単位の認証を行うのほうが適しています。
|
||||
全ルート共通ではなく、ルート単位で認証を分けたいときは、[S11. Pre-request handlerでルート単位の認証を行う](s11-pre-request)のほうが適しています。
|
||||
|
||||
> **Note:** レスポンスを加工したいだけなら、`set_post_routing_handler()`のほうが適切です。S10. Post-routing handlerでレスポンスヘッダーを追加するを参照してください。
|
||||
> **Note:** レスポンスを加工したいだけなら、`set_post_routing_handler()`のほうが適切です。[S10. Post-routing handlerでレスポンスヘッダーを追加する](s10-post-routing)を参照してください。
|
||||
|
||||
@@ -4,7 +4,7 @@ order: 30
|
||||
status: "draft"
|
||||
---
|
||||
|
||||
S09で紹介した`set_pre_routing_handler()`はルーティングの**前**に呼ばれるので、「どのルートにマッチしたか」を知れません。ルートによって認証の有無を変えたい場合は、`set_pre_request_handler()`のほうが便利です。
|
||||
[S09. 全ルートに共通の前処理をする](s09-pre-routing)で紹介した`set_pre_routing_handler()`はルーティングの**前**に呼ばれるので、「どのルートにマッチしたか」を知れません。ルートによって認証の有無を変えたい場合は、`set_pre_request_handler()`のほうが便利です。
|
||||
|
||||
## Pre-routingとの違い
|
||||
|
||||
@@ -44,4 +44,4 @@ Pre-routingハンドラと同じく、`HandlerResponse`を返します。
|
||||
|
||||
## 認証情報を後続のハンドラに渡す
|
||||
|
||||
認証で取り出したユーザー情報などをルートハンドラに渡したいときは、`res.user_data`を使います。詳しくはS12. `res.user_data`でハンドラ間データを渡すを参照してください。
|
||||
認証で取り出したユーザー情報などをルートハンドラに渡したいときは、`res.user_data`を使います。詳しくは[S12. `res.user_data`でハンドラ間データを渡す](s12-user-data)を参照してください。
|
||||
|
||||
@@ -48,4 +48,4 @@ svr.set_error_handler([](const httplib::Request &req, httplib::Response &res) {
|
||||
|
||||
これで全エラーが統一されたJSONで返ります。
|
||||
|
||||
> **Note:** `set_error_handler()`は、ルートハンドラが例外を投げた場合の500エラーにも呼ばれます。例外そのものの情報を取り出したい場合は`set_exception_handler()`を組み合わせましょう。S14. 例外をキャッチするを参照してください。
|
||||
> **Note:** `set_error_handler()`は、ルートハンドラが例外を投げた場合の500エラーにも呼ばれます。例外そのものの情報を取り出したい場合は`set_exception_handler()`を組み合わせましょう。[S14. 例外をキャッチする](s14-exception-handler)を参照してください。
|
||||
|
||||
@@ -59,6 +59,6 @@ svr.set_logger([](const auto &req, const auto &res) {
|
||||
});
|
||||
```
|
||||
|
||||
`user_data`の使い方はS12. `res.user_data`でハンドラ間データを渡すも参照してください。
|
||||
`user_data`の使い方は[S12. `res.user_data`でハンドラ間データを渡す](s12-user-data)も参照してください。
|
||||
|
||||
> **Note:** ロガーはリクエスト処理と同じスレッドで同期的に呼ばれます。重い処理を直接入れると全体のスループットが落ちるので、必要ならキューに流して非同期で処理しましょう。
|
||||
|
||||
@@ -49,4 +49,4 @@ t.join();
|
||||
|
||||
> **Note:** `bind_to_any_port()`は失敗すると`-1`を返します。権限エラーや利用可能ポートが無いケースなので、返り値のチェックを忘れずに。
|
||||
|
||||
> サーバーを止める方法はS19. グレースフルシャットダウンするを参照してください。
|
||||
> サーバーを止める方法は[S19. グレースフルシャットダウンする](s19-graceful-shutdown)を参照してください。
|
||||
|
||||
@@ -54,4 +54,4 @@ if (!svr.bind_to_port("0.0.0.0", 8080)) {
|
||||
|
||||
`listen_after_bind()`はサーバーが停止するまでブロックし、正常終了なら`true`を返します。
|
||||
|
||||
> **Note:** 空いているポートを自動で選びたいときはS17. ポートを動的に割り当てるを参照してください。こちらも内部では`bind_to_any_port()` + `listen_after_bind()`の組み合わせです。
|
||||
> **Note:** 空いているポートを自動で選びたいときは[S17. ポートを動的に割り当てる](s17-bind-any-port)を参照してください。こちらも内部では`bind_to_any_port()` + `listen_after_bind()`の組み合わせです。
|
||||
|
||||
@@ -52,6 +52,6 @@ svr.set_keep_alive_max_count(1000);
|
||||
|
||||
## スレッドプールとの関係
|
||||
|
||||
Keep-Aliveでつながりっぱなしの接続は、その間ずっとワーカースレッドを1つ占有します。接続数 × 同時リクエスト数がスレッドプールのサイズを超えると、新しいリクエストが待たされます。スレッド数の調整はS21. マルチスレッド数を設定するを参照してください。
|
||||
Keep-Aliveでつながりっぱなしの接続は、その間ずっとワーカースレッドを1つ占有します。接続数 × 同時リクエスト数がスレッドプールのサイズを超えると、新しいリクエストが待たされます。スレッド数の調整は[S21. マルチスレッド数を設定する](s21-thread-pool)を参照してください。
|
||||
|
||||
> **Note:** クライアント側の挙動はC14. 接続の再利用とKeep-Aliveの挙動を理解するを参照してください。サーバーがタイムアウトで接続を切っても、クライアントは自動で再接続します。
|
||||
> **Note:** クライアント側の挙動は[C14. 接続の再利用とKeep-Aliveの挙動を理解する](c14-keep-alive)を参照してください。サーバーがタイムアウトで接続を切っても、クライアントは自動で再接続します。
|
||||
|
||||
@@ -42,8 +42,8 @@ wolfSSLには商用ライセンスとサポートがあります。製品に組
|
||||
|
||||
証明書の検証制御、SSLServerの立ち上げ、ピア証明書の取得などは、どのバックエンドでも同じAPIで呼べます。
|
||||
|
||||
- T02. SSL証明書の検証を制御する
|
||||
- T03. SSL/TLSサーバーを立ち上げる
|
||||
- T05. サーバー側でピア証明書を参照する
|
||||
- [T02. SSL証明書の検証を制御する](t02-cert-verification)
|
||||
- [T03. SSL/TLSサーバーを立ち上げる](t03-ssl-server)
|
||||
- [T05. サーバー側でピア証明書を参照する](t05-peer-cert)
|
||||
|
||||
> **Note:** macOSでは、OpenSSL系のバックエンドを使う場合、システムのキーチェーンからルート証明書を自動で読む設定(`CPPHTTPLIB_USE_CERTS_FROM_MACOSX_KEYCHAIN`)がデフォルトで有効です。無効にしたい場合は`CPPHTTPLIB_DISABLE_MACOSX_AUTOMATIC_ROOT_CERTIFICATES`を定義してください。
|
||||
|
||||
@@ -48,6 +48,6 @@ cli.enable_server_hostname_verification(false);
|
||||
|
||||
多くのLinuxディストリビューションでは、`/etc/ssl/certs/ca-certificates.crt`などにルート証明書がまとまっています。cpp-httplibは起動時にOSのデフォルトストアを自動で読みにいくので、普通のサーバーならとくに設定不要です。
|
||||
|
||||
> mbedTLSやwolfSSLバックエンドでも同じAPIが使えます。バックエンドの選び方はT01. OpenSSL・mbedTLS・wolfSSLの選択指針を参照してください。
|
||||
> mbedTLSやwolfSSLバックエンドでも同じAPIが使えます。バックエンドの選び方は[T01. OpenSSL・mbedTLS・wolfSSLの選択指針](t01-tls-backends)を参照してください。
|
||||
|
||||
> 失敗したときの詳細を調べる方法はC18. SSLエラーをハンドリングするを参照してください。
|
||||
> 失敗したときの詳細を調べる方法は[C18. SSLエラーをハンドリングする](c18-ssl-errors)を参照してください。
|
||||
|
||||
@@ -34,7 +34,7 @@ httplib::SSLServer svr("cert.pem", "key.pem",
|
||||
nullptr, nullptr, "password");
|
||||
```
|
||||
|
||||
第3、第4引数はクライアント証明書検証用(mTLS、T04参照)なので、今は`nullptr`を指定します。
|
||||
第3、第4引数はクライアント証明書検証用(mTLS、[T04. mTLSを設定する](t04-mtls)参照)なので、今は`nullptr`を指定します。
|
||||
|
||||
## メモリ上のPEMから立ち上げる
|
||||
|
||||
@@ -73,6 +73,6 @@ openssl req -x509 -newkey rsa:2048 -days 365 -nodes \
|
||||
|
||||
本番では、Let's Encryptや社内CAから発行された証明書を使いましょう。
|
||||
|
||||
> **Warning:** HTTPSサーバーを443番ポートで立ち上げるにはroot権限が必要です。安全に立ち上げる方法はS18. `listen_after_bind`で起動順序を制御するの「特権降格」を参照してください。
|
||||
> **Warning:** HTTPSサーバーを443番ポートで立ち上げるにはroot権限が必要です。安全に立ち上げる方法は[S18. `listen_after_bind`で起動順序を制御する](s18-listen-after-bind)の「特権降格」を参照してください。
|
||||
|
||||
> クライアント証明書による相互認証(mTLS)はT04. mTLSを設定するを参照してください。
|
||||
> クライアント証明書による相互認証(mTLS)は[T04. mTLSを設定する](t04-mtls)を参照してください。
|
||||
|
||||
@@ -59,7 +59,7 @@ auto res = cli.Get("/");
|
||||
|
||||
## ハンドラからクライアント情報を取得する
|
||||
|
||||
ハンドラの中で、どのクライアントが接続してきたかを確認したいときは`req.peer_cert()`を使います。詳しくはT05. サーバー側でピア証明書を参照するを参照してください。
|
||||
ハンドラの中で、どのクライアントが接続してきたかを確認したいときは`req.peer_cert()`を使います。詳しくは[T05. サーバー側でピア証明書を参照する](t05-peer-cert)を参照してください。
|
||||
|
||||
## 用途
|
||||
|
||||
|
||||
@@ -77,7 +77,7 @@ svr.set_pre_request_handler(
|
||||
});
|
||||
```
|
||||
|
||||
Pre-requestハンドラと組み合わせれば、共通の認可ロジックを一箇所にまとめられます。詳しくはS11. Pre-request handlerでルート単位の認証を行うを参照してください。
|
||||
Pre-requestハンドラと組み合わせれば、共通の認可ロジックを一箇所にまとめられます。詳しくは[S11. Pre-request handlerでルート単位の認証を行う](s11-pre-request)を参照してください。
|
||||
|
||||
## SNI(Server Name Indication)
|
||||
|
||||
@@ -85,4 +85,4 @@ Pre-requestハンドラと組み合わせれば、共通の認可ロジックを
|
||||
|
||||
> **Warning:** `req.peer_cert()`は、mTLSが有効で、かつクライアントが証明書を提示した場合のみ有効な値を返します。通常のTLS接続では空の`PeerCert`が返ります。使う前に必ず`bool`チェックしてください。
|
||||
|
||||
> mTLSの設定方法はT04. mTLSを設定するを参照してください。
|
||||
> mTLSの設定方法は[T04. mTLSを設定する](t04-mtls)を参照してください。
|
||||
|
||||
@@ -71,7 +71,7 @@ ws.send("Hello"); // テキストフレーム
|
||||
ws.send(binary_data, binary_data_size); // バイナリフレーム
|
||||
```
|
||||
|
||||
`std::string`を受け取るオーバーロードはテキスト、`const char*`とサイズを受け取るオーバーロードはバイナリとして送られます。詳しくはW04. バイナリフレームを送受信するを参照してください。
|
||||
`std::string`を受け取るオーバーロードはテキスト、`const char*`とサイズを受け取るオーバーロードはバイナリとして送られます。詳しくは[W04. バイナリフレームを送受信する](w04-websocket-binary)を参照してください。
|
||||
|
||||
## スレッドとの関係
|
||||
|
||||
@@ -83,6 +83,6 @@ svr.new_task_queue = [] {
|
||||
};
|
||||
```
|
||||
|
||||
詳細はS21. マルチスレッド数を設定するを参照してください。
|
||||
詳細は[S21. マルチスレッド数を設定する](s21-thread-pool)を参照してください。
|
||||
|
||||
> **Note:** HTTPSサーバーの上でWebSocketを動かしたいときは、`httplib::Server`の代わりに`httplib::SSLServer`を使えば、同じ`WebSocket()`ハンドラがそのまま動きます。クライアント側は`wss://`スキームを指定するだけです。
|
||||
|
||||
@@ -57,4 +57,4 @@ WebSocketプロトコルでは、PingフレームにはPongフレームで応答
|
||||
|
||||
> **Warning:** Ping間隔を極端に短くすると、WebSocket接続ごとにバックグラウンドでスレッドが走るので、CPU負荷が上がります。接続数が多いサーバーでは控えめな値に設定しましょう。
|
||||
|
||||
> 接続が閉じたときの処理はW03. 接続クローズをハンドリングするを参照してください。
|
||||
> 接続が閉じたときの処理は[W03. 接続クローズをハンドリングする](w03-websocket-close)を参照してください。
|
||||
|
||||
@@ -56,7 +56,7 @@ switch (result) {
|
||||
|
||||
## Pingもバイナリフレームの一種
|
||||
|
||||
WebSocketのPing/PongフレームもOpcodeレベルではバイナリに近い扱いですが、cpp-httplibが自動で処理するので、アプリケーションコードで意識する必要はありません。W02. ハートビートを設定するを参照してください。
|
||||
WebSocketのPing/PongフレームもOpcodeレベルではバイナリに近い扱いですが、cpp-httplibが自動で処理するので、アプリケーションコードで意識する必要はありません。[W02. ハートビートを設定する](w02-websocket-ping)を参照してください。
|
||||
|
||||
## サンプル: 画像を送る
|
||||
|
||||
|
||||
Reference in New Issue
Block a user