java - 配置 Apache HttpClient 以通过代理/负载平衡器访问服务(覆盖主机 header )

标签 java http-headers apache-httpclient-4.x

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

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

我已经尝试使用 wget 对其进行调试,问题似乎在于,目标服务器通过使用请求 URL 和主机 header 中的主机名来识别所需的资源。由于主机名不匹配,无法找到资源。

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

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

技术细节:

  1. 客户端在 RESTeasy 中用作执行器来调用 REST API。因此,“手动”设置虚拟主机(如 here 所述)不是一种选择。

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

编辑 2: 进一步调查显示,需要在请求对象上设置参数。以下是HttpClient设置虚拟主机v.4.2-aplha1的代码:

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 属性?

最佳答案

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


跟进

好的。让我们拿一个更大的大锤。可以使用拦截器覆盖 Host header 的内容。

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

可以使拦截器足够聪明,仅针对特定主机有选择地覆盖 header 。

关于java - 配置 Apache HttpClient 以通过代理/负载平衡器访问服务(覆盖主机 header ),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9499697/

相关文章:

java - HTTPClient 4.1 中带有文件和字符串的多部分 POST

java - Guice 中范围注释和范围实例之间的区别

java - 在Struts2应用程序上动态创建线程

javascript - 如何仅获取(使用 Fetch API)Javascript 中的 header ,而不是全部内容?

javascript - Google 分析代码和带有 php header 位置的重定向

RestEasy客户端: Invalid use of BasicClientConnManager: connection still allocated

java - 使用 & (bg) 运行时,Linux csh 脚本将暂停(tty 输出)

java - 当在复合键中使用时,JPA AttributeConverter 在 Spring-data/hibernate 查询中不被接受

java - 无法将 PDF 文件作为二进制数据获取

java - 在 Java 中从特定 IP 生成 HttpRequest