Настройка Apache HttpClient для доступа к сервису через прокси / балансировщик нагрузки (переопределяющий заголовок хоста) - PullRequest
3 голосов
/ 29 февраля 2012

У меня проблема с подключением Apache HttpClient к сервису, внешнему по отношению к моей виртуализированной среде разработки.Чтобы получить доступ к Интернету (например, api.twitter.com), мне нужно позвонить по локальному URL (например, api.twitter.com.dev.mycompany.net), который затем перенаправит запрос на реальный хост.

Проблема в том, что на любой отправленный мной запрос я получаю ответ 404. Не найдено.

Я попытался отладить его с помощью wget, и проблема заключается в том, что сервер назначенияидентифицирует нужный ресурс, используя URL-адрес запроса и имя хоста в заголовке хоста.Поскольку имя хоста не совпадает, он не может найти ресурс.

Я (безуспешно) попытался переопределить заголовок хоста, установив параметр http.virtual-host на клиенте следующим образом:

HttpClient client = new DefaultHttpClient();
if (envType.isWithProxy()) {
    client.getParams().setParameter(ClientPNames.VIRTUAL_HOST, "api.twitter.com");
}

Технические подробности:

  1. Клиент используется в качестве исполнителя в RESTeasy для вызова REST API.Поэтому «ручная» настройка виртуального хоста (как описано здесь ) не является опцией.

  2. Все делается через HTTPS / SSL - я не думаю, что это имеет значение.

Редактировать 1: Использование HttpHost вместо String также не дает желаемого эффекта:

HttpClient client = new DefaultHttpClient();
if (envType.isWithProxy()) {
    HttpHost realHost = new HttpHost("api.twitter.com", port, scheme);
    client.getParams().setParameter(ClientPNames.VIRTUAL_HOST, realHost);
}

Edit 2: Дальнейшее исследование показало, что параметр должен быть установлен в объекте запроса.Ниже приведен код v. 4.2-aplha1 HttpClient, устанавливающий виртуальный хост:

HttpRequest orig = request;
RequestWrapper origWrapper = wrapRequest(orig);
origWrapper.setParams(params);
HttpRoute origRoute = determineRoute(target, origWrapper, context);

virtualHost = (HttpHost) orig.getParams().getParameter(
            ClientPNames.VIRTUAL_HOST);

params - это параметры, передаваемые клиентом.Но значение «virtualHost» читается из параметров запроса.

Таким образом, это меняет природу вопроса на: Как установить свойство VIRTUAL_HOST для запросов?

1 Ответ

3 голосов
/ 29 февраля 2012

ClientPNames.VIRTUAL_HOST - это правильный параметр для переопределения физического имени хоста в HTTP-запросах. Я бы просто рекомендовал установить этот параметр в объекте запроса вместо объекта клиента. Если это не дает желаемого эффекта, пожалуйста, опубликуйте полный проводной / контекстный журнал сеанса (см. руководство по ведению журнала для инструкций) здесь или в списке пользователей HttpClient.


Последующий

OK. Давайте возьмем большую кувалду. Можно переопределить содержимое заголовка Host, используя перехватчик.

DefaultHttpClient client = new DefaultHttpClient();
client.addRequestInterceptor(new HttpRequestInterceptor() {

    public void process(
            final HttpRequest request, 
            final HttpContext context) throws HttpException, IOException {
        request.setHeader(HTTP.TARGET_HOST, "www.whatever.com");
    }
});

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

...