mirror of
https://github.com/yhirose/cpp-httplib.git
synced 2026-10-19 11:19:36 +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.
65 lines
2.6 KiB
Markdown
65 lines
2.6 KiB
Markdown
---
|
|
title: "C17. Handle Error Codes"
|
|
order: 17
|
|
status: "draft"
|
|
---
|
|
|
|
`cli.Get()`, `cli.Post()`, and friends return a `Result`. When the request fails — can't reach the server, times out, etc. — the result is "falsy", with one exception noted in the table below. To get the specific reason, use `Result::error()`.
|
|
|
|
## Basic check
|
|
|
|
```cpp
|
|
httplib::Client cli("http://localhost:8080");
|
|
auto res = cli.Get("/api/data");
|
|
|
|
if (res) {
|
|
// the request was sent and a response came back
|
|
std::cout << "status: " << res->status << std::endl;
|
|
} else {
|
|
// the network layer failed
|
|
std::cerr << "error: " << httplib::to_string(res.error()) << std::endl;
|
|
}
|
|
```
|
|
|
|
Use `if (res)` to check success. On failure, `res.error()` returns a `httplib::Error` enum value. Pass it to `to_string()` to get a human-readable description.
|
|
|
|
## Common errors
|
|
|
|
| Value | Meaning |
|
|
| --- | --- |
|
|
| `Error::Connection` | Couldn't connect to the server, or the `Client` was built from a URL it can't use (userinfo or a backslash in the authority, a bad port). In the latter case `cli.is_valid()` is `false` |
|
|
| `Error::ConnectionTimeout` | Connection timeout (`set_connection_timeout`) |
|
|
| `Error::Read` / `Error::Write` | Error during send or receive. A timeout from `set_read_timeout` or `set_max_timeout` is also reported as `Error::Read` |
|
|
| `Error::Timeout` | A body read timed out in `stream::Get()` or `SSEClient` |
|
|
| `Error::ExceedRedirectCount` | Too many redirects |
|
|
| `Error::SSLConnection` | TLS handshake failed |
|
|
| `Error::SSLServerVerification` | Server certificate verification failed |
|
|
| `Error::ProxyConnection` | The proxy refused the CONNECT tunnel. A 407 is the exception: `res` is truthy with `res->status == 407`, and `res.error()` is still `Error::ProxyConnection` |
|
|
| `Error::Canceled` | A progress callback, a `ContentReceiver`, a `ResponseHandler`, or an upload content provider returned `false` |
|
|
|
|
## Network errors vs. HTTP errors
|
|
|
|
Even when `res` is truthy, the HTTP status code can still be 4xx or 5xx. These are two different things.
|
|
|
|
```cpp
|
|
auto res = cli.Get("/api/data");
|
|
if (!res) {
|
|
// network error (no response received at all)
|
|
std::cerr << "network error: " << httplib::to_string(res.error()) << std::endl;
|
|
return 1;
|
|
}
|
|
|
|
if (res->status >= 400) {
|
|
// HTTP error (response received, but the status is bad)
|
|
std::cerr << "http error: " << res->status << std::endl;
|
|
return 1;
|
|
}
|
|
|
|
// success
|
|
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](../c18-ssl-errors).
|