ProxySelector将URL的方案从https://更改为socket:// [英] ProxySelector changes URL's scheme from https:// to socket://

查看:554
本文介绍了ProxySelector将URL的方案从https://更改为socket://的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要访问Facebook,但所有传出的通信都在我们的服务器上被阻止,因此我必须使用代理。

I need to access Facebook but all outgoing communication is blocked on our server so I have to use proxy.

我使用以下代码初始化代理:

I initialize proxies with:

ProxySelector.setDefault(new ConfigurableProxySelector(mapping));

代理类型是HTTP,代理主机和端口正常工作(通过简单的wget测试确认)。

Proxy type is HTTP, proxy host and port are working (confirmed by simple wget test).

我正在尝试这样做:

HttpClient httpClient = new HttpClient();
HttpMethod method = new GetMethod("https://graph.facebook.com:443");

int status = httpClient.executeMethod(method);

现在,在我的类ConfigurableProxySelector中,我有select方法,我有断点:

Now, in my class ConfigurableProxySelector I have select method on which I have breakpoint:

public List<Proxy> select(URI uri) {
...
}

所以,使用HttpClient的我作出请求,该请求应当被代理和代码停止在断点在ConfigurableProxySelector select()方法

So, using HttpClient I make an request, which should be proxied and code stops at breakpoint in select() method in ConfigurableProxySelector.

但令人奇怪的是,uri.scheme =插座和.toString()给出socket://graph.facebook.com:443而不是https://graph.facebook.com:443。

But what is strange is that uri.scheme = "socket" and .toString() gives "socket://graph.facebook.com:443" instead of "https://graph.facebook.com:443".

因为ProxySelector具有https://的映射而不是socket://的映射,所以它找不到它并以Connection refused结束。奇怪的是select()方法在执行结束之前调用了4次Connection refused。

Because ProxySelector have mapping for "https://" and not for "socket://", it does not find it and it ends with "Connection refused". What is strange is that select() method is called 4 times before execution ends with "Connection refused".

任何帮助都将不胜感激。

Any help would be appreciated.

推荐答案

Apache HTTP Client 3.1本身不会支持从默认ProxySelector或用户实现返回的HTTP代理。

Apache HTTP Client 3.1 will not natively honor HTTP Proxies returned from the default ProxySelector or user implementations.

ProxySelector是一个服务类,它根据其方案选择并返回给定URL的合适代理。例如,如果定义了一个HTTP代理,则 http:// somehost 的请求将尝试提供HTTP代理。可以使用系统属性在运行时配置默认的ProxySelector,例如 http.proxyHost http.proxyPort

ProxySelector is a service class which selects and returns a suitable Proxy for a given URL based on its scheme. For example, a request for http://somehost will try to provide an HTTP proxy if one is defined. The default ProxySelector can be configured at runtime using System Properties, such as http.proxyHost and http.proxyPort.

HttpURLConnection类的一个实例将检查对默认的ProxySelector多次:第一选择用于 http https ,然后在构建原始tcp套接字时,使用套接字计划。 SOCKS代理可用于代理原始tcp套接字,但通常不在企业环境中找到,因此原始tcp套接字通常不会接收代理。

An instance of HTTPUrlConnection will check against the default ProxySelector multiple times: 1st to select for http or https, then later when it builds the raw tcp socket, using the socket scheme. A SOCKS proxy could be used to proxy a raw tcp socket but are not often found in corporate environments, so a raw tcp socket will usually receive no proxy.

另一方面,HC 3.1 永远不会检查 http / <的默认ProxySelector code> https 计划。但是,当它最终构建原始套接字时,它将在稍后检查套接字方案 - 这是您看到的请求。这意味着系统属性 http.proxyHost http.proxyPort 无效。对于只有HTTP / HTTPS代理的大多数人来说,这显然不太理想。

HC 3.1, on the other hand, will never check the default ProxySelector for the http/https schemes. It will check, however, at a later points for the socket scheme when it eventually builds the raw socket - This is the request you are seeing. This means the System Properties http.proxyHost and http.proxyPort are ineffective. This is obviously not ideal for most people who only have an HTTP/HTTPS proxy.

要解决此问题,您有两种选择:在每个HC 3.1连接上定义代理或者实现你自己的HC 3.1 HTTPConnectionManager。

To work around this, you have two options: define a proxy on each HC 3.1 connection or implement your own HC 3.1 HTTPConnectionManager.

HTTPConnectionManager负责建立HC 3.1的连接客户端。

The HTTPConnectionManager is responsible for building connections for the HC 3.1 client.

默认的HC 3.1 HTTPConnectionManager可以扩展,以便在以与HTTPUrlConnection相同的方式构建请求时从ProxySelector(默认或自定义)中查找合适的代理作用:

The default HC 3.1 HTTPConnectionManager can be extended so that it looks for a suitable proxy from a ProxySelector (default or custom) when building the request in the same way HTTPUrlConnection does:

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客户端时,请使用你的新连接管理器:

Then, when you create an HC 3.1 client, use your new connection manager:

HttpClient client = new HttpClient(new MyHTTPConnectionManager() );

这篇关于ProxySelector将URL的方案从https://更改为socket://的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆