我需要访问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.proxyHosthttp.proxyPort)配置默认的ProxySelector。

HTTPUrlConnection

一个HTTPUrlConnection实例将多次检查默认的ProxySelector:第一个选择httphttps,然后稍后使用socket方案构建原始tcp套接字。 SOCKS代理可用于代理原始tcp套接字,但在公司环境中并不常见,因此原始tcp套接字通常将不接收任何代理。

HTTP客户端3.1

另一方面,HC 3.1将从不检查http/https方案的默认ProxySelector。但是,在最终构建原始套接字时,它将在以后检查socket方案-这是您正在看到的请求。这意味着系统属性http.proxyHosthttp.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/

10-09 09:36