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

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

问题描述

我在使用Apache HttpClient连接到虚拟化开发环境外部的服务时遇到问题。
要访问互联网(例如api.twitter.com),我需要拨打本地网址(例如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.

I尝试使用wget进行调试,看来问题是,目标服务器通过在主机头中同时使用请求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. 客户端在RESTeasy中用作执行器来调用REST API。因此,手动设置虚拟主机(如所述这里)不是一个选项。

一切都是通过HTTPS / SSL完成的 - 不是我觉得它有所作为。

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

编辑1:使用HttpHost代替字符串也不具备所需的效果:

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

编辑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.

关注-up

好的。我们来拿一把更大的大锤。可以使用拦截器覆盖主机标头的内容。

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通过代理/负载均衡器访问服务(覆盖主机头)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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