我需要访问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://”的,所以找不到它,并且以“拒绝连接”结尾。奇怪的是,在执行以“拒绝连接”结束之前,select()方法被调用了4次。
任何帮助,将不胜感激。
最佳答案
Apache HTTP Client 3.1本身不会接受默认ProxySelector或用户实现返回的HTTP代理。
ProxySelector快速摘要
ProxySelector是一个服务类,它根据其方案为给定的URL选择并返回合适的Proxy。例如,如果定义了http://somehost
的请求,它将尝试提供HTTP代理。可以在运行时使用系统属性(例如http.proxyHost
和http.proxyPort
)配置默认的ProxySelector。
HTTPUrlConnection
一个HTTPUrlConnection实例将多次检查默认的ProxySelector:第一个选择http
或https
,然后稍后使用socket
方案构建原始tcp套接字。 SOCKS代理可用于代理原始tcp套接字,但在公司环境中并不常见,因此原始tcp套接字通常将不接收任何代理。
HTTP客户端3.1
另一方面,HC 3.1将从不检查http
/https
方案的默认ProxySelector。但是,在最终构建原始套接字时,它将在以后检查socket
方案-这是您正在看到的请求。这意味着系统属性http.proxyHost
和http.proxyPort
无效。对于大多数只有HTTP/HTTPS代理的人来说,这显然不是理想的选择。
要解决此问题,您有两个选择:在每个HC 3.1连接上定义一个代理或实现自己的HC 3.1 HTTPConnectionManager。
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() );
关于java - ProxySelector从https ://to socket://更改URL的方案,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/7413552/