Files
cpp-httplib/docs-src/pages/ja/cookbook/c16-proxy.md
yhirose bef278e0d2 Fix docs pages that no longer match the code
Samples that did not compile or run as shown:
- res.user_data.get<T>() inside a generic lambda needs the `template`
  keyword; use explicit parameter types (tour 09, cookbook s15).
- listen() on a Unix domain socket fails with port 0 (tour 09, s22).
- "*.dev.local" is not a NO_PROXY pattern (c16).
- ssl_backend_error() holds a verify result, not an ERR_get_error()
  value, after a verification failure; decode each with the matching
  OpenSSL function (c18).
- The content provider's `length` is everything that remains, so the
  sample read the whole file in one call (s05).

Statements corrected:
- Client keep-alive is off by default; c14 is rewritten around
  set_keep_alive(true).
- Mounted files are looked up before GET handlers (tour 04, s04).
- Params keep insertion order, and to_string(Error::Connection) reads
  "Could not establish connection" (tour 02).
- A chunked provider ends with sink.done(), and post_routing_handler
  runs before the response is sent (tour 09).
- Timeouts surface as Error::Read; Error::Timeout comes from the stream
  API (c17). The max timeout cuts off the wait for the response only
  (c13). The progress callback needs Content-Length (c11).
- Encoding selection follows q-values, then Brotli, gzip, Zstd (s08),
  and the client compresses with the first of those it was built with
  (c15).
- stop() cuts a provider-driven response short (s19); a rejected
  content_reader already gets 400 or 413 (s07); user_data values must be
  copyable (s12); Client accepts a client certificate too (t04);
  on_message() is the fallback for every unhandled event and 204/403/404
  end reconnection (e04); the pong timeout takes two to three intervals
  and ends a waiting read() (w02).

In the LLM app tutorial, an uncaught exception does not crash the
server, so say what it does instead. Drop the server and client timeout
settings whose stated purpose, covering inference and download time,
they do not serve: those timeouts bound a single socket wait. Update
the llama.cpp server layout in chapter 7.
2026-10-08 20:39:13 -04:00

4.1 KiB
Raw Blame History

title, order, status
title order status
C16. プロキシを経由してリクエストを送る 16 draft

社内ネットワークや特定の経路を通したい場合、HTTPプロキシを経由してリクエストを送れます。set_proxy()でプロキシのホストとポートを指定するだけです。

基本の使い方

httplib::Client cli("https://api.example.com");
cli.set_proxy("proxy.internal", 8080);

auto res = cli.Get("/users");

プロキシ経由でリクエストが送られます。HTTPSの場合はCONNECTメソッドでトンネルが張られるので、cpp-httplib側で特別な設定は要りません。

プロキシに認証を設定する

プロキシ自体が認証を要求する場合は、set_proxy_basic_auth()やset_proxy_bearer_token_auth()を使います。

cli.set_proxy("proxy.internal", 8080);
cli.set_proxy_basic_auth("user", "password");
cli.set_proxy_bearer_token_auth("token");

OpenSSL(または他のTLSバックエンド)付きでビルドしていれば、Digest認証も使えます。

cli.set_proxy_digest_auth("user", "password");

エンドのサーバー認証と組み合わせる

プロキシ認証と、エンドサーバーへの認証(C05. Basic認証を使うやC06. BearerトークンでAPIを呼ぶ)は別物です。両方が必要なら、両方設定します。

cli.set_proxy("proxy.internal", 8080);
cli.set_proxy_basic_auth("proxy-user", "proxy-pass");

cli.set_bearer_token_auth("api-token"); // エンドサーバー向け

プロキシにはProxy-Authorization、エンドサーバーにはAuthorizationヘッダーが送られます。

特定のホストだけプロキシをバイパスする

社内エンドポイントなどはプロキシを経由させたくないことがあります。set_no_proxy()で除外リストを指定できます。

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()に渡してください。

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_PROXYとNO_PROXYは名前がHTTP_で始まらないので、どちらの大文字小文字でも安全です。