From 26569b42fa22eb9ce6cb85b6c3b08d87e4f2f7df Mon Sep 17 00:00:00 2001 From: yhirose Date: Fri, 8 May 2026 23:23:14 +0900 Subject: [PATCH] Document NO_PROXY and set_proxy_from_env in cookbook c16-proxy Replaces the now-incorrect Note at the bottom of c16-proxy ("cpp-httplib does not read HTTP_PROXY...") with the actual API. JA is the master per the project's translation workflow; the EN translation lands in the same PR. Both pages remain `status: "draft"` for normal review. Adds two sections: - Bypass the proxy for specific hosts (set_no_proxy): pattern syntax, dot-boundary rule, case-insensitivity, IP normalization via inet_pton, port-specific-entries unsupported, malformed entries dropped. - Read proxy settings from the environment (set_proxy_from_env): which variables are read, lowercase-only http_proxy with an inline httpoxy / CVE-2016-5385 explanation, threading caveat. --- docs-src/pages/en/cookbook/c16-proxy.md | 41 ++++++++++++++++++++++++- docs-src/pages/ja/cookbook/c16-proxy.md | 41 ++++++++++++++++++++++++- 2 files changed, 80 insertions(+), 2 deletions(-) diff --git a/docs-src/pages/en/cookbook/c16-proxy.md b/docs-src/pages/en/cookbook/c16-proxy.md index 5b193b3..c6fe7c4 100644 --- a/docs-src/pages/en/cookbook/c16-proxy.md +++ b/docs-src/pages/en/cookbook/c16-proxy.md @@ -49,4 +49,43 @@ cli.set_bearer_token_auth("api-token"); // for the end server `Proxy-Authorization` is sent to the proxy, `Authorization` to the end server. -> **Note:** cpp-httplib does not read `HTTP_PROXY` or `HTTPS_PROXY` environment variables automatically. If you want to honor them, read them in your application and pass the values to `set_proxy()`. +## Bypass the proxy for specific hosts + +You often want internal endpoints to skip the proxy. Configure a bypass list with `set_no_proxy()`. + +```cpp +cli.set_proxy("proxy.internal", 8080); +cli.set_no_proxy({"internal.corp", "10.0.0.0/8", "*.dev.local"}); +``` + +Each entry is one of: + +- `*` — bypass the proxy for all hosts +- a hostname suffix (e.g. `example.com`) — matches `example.com` itself and any subdomain (`foo.example.com`). A leading dot 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`) + +Hostname matching is case-insensitive and uses a dot-boundary rule, so an entry of `example.com` does **not** match `evilexample.com`. IP comparisons are normalized through `inet_pton`, so `127.0.0.1` cannot be bypassed via alternate string forms (e.g. `127.000.000.001`). When an entry matches, the `Proxy-Authorization` header is suppressed as well. + +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 + +Call `set_proxy_from_env()` at startup to pick up proxy configuration from 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 +- `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. diff --git a/docs-src/pages/ja/cookbook/c16-proxy.md b/docs-src/pages/ja/cookbook/c16-proxy.md index 296035e..a71ca28 100644 --- a/docs-src/pages/ja/cookbook/c16-proxy.md +++ b/docs-src/pages/ja/cookbook/c16-proxy.md @@ -49,4 +49,43 @@ cli.set_bearer_token_auth("api-token"); // エンドサーバー向け プロキシには`Proxy-Authorization`、エンドサーバーには`Authorization`ヘッダーが送られます。 -> **Note:** 環境変数の`HTTP_PROXY`や`HTTPS_PROXY`は自動的には読まれません。必要ならアプリケーション側で読み取って`set_proxy()`に渡してください。 +## 特定のホストだけプロキシをバイパスする + +社内エンドポイントなどはプロキシを経由させたくないことがあります。`set_no_proxy()`で除外リストを指定できます。 + +```cpp +cli.set_proxy("proxy.internal", 8080); +cli.set_no_proxy({"internal.corp", "10.0.0.0/8", "*.dev.local"}); +``` + +エントリは次のいずれかです。 + +- `*` — すべてのホストでバイパス +- ホスト名サフィックス(例: `example.com`)— `example.com`本体と任意のサブドメイン(`foo.example.com`)にマッチ。先頭にドットを付けても同じ意味です(`.example.com`)。 +- 単一のIPリテラル(例: `192.168.1.1`、`::1`) +- CIDRブロック(例: `10.0.0.0/8`、`fe80::/10`) + +ホスト名のマッチは大文字小文字を区別せず、ドット境界でしか一致しません。たとえば`example.com`というエントリは`evilexample.com`にはマッチしません。IPの比較は`inet_pton`で正規化されるので、`127.0.0.1`を`127.000.000.001`のような別表記でバイパスすることはできません。マッチした場合、`Proxy-Authorization`ヘッダーも自動的に外れます。 + +不正な書式のエントリは黙って捨てられます。`example.com:8080`のようなポート指定エントリはサポート外です(cpp-httplibの他のホストキーAPIもホスト名のみを扱う設計のため)。 + +## 環境変数からプロキシ設定を読み込む + +`set_proxy_from_env()`を呼ぶと、起動時の環境変数からプロキシ設定をまとめて取り込めます。 + +```cpp +httplib::Client cli("https://api.example.com"); +cli.set_proxy_from_env(); +``` + +読み込まれる変数: + +- `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`しているケースは未定義です。