ProxySelector меняет схему URL с https: // на сокет: // - PullRequest
2 голосов
/ 14 сентября 2011

Мне нужен доступ к 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 у меня есть метод выбора, для которого у меня есть точка останова:

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

Итак, используя HttpClient, я делаю запрос, который следует проксировать, и код останавливается на точке останова в методе select () в ConfigurableProxySelector.

Но странно то, что uri.scheme = "socket" и .toString () выдают "socket: //graph.facebook.com: 443" вместо "https://graph.facebook.com:443".

Поскольку ProxySelector имеет отображение для «https://", а не для« socket: // », он не находит его и заканчивается« Отказано в соединении ». Странно то, что метод select () вызывается 4 раза раньше выполнение заканчивается «Отказ в соединении».

Любая помощь будет оценена.

Ответы [ 2 ]

4 голосов
/ 28 января 2013

Apache HTTP Client 3.1 изначально не будет учитывать прокси-серверы HTTP, возвращаемые из реализации ProxySelector по умолчанию или пользовательских реализаций.

Краткое описание ProxySelector

ProxySelector - это класс службы, который выбирает и возвращает подходящий проксидля данного URL на основе его схемы.Например, запрос на http://somehost попытается предоставить HTTP-прокси, если он определен.ProxySelector по умолчанию можно настроить во время выполнения с помощью системных свойств, таких как http.proxyHost и http.proxyPort.

HTTPUrlConnection

Экземпляр HTTPUrlConnection будет несколько раз проверять ProxySelector по умолчанию: сначала выберите значение http или https, затем позже, когда он создаст необработанный сокет tcp, используяsocket схема.Прокси-сервер SOCKS можно использовать для прокси-сервера необработанного tcp-сокета, но его не часто можно встретить в корпоративных средах, поэтому необработанный tcp-сокет обычно не получает прокси.

HTTP-клиент 3.1

HC 3.1,с другой стороны, никогда не будет проверять ProxySelector по умолчанию для http / https схем .Однако в дальнейшем он проверит схему socket, когда в конечном итоге создаст необработанный сокет - это запрос, который вы видите.Это означает, что системные свойства http.proxyHost и http.proxyPort неэффективны.Очевидно, что это не идеально для большинства людей, которые имеют только прокси HTTP / HTTPS.

Чтобы обойти это, у вас есть два варианта: определить прокси для каждого соединения HC 3.1 или реализовать свой собственный HTTP 3.1 HTTPConnectionManager HC.

HTTPConnectionManager

HTTPConnectionManager отвечает за построение соединений для клиента HC 3.1.

Стандартный HTTP HCConnectionManager HC 3.1 может быть расширен, так что он ищет подходящий прокси-сервер из ProxySelector(по умолчанию или пользовательский) при построении запроса таким же образом, как HTTPUrlConnection:

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() );
2 голосов
/ 28 сентября 2011

Схему меняет не ProxySelector, а SocketFactory, открывающая Socket.Если SocketFactory имеет значение null, сокет SOCKS будет создан по умолчанию, который разрешает только прокси SOCKS.Я ничего не знаю о Sockets и не могу сказать вам, есть ли способ заставить его работать с HTTP прокси.

Но использование другого подхода может помочь, так как Apache HttpClient, похоже, имеет свой собственный способ настройки прокси.

client.getHostConfiguration().setProxy(proxyHost, proxyPort);

if (proxyUser != null) {
    client.getState().setProxyCredentials(new AuthScope(proxyHost, proxyPort), 
        new UsernamePasswordCredentials(proxyUser, proxyPassword));
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...