1

我正在使用 httpclient 4.2.5 发出必须处理重定向的 http 请求。这里有一个小例子来理解上下文:

  1. A 向 B 发送 http 请求(使用 httpclient 4.2.5)
  2. B 将 302 重定向(包含到 C 的 URL)发送回 A
  3. A跟随重定向到C
  4. C 检索请求 URL 并使用它做一些工作

如果 C 通过 (HttpServlet API) 解析请求 URL,request.getRequestURL()它包含例如来自步骤 1 的原始请求的主机和端口,这是错误的。

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

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

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

实施我自己的重定向策略并没有帮助,因为在它之后复制了原始标头。

4

2 回答 2

4

尝试从 bitbucket 的下载部分使用HttpClient. 在第一个请求之后,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"))
        }
      }
    }
  }
})
于 2014-04-03T13:28:22.183 回答
0

请注意返回由调用者显式添加到消息orig.getAllHeaders()中的标头数组。上面发布的代码不会复制由诸如、等自动生成的请求标头。DefaultRequestDirectorHttpClientHostContent-LengthTransfer-Encoding

您发布了会话的电报日志,显示了该问题,我可能能够说明为什么重定向无法按预期工作。

于 2013-07-31T13:31:52.370 回答