我需要访问Facebook,但所有传出通信在我们的服务器上被阻止,所以我必须使用代理。
我初始化代理:
ProxySelector.setDefault(new ConfigurableProxySelector(mapping));
代理类型为HTTP,代理主机和端口正常工作(通过简单的wget测试确认)
I'm try to do this:
HttpClient httpClient = new HttpClient();
HttpMethod method = new GetMethod("https://graph.facebook.com:443");
int status = httpClient.executeMethod(method);
现在,在我的类ConfigurableProxySelector我有选择方法上我有断点:
public List<Proxy> select(URI uri) {
...
}
所以,使用HttpClient我做一个请求,它应该被代理和代码停止在断点中选择()方法在ConfigurableProxySelector。
但是奇怪的是uri。scheme = "socket"并且. tostring()给出"socket://graph.facebook.com:443"而不是"https://graph.facebook.com:443"。
因为ProxySelector有"https://"的映射,而不是"socket://",它找不到它,它以"拒绝连接"结束。奇怪的是,select()方法被调用了4次,直到执行结束时显示"Connection refused"。
Apache HTTP Client 3.1将不会本地尊重从默认ProxySelector或用户实现返回的HTTP代理。
ProxySelector快速总结
ProxySelector是一个服务类,它根据方案为给定的URL选择并返回一个合适的代理。例如,如果定义了HTTP代理,则对http://somehost
的请求将尝试提供HTTP代理。默认的ProxySelector可以在运行时通过System Properties进行配置,例如http.proxyHost
和http.proxyPort
。
HTTPUrlConnection
HTTPUrlConnection的实例将多次检查默认ProxySelector:首先选择http
或https
,然后当它构建原始tcp套接字时,使用socket
方案。SOCKS代理可用于代理原始tcp套接字,但在企业环境中并不常见,因此原始tcp套接字通常不会接收代理。
HTTP Client 3.1
另一方面,HC 3.1将永远不会检查http
/https
方案的默认ProxySelector。但是,当它最终构建原始套接字时,它将稍后检查socket
方案—这就是您所看到的请求。这意味着系统属性http.proxyHost
和http.proxyPort
无效。对于只有HTTP/HTTPS代理的大多数人来说,这显然不是理想的。
HTTPConnectionManager
HTTPConnectionManager负责为HC 3.1客户端构建连接。
默认的HC 3.1 HTTPConnectionManager可以扩展,以便它在构建请求时从ProxySelector(默认或自定义)中寻找合适的代理,与HTTPUrlConnection相同:
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() );
改变方案的不是ProxySelector,而是打开Socket的SocketFactory。如果SocketFactory为空,默认情况下将创建一个SOCKS套接字,它只允许SOCKS代理。我对套接字一无所知,也不能告诉你是否有办法让它与HTTP代理一起工作。
但是使用另一种方法可能会有所帮助,因为Apache HttpClient似乎有自己的方式来配置代理。
client.getHostConfiguration().setProxy(proxyHost, proxyPort);
if (proxyUser != null) {
client.getState().setProxyCredentials(new AuthScope(proxyHost, proxyPort),
new UsernamePasswordCredentials(proxyUser, proxyPassword));
}