HttpClient 4 代理错误:不支持 http 协议
当 HTTPS 路由先连接 HTTP 代理时,请在自定义 Apache HttpClient 4 注册表中保留普通 HTTP 工厂。
在 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 的代理地址。配置另一个 builder 不会更新已经构建的客户端。
还要检查 builder 的归属:HttpClientBuilder 的文档说明,显式提供的连接管理器可能覆盖其单独的 SSL 配置输入。应把所需的工厂放进管理器的注册表,而不是假定之后调用 setSSLContext 会替换其内部实现。
这一诊断针对本地方案注册表。代理认证质询或目标被拒绝是更晚出现的不同结果。调查这些响应时,请保留两个工厂注册。