我需要访问Facebook,但所有传出通信都在我们的服务器上被阻止,所以我必须使用代理。
我用以下代码初始化代理:
ProxySelector.setDefault(new ConfigurableProxySelector(mapping));
代理类型是HTTP,代理主机和端口正在工作(通过简单的wget测试确认)。
我正在尝试这样做:
HttpClient httpClient = new HttpClient();
HttpMethod method = new GetMethod("https://graph.facebook.com:443");
int status = httpClient.executeMethod(method);
现在,在我的类ConfigurableProxySelector中,我有select方法,我有断点:
public List<Proxy> select(URI uri) {
...
}
因此,使用HttpClient我发出一个请求,该请求应该被代理,并且代码在ConfigurableProxySelector中的select()方法中的断点处停止。
但奇怪的是,uri.scheme =“socket”和.toString()给出“socket://graph.facebook.com:443”而不是“https://graph.facebook.com:443”
因为ProxySelector的映射为“https://”而不是“socket://”,所以它找不到它,并以“Connection refused”结束。奇怪的是select()方法在执行以“Connection refused”结束之前被调用了4次。
任何帮助都将不胜感激。
答案 0 :(得分:4)
Apache HTTP Client 3.1本身不会支持从默认ProxySelector或用户实现返回的HTTP代理。
ProxySelector是一个服务类,它根据其方案为给定的URL选择并返回合适的代理。例如,http://somehost
的请求将尝试提供HTTP代理(如果已定义)。可以使用系统属性在运行时配置默认ProxySelector,例如http.proxyHost
和http.proxyPort
。
HTTPUrlConnection的一个实例将多次检查默认的ProxySelector:1st用于选择http
或https
,然后在构建原始tcp套接字时使用socket
方案。 SOCKS代理可用于代理原始tcp套接字,但通常不在企业环境中找到,因此原始tcp套接字通常不会接收代理。
HC 3.1 永远不会检查http
/ https
方案的默认ProxySelector 。但是,当它最终构建原始套接字时,它将在稍后检查socket
方案 - 这是您看到的请求。这意味着系统属性http.proxyHost
和http.proxyPort
无效。对于只有HTTP / HTTPS代理的大多数人来说,这显然不太理想。
要解决此问题,您有两种选择:在每个HC 3.1连接上定义代理或实现您自己的HC 3.1 HTTPConnectionManager。
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() );
答案 1 :(得分:2)
更改方案的不是ProxySelector,而是SocketFactory打开Socket。 如果SocketFactory为null,则默认情况下将创建SOCKS套接字,该套接字仅允许SOCKS代理。我对套接字一无所知,也无法告诉你是否有办法让它与HTTP代理一起工作。
但是使用其他方法可能会有所帮助,因为Apache HttpClient似乎有自己的配置代理的方式。
client.getHostConfiguration().setProxy(proxyHost, proxyPort);
if (proxyUser != null) {
client.getState().setProxyCredentials(new AuthScope(proxyHost, proxyPort),
new UsernamePasswordCredentials(proxyUser, proxyPassword));
}