在HTTPClient中重定向时覆盖的标头值

时间:2013-07-31 12:38:22

标签: java apache-httpclient-4.x

我正在使用httpclient 4.2.5来制作必须处理重定向的http请求。 以下是了解上下文的一个小例子:

  1. A发送http请求(使用httpclient 4.2.5)到B
  2. B将302重定向(包含url到C)发送回A
  3. A跟随重定向到C
  4. C检索请求URL并使用它做一些工作
  5. 如果C通过request.getRequestURL()(HttpServlet API)解析请求URL,它包含例如来自步骤1的原始请求的主机和端口,这是错误的。

    问题存在于步骤2中,其中httpclient处理重定向。它只是将原始请求(步骤1)中的所有标题复制到当前请求(步骤3)。我已经看过负责任的代码,通过grepcode:
    DefaultRequestDirector

    HttpUriRequest redirect = redirectStrategy.getRedirect(request, response, context);
    HttpRequest orig = request.getOriginal();
    redirect.setHeaders(orig.getAllHeaders());
    

    我真的不明白为什么原始请求的所有标题都被复制到当前请求中 例如。使用cURL进行简单测试就是按预期进行,C将接收正确的主机和端口。

    实现我自己的重定向策略没有用,因为原始标题会在它之后复制。

2 个答案:

答案 0 :(得分:3)

尝试使用HttpClient从bitbucket的下载部分下载文件时遇到了同样的问题。在第一个请求后,bitbucket向CDN发送重定向,然后在设置Authorization标头时发出抱怨。

我通过更改DefaultRedirectStrategy.getRedirect()方法来处理它,以返回不允许设置Authorization标头的重定向对象。

我使用Scala,所以这里是代码:

val http = new DefaultHttpClient()
http.setRedirectStrategy(new DefaultRedirectStrategy() {
  override def getRedirect(
    request: HttpRequest, response: HttpResponse, context: HttpContext
  ): HttpRequestBase = {
    val uri: URI = getLocationURI(request, response, context)
    val method: String = request.getRequestLine.getMethod
    if (method.equalsIgnoreCase(HttpHead.METHOD_NAME)) {
      new HttpHead(uri) {
        override def setHeaders(headers: Array[Header]) {
          super.setHeaders(headers.filterNot(_.getName == "Authorization"))
        }
      }
    }
    else {
      new HttpGet(uri) {
        override def setHeaders(headers: Array[Header]) {
          super.setHeaders(headers.filterNot(_.getName == "Authorization"))
        }
      }
    }
  }
})

答案 1 :(得分:0)

请注意orig.getAllHeaders()会返回调用者添加到邮件中的明确标题数组。上面发布的DefaultRequestDirector代码会HttpClientHostContent-Length自动生成 not 自动生成的复制请求标头等等。

您发布会话的有线日志,显示问题我可能会告诉您为什么重定向无法按预期工作。