配置 Apache HttpClient 通过代理/负载均衡器访问服务(覆盖 Host 标头) [英] Configuring Apache HttpClient to access service through proxy/load-balancer (overriding Host header)

查看:48
本文介绍了配置 Apache HttpClient 通过代理/负载均衡器访问服务(覆盖 Host 标头)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在让 Apache HttpClient 连接到虚拟化开发环境外部的服务时遇到问题.要访问互联网(例如 api.twitter.com),我需要调用本地 URL(例如 api.twitter.com.dev.mycompany.net),然后将请求转发到真实主机.

I am having a problem getting the Apache HttpClient to connect to a service external to my virtualised development environment. To access the internet (e.g. api.twitter.com) I need to call a local URL (e.g. api.twitter.com.dev.mycompany.net), which then forwards the request to real host.

问题是,无论我发送什么请求,我都会收到 404 Not Found 响应.

The problem is, that to whatever request I send, I get a 404 Not Found response.

我已尝试使用 wget 对其进行调试,但问题似乎在于,目标服务器通过在 Host 标头中同时使用请求 URL 和主机名来标识所需的资源.由于主机名不匹配,无法定位资源.

I have tried debugging it using wget, and it appears the problem is, that the destination server identifies the desired resource by using both the request URL and the hostname in the Host header. Since the hostname does not match, it is unable to locate the resource.

我(未成功)尝试通过在客户端上设置 http.virtual-host 参数来覆盖 Host 标头,如下所示:

I have (unsuccessfully) tried to override the Host header by setting the http.virtual-host parameter on the client like this:

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

技术细节:

  1. Client 在 RESTeasy 中作为执行器来调用 REST API.所以手动"设置虚拟主机(如 此处) 不是一种选择.

一切都是通过 HTTPS/SSL 完成的 - 我认为这并没有什么不同.

Everything is done via HTTPS/SSL - not that I think it makes a difference.

编辑 1: 使用 HttpHost 而不是 String 也没有达到预期的效果:

Edit 1: Using a HttpHost instead of a String does not have the desired effect either:

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: 进一步调查显示,需要在请求对象上设置该参数.以下是HttpClient设置虚拟主机的代码v. 4.2-aplha1:

Edit 2: Further investigation has revealed, that the parameter needs to be set on the request object. The following is the code v. 4.2-aplha1 of HttpClient setting the virtual host:

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' 的值是从请求参数中读取的.

paramsare the parameters passed from the client. But the value for 'virtualHost' is read from the request parameters.

因此,这将问题的性质更改为:如何在请求上设置 VIRTUAL_HOST 属性?

So this changes the nature of the question to: How do I set the VIRTUAL_HOST property on the requests?

推荐答案

ClientPNames.VIRTUAL_HOST 是覆盖 HTTP 请求中物理主机名的正确参数.我只建议在请求对象而不是客户端对象上设置此参数.如果这没有产生预期的效果,请发布会话的完整线路/上下文日志(请参阅 登录指南 以获取说明)此处或 HttpClient 用户列表.

ClientPNames.VIRTUAL_HOST is the right parameter for overriding physical host name in HTTP requests. I would just recommend setting this parameter on the request object instead of the client object. If that does not produce the desired effect please post the complete wire / context log of the session (see logging guide for instructions) either here or to the HttpClient user list.

跟进

好的.让我们拿一把更大的大锤.可以使用拦截器覆盖 Host 标头的内容.

OK. Let's take a larger sledge hammer. One can override content of the Host header using an interceptor.

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

可以使拦截器足够聪明,可以选择性地覆盖标头,仅针对特定主机.

One can make the interceptor clever enough to override the header selectively, only for specific hosts.

这篇关于配置 Apache HttpClient 通过代理/负载均衡器访问服务(覆盖 Host 标头)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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