Apache HTTP Client 3.1 本身不会支持从默认 ProxySelector 或用户实现返回的 HTTP 代理。
ProxySelector 快速总结
ProxySelector 是一个服务类,它根据其方案为给定 URL 选择并返回合适的代理。例如,请求http://somehost
如果已定义,将尝试提供 HTTP 代理。默认的ProxySelector可以在运行时使用系统属性进行配置,例如http.proxyHost
and http.proxyPort
.
HTTPUrl连接
HTTPUrlConnection 的实例将多次检查默认的 ProxySelector:第一次选择http
or https
,然后当它构建原始 tcp 套接字时,使用socket
方案。 SOCKS 代理可用于代理原始 tcp 套接字,但在企业环境中并不常见,因此原始 tcp 套接字通常不会接收代理。
HTTP 客户端 3.1
另一方面,HC 3.1 将永远不要检查默认的 ProxySelectorhttp
/https
schemes。不过,稍后它会检查socket
最终构建原始套接字时的方案 - 这是您看到的请求。这意味着系统属性http.proxyHost
and http.proxyPort
是无效的。对于大多数只有 HTTP/HTTPS 代理的人来说,这显然并不理想。
要解决此问题,您有两个选择:在每个 HC 3.1 连接上定义代理或实施您自己的 HC 3.1 HTTPConnectionManager。
HTTP连接管理器
HTTPConnectionManager 负责为 HC 3.1 客户端建立连接。
可以扩展默认的 HC 3.1 HTTPConnectionManager,以便在以与 HTTPUrlConnection 相同的方式构建请求时从 ProxySelector(默认或自定义)查找合适的代理:
public class MyHTTPConnectionManager extends SimpleHttpConnectionManager {
@Override
public HttpConnection getConnectionWithTimeout(
HostConfiguration hostConfiguration, long timeout) {
HttpConnection hc = super.getConnectionWithTimeout(hostConfiguration, timeout);
try {
URI uri = new URI( hostConfiguration.getHostURL());
List<Proxy> hostProxies = ProxySelector.getDefault().select(uri);
Proxy Proxy = hostProxies.get(0);
InetSocketAddress sa = (InetSocketAddress) Proxy.address();
hc.setProxyHost(sa.getHostName());
hc.setProxyPort(sa.getPort());
} catch (URISyntaxException e) {
return hc;
}
return hc;
}
}
然后,当您创建 HC 3.1 客户端时,使用新的连接管理器:
HttpClient client = new HttpClient(new MyHTTPConnectionManager() );