Document set_no_proxy and set_proxy_from_env in README

Adds two subsections under "Proxy server support":

  - "Bypass the proxy for specific hosts (NO_PROXY)" — set_no_proxy,
    pattern syntax, dot-boundary rule, IP normalization, limitations
    (no port-specific entries, no v4-mapped v6 cross-match, replace
    semantics).

  - "Read proxy settings from the environment" — set_proxy_from_env,
    which variables are read, the lowercase-only http_proxy rule with
    an inline httpoxy / CVE-2016-5385 explanation, threading
    expectations.

Documentation only. Closes the doc gap from #2446.
This commit is contained in:
yhirose
2026-05-08 23:21:47 +09:00
parent cbd0ec5a99
commit 60cb6f5896

View File

@@ -1181,6 +1181,76 @@ cli.set_proxy_bearer_token_auth("pass");
> [!NOTE] > [!NOTE]
> OpenSSL is required for Digest Authentication. > OpenSSL is required for Digest Authentication.
#### Bypass the proxy for specific hosts (`NO_PROXY`)
`set_no_proxy` configures a bypass list. Each pattern is one of:
- `*` — bypass the proxy for every target
- a hostname suffix, e.g. `example.com` — matches `example.com` and any
subdomain (`foo.example.com`). A leading dot (`.example.com`) is
permitted but informational; both forms are equivalent.
- a single IP literal, e.g. `192.168.1.1`, `::1`
- a CIDR block, e.g. `10.0.0.0/8`, `fe80::/10`
```cpp
cli.set_proxy("proxy.corp", 3128);
cli.set_no_proxy({"internal.corp", "10.0.0.0/8", "*.dev.local"});
```
When a NO_PROXY entry matches the target host, the request is sent
directly and the corresponding `Proxy-Authorization` header is
suppressed.
Hostname matching is **case-insensitive** and uses a dot-boundary rule,
so `evilexample.com` does **not** match an entry of `example.com`. IP
comparisons are normalized through `inet_pton`, so `127.0.0.1` cannot
be bypassed via alternate string forms (e.g. leading-zero octets or
decimal-form integers). Malformed entries are silently dropped.
Limitations:
- Port-specific entries (`example.com:8080`) are not supported. cpp-httplib's
other host-keyed APIs (e.g. `set_hostname_addr_map`) are also keyed on
hostname only; supporting host:port for NO_PROXY alone would be
inconsistent.
- IPv4-mapped IPv6 addresses (`::ffff:1.2.3.4`) are not cross-matched
against IPv4 NO_PROXY entries.
- `set_no_proxy` replaces any previously configured list; there is no
append API.
#### Read proxy settings from the environment
`set_proxy_from_env` configures the client from proxy-related
environment variables.
```cpp
httplib::Client cli("https://api.example.com");
cli.set_proxy_from_env();
```
Variables read:
- `https_proxy` / `HTTPS_PROXY` — used by HTTPS clients (`SSLClient`)
- `http_proxy` (lowercase only — see security note below) — used by HTTP clients
- `no_proxy` / `NO_PROXY` — comma-separated list of bypass patterns
Returns `true` if at least one variable was found and applied.
> [!IMPORTANT]
> The uppercase `HTTP_PROXY` is intentionally ignored to mitigate the
> "httpoxy" class of bugs ([CVE-2016-5385](https://httpoxy.org/)). In
> CGI / FastCGI environments the variable name collides with the
> `HTTP_*` namespace used to expose request headers, allowing a remote
> attacker to set the proxy URL via the `Proxy:` request header.
> cpp-httplib follows curl, Go, and Python `requests` in honoring only
> the lowercase `http_proxy`. `HTTPS_PROXY` and `NO_PROXY` are safe in
> either case because their names do not begin with `HTTP_`.
> [!NOTE]
> `set_proxy_from_env` reads `getenv` synchronously. Call it once at
> startup before issuing any requests; concurrent `setenv` from other
> threads is undefined.
### Range ### Range
```cpp ```cpp