Drop set_proxy_from_env per #2446 discussion

Per @unterwegi's feedback in #2446, environment variable handling
conflicts with cpp-httplib's long-standing policy of explicit
configuration (e.g. set_ca_cert_path requires explicit paths instead
of reading SSL_CERT_FILE / SSL_CERT_DIR). The NO_PROXY matching logic
is the genuinely tricky part worth keeping in the library; getenv
parsing is trivial and is left to the caller.

- Remove Client::set_proxy_from_env, ClientImpl::set_proxy_from_env,
  and ClientImpl::apply_proxy_url
- Remove ScopedEnv test helper and env-driven NoProxyTest cases
- Replace the "Read proxy settings from the environment" docs with a
  short snippet showing how to parse no_proxy and feed set_no_proxy()
- Keep set_no_proxy() and all NO_PROXY pattern matching intact
This commit is contained in:
yhirose
2026-05-24 21:17:37 -04:00
parent b66fe35868
commit f302e15228
5 changed files with 40 additions and 294 deletions

View File

@@ -69,23 +69,19 @@ Hostname matching is case-insensitive and uses a dot-boundary rule, so an entry
Malformed entries are silently dropped. Port-specific entries such as `example.com:8080` are not supported (cpp-httplib's other host-keyed APIs are also keyed on hostname only).
## Read proxy settings from the environment
## Reading proxy settings from the environment
Call `set_proxy_from_env()` at startup to pick up proxy configuration from environment variables.
cpp-httplib does not read `HTTP_PROXY` / `HTTPS_PROXY` / `NO_PROXY` itself. The library's configuration API is explicit by design — `set_ca_cert_path()` is the same way. If you want that behavior, parse the variables in your application and feed them to `set_proxy()` and `set_no_proxy()`.
```cpp
httplib::Client cli("https://api.example.com");
cli.set_proxy_from_env();
if (auto *v = std::getenv("no_proxy"); v && *v) {
std::vector<std::string> patterns;
std::stringstream ss(v);
for (std::string item; std::getline(ss, item, ',');) {
if (!item.empty()) { patterns.push_back(std::move(item)); }
}
cli.set_no_proxy(patterns);
}
```
Variables read:
- `https_proxy` / `HTTPS_PROXY` — used by HTTPS clients
- `http_proxy` (**lowercase only**, see below) — used by HTTP clients
- `no_proxy` / `NO_PROXY` — comma-separated bypass list
Returns `true` if at least one variable was found and applied.
> **Security Note:** The uppercase `HTTP_PROXY` is intentionally **not** read. In CGI/FastCGI environments, the `HTTP_*` namespace is used to expose HTTP request headers, which lets a remote attacker inject an arbitrary proxy URL via the `Proxy:` request header ([CVE-2016-5385 / "httpoxy"](https://httpoxy.org/)). 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. Concurrent `setenv` from other threads while this function runs is undefined.
> **Security Note:** If you also read `HTTP_PROXY` from the environment, prefer the lowercase `http_proxy` only. The uppercase form is poisoned in CGI/FastCGI environments by the `Proxy:` request header ([CVE-2016-5385 / "httpoxy"](https://httpoxy.org/)). `HTTPS_PROXY` and `NO_PROXY` are safe in either case because their names do not begin with `HTTP_`.

View File

@@ -71,21 +71,17 @@ cli.set_no_proxy({"internal.corp", "10.0.0.0/8", "*.dev.local"});
## 環境変数からプロキシ設定を読み込む
`set_proxy_from_env()`を呼ぶと、起動時の環境変数からプロキシ設定をまとめて取り込めます。
cpp-httplib本体は`HTTP_PROXY` / `HTTPS_PROXY` / `NO_PROXY`を読みません。設定APIを明示的に保つ方針で、`set_ca_cert_path()`なども同様です。必要なら、アプリ側で環境変数を読んで`set_proxy()``set_no_proxy()`に渡します。
```cpp
httplib::Client cli("https://api.example.com");
cli.set_proxy_from_env();
if (auto *v = std::getenv("no_proxy"); v && *v) {
std::vector<std::string> patterns;
std::stringstream ss(v);
for (std::string item; std::getline(ss, item, ',');) {
if (!item.empty()) { patterns.push_back(std::move(item)); }
}
cli.set_no_proxy(patterns);
}
```
読み込まれる変数:
- `https_proxy` / `HTTPS_PROXY` — HTTPSクライアントが使用
- `http_proxy`**小文字のみ**、後述)— HTTPクライアントが使用
- `no_proxy` / `NO_PROXY` — カンマ区切りのバイパスリスト
少なくとも1つの変数が見つかって適用されたら`true`を返します。
> **Security Note:** 大文字の`HTTP_PROXY`は意図的に**読まれません**。CGI/FastCGI環境では`HTTP_*`という名前空間がHTTPリクエストヘッダーの公開に使われており、攻撃者が`Proxy:`リクエストヘッダーで任意のプロキシURLを差し込めてしまうためです[CVE-2016-5385 / "httpoxy"](https://httpoxy.org/)。curl・Go・Python `requests`と同じく、cpp-httplibも小文字の`http_proxy`しか採用しません。`HTTPS_PROXY`や`NO_PROXY`は名前が`HTTP_`で始まらないので、どちらの大文字小文字でも安全です。
> **Note:** `set_proxy_from_env()`は同期的に`getenv`を呼ぶだけなので、起動時に1回呼ぶことを想定しています。他スレッドが同時に`setenv`しているケースは未定義です。
> **Security Note:** `HTTP_PROXY`をアプリ側で読む場合は、小文字の`http_proxy`だけを採用してください。大文字の方はCGI/FastCGI環境で`Proxy:`リクエストヘッダーから汚染される可能性があります([CVE-2016-5385 / "httpoxy"](https://httpoxy.org/))。`HTTPS_PROXY`や`NO_PROXY`は名前が`HTTP_`で始まらないので、どちらの大文字小文字でも安全です。