我正在使用 httpclient 4.2.5 发出还必须处理重定向的 http 请求。 这是一个理解上下文的小例子:
- A向B发送http请求(使用httpclient 4.2.5)
- B 向 A 发送 302 重定向(包含到 C 的 url)
- A 跟随重定向到 C
- C 检索请求 URL 并用它做一些工作
如果 C 通过 request.getRequestURL()
(HttpServlet API)解析请求 URL,它包含例如来自第 1 步的原始请求的主机和端口,这是错误的。
问题存在于第 2 步,其中 httpclient 处理重定向。它只是将所有 header 从原始请求(第 1 步)复制到当前请求(第 3 步)。我已经通过 grepcode 查看了负责的代码:
DefaultRequestDirector
HttpUriRequest redirect = redirectStrategy.getRedirect(request, response, context);
HttpRequest orig = request.getOriginal();
redirect.setHeaders(orig.getAllHeaders());
我不太明白为什么要把原请求的所有header都复制到当前请求中。
例如。使用 cURL 进行简单测试是按预期进行的,C 将收到正确的主机和端口。
实现我自己的重定向策略无济于事,因为在它之后复制了原始 header 。
最佳答案
尝试使用 HttpClient
从 bitbucket 的下载部分下载文件时,我遇到了同样的问题。在第一个请求之后,bitbucket 将重定向发送到 CDN,如果设置了 Authorization
header ,CDN 就会提示。
我通过更改 DefaultRedirectStrategy.getRedirect()
方法来返回不允许设置 Authorization
header 的重定向对象来解决它。
我使用 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"))
}
}
}
}
})
关于java - header 值在 HTTPClient 中重定向时被覆盖,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17970633/