Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
6b649b3
Route proxy-enabled checks through is_proxy_enabled_for_host helper
yhirose May 8, 2026
91f38e6
Add detail::parse_proxy_url with control-char and scheme validation
yhirose May 8, 2026
7001ceb
Add NO_PROXY parsing and matching helpers in detail namespace
yhirose May 8, 2026
d38753d
Add Client::set_no_proxy and wire NO_PROXY into proxy decision
yhirose May 8, 2026
15d0492
Add Client::set_proxy_from_env with httpoxy mitigation
yhirose May 8, 2026
cbd0ec5
Add NO_PROXY behavior tests
yhirose May 8, 2026
60cb6f5
Document set_no_proxy and set_proxy_from_env in README
yhirose May 8, 2026
8c20221
Document NO_PROXY and set_proxy_from_env in cookbook c16-proxy
yhirose May 8, 2026
1d462ec
Simplify NO_PROXY implementation per review
yhirose May 8, 2026
73115a2
Inline proxy URL parsing and env reading; drop intermediate structs
yhirose May 10, 2026
d0f1750
Trim doc comments to match the rest of httplib.h
yhirose May 10, 2026
12cf796
Add NO_PROXY tests covering edge cases found during PR review
yhirose May 14, 2026
b66fe35
Unify IPv4/IPv6 CIDR matching into a single byte-buffer helper
yhirose May 14, 2026
f302e15
Drop set_proxy_from_env per #2446 discussion
yhirose May 25, 2026
7534d8f
docs: blend NO_PROXY env-var note into c16-proxy cookbook style
yhirose May 25, 2026
70295a9
Skip digest 407 retry when target is bypassed by NO_PROXY
yhirose May 25, 2026
ff9740f
Make set_no_proxy safe across redirects and keep-alive
yhirose May 25, 2026
e2ae085
Tighten NO_PROXY entry parsing
yhirose May 25, 2026
e482dfa
Refactor: introduce disconnect() and remove invalidate_keep_alive_socket
yhirose May 25, 2026
629d46a
Fix MultiHopRedirect test on Windows; trim NoProxyTest comments
yhirose May 25, 2026
9901a4e
Consolidate NoProxyTest server boilerplate; drop hardcoded sentinel p…
yhirose May 25, 2026
2ad8773
Trim README NO_PROXY section to match surrounding granularity
yhirose May 25, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -1181,6 +1181,17 @@ cli.set_proxy_bearer_token_auth("pass");
> [!NOTE]
> OpenSSL is required for Digest Authentication.

#### Bypass the proxy for specific hosts (`NO_PROXY`)

```cpp
cli.set_no_proxy({"internal.corp", "10.0.0.0/8", "*.dev.local"});
```

Each pattern is `*`, a hostname suffix, an IP literal, or a CIDR block.
Hostname matching is case-insensitive with a dot-boundary rule. See the
[NO_PROXY cookbook](https://yhirose.github.io/cpp-httplib/en/cookbook/c16-proxy)
for details and for reading the variable from the environment.

### Range

```cpp
Expand Down
37 changes: 36 additions & 1 deletion docs-src/pages/en/cookbook/c16-proxy.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,4 +49,39 @@ 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

cpp-httplib doesn't touch `HTTP_PROXY` / `HTTPS_PROXY` / `NO_PROXY` on its own — the config API is always explicit, the same way `set_ca_cert_path()` is. If you'd like that behavior, read the variables in your application and feed them to `set_proxy()` and `set_no_proxy()`.

```cpp
if (const char *v = std::getenv("no_proxy")) {
std::vector<std::string> patterns;
std::stringstream ss(v);
for (std::string item; std::getline(ss, item, ',');) {
if (!item.empty()) { patterns.push_back(item); }
}
cli.set_no_proxy(patterns);
}
```

If you also read `HTTP_PROXY` yourself, honor 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 don't begin with `HTTP_`.
37 changes: 36 additions & 1 deletion docs-src/pages/ja/cookbook/c16-proxy.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,4 +49,39 @@ 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もホスト名のみを扱う設計のため)。

## 環境変数からプロキシ設定を読み込む

cpp-httplib本体は`HTTP_PROXY` / `HTTPS_PROXY` / `NO_PROXY`を読みません。`set_ca_cert_path()`と同じで、設定APIは常に明示的にしています。環境変数を反映させたい場合は、アプリ側で読んで`set_proxy()`や`set_no_proxy()`に渡してください。

```cpp
if (const char *v = std::getenv("no_proxy")) {
std::vector<std::string> patterns;
std::stringstream ss(v);
for (std::string item; std::getline(ss, item, ',');) {
if (!item.empty()) { patterns.push_back(item); }
}
cli.set_no_proxy(patterns);
}
```

`HTTP_PROXY`も自分で読むなら、小文字の`http_proxy`だけを採用してください。大文字の方はCGI/FastCGI環境で`Proxy:`リクエストヘッダーから汚染される可能性があります([CVE-2016-5385 / "httpoxy"](https://httpoxy.org/))。`HTTPS_PROXY`と`NO_PROXY`は名前が`HTTP_`で始まらないので、どちらの大文字小文字でも安全です。
Loading
Loading