ProxySelector changes URL's scheme from https:// to socket://

前端 未结 2 1005
刺人心
刺人心 2021-01-15 09:03

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.se         


        
2条回答
  •  孤城傲影
    2021-01-15 09:37

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

    Quick Summary of ProxySelector

    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

    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.

    HTTP Client 3.1

    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.

    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

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

    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 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;
    }
    }
    

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

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

提交回复
热议问题