Apache HttpClient 4 のアプリケーションでは、HTTPS の宛先であってもすべての接続が TLS で始まるわけではありません。通常の HTTP プロキシには平文の接続で到達し、その後に CONNECT がトンネルを開き、宛先に向けて TLS が重ねられます。

カスタムの接続マネージャが https だけを登録していると、最初のプロキシ経由のホップが UnsupportedSchemeException: http protocol is not supported で失敗することがあります。

4.5 API では、そのマネージャを構築するときに両方のファクトリを含めます:

var registry = RegistryBuilder.<ConnectionSocketFactory>create()
    .register("http", PlainConnectionSocketFactory.getSocketFactory())
    .register("https", tlsFactory)
    .build();

var manager = new PoolingHttpClientConnectionManager(registry);
var client = HttpClients.custom()
    .setConnectionManager(manager)
    .setProxy(new HttpHost("proxy.example.net", 8080, "http"))
    .build();

tlsFactory はアプリケーションが既に持つ SSLConnectionSocketFactory で、意図した信頼とホスト名の検証を伴います。示されている型は Apache 4 の org.apache.http パッケージのものです。この断片は Java のローカル変数型推論を前提としており、古い Java ソースでは明示的な型を使えます。

修正したマネージャは、実際にリクエストに使われるクライアントに取り付けてください。プロキシ認証のない許可された公開 HTTPS リクエストでは、HTTP プロキシ一覧の HTTP エントリが HttpHost のプロキシアドレスを埋められます。別のビルダを設定しても、既に構築済みのクライアントは更新されません。

ビルダの所有権も確認してください。HttpClientBuilder の文書は、明示的に渡した接続マネージャが個別の SSL 設定入力より優先され得ると述べています。後から setSSLContext を呼べば内部が置き換わると考えず、必要なファクトリをマネージャのレジストリに入れてください。

この診断はローカルのスキームレジストリに関するものです。プロキシ認証の要求や拒否された宛先は、より後の別の結果です。それらの応答を調べる間は、両方のファクトリ登録を保持してください。

関連記事