首页 > 网站 > Apache > 正文

Apache HttpClient中循环重定向的bug详解

2024-08-27 18:22:34
字体:
来源:转载
供稿:网友

最近在使用Apache HttpClient4.x时发现如果出现循环重定向的话就会出现bug问题了,这样导致服务器无法正常访问,会一直跳来跳去了,下面我来给大家介绍解决此问题的方法.

在Apache HttpClient 4.0里有个循环重定向的bug,当服务器试图正常的从域名A跳转到B的时候就会发生,我是在 Vevb.com 跳 www.Vevb.com 的时候发现的,换过最新版也发现还是有这个问题.

跟踪了DefaultRequestDirector.java之后发现,它在内部创建了一个HttpRedirect对象来处理重定向,这个对象会重用你之前的HttpGet对象里的HTTP 头,导致这个bug的根源在于,连Host头也用了,这表示重定向到的新域名如果和老域名如果是同一组集群,那么服务器会试图重新发一个重定向请求,这样就造成了HttpClient抛出CircularRedirectException.

我是派生了DefaultRequestDirector类来改掉这个问题,代码如下:

  1. public class RedirectRequestDirector extends DefaultRequestDirector 
  2.     RedirectRequestDirector( 
  3.             final HttpRequestExecutor requestExec, 
  4.             final ClientConnectionManager conman, 
  5.             final ConnectionReuseStrategy reustrat, 
  6.             final ConnectionKeepAliveStrategy kastrat, 
  7.             final HttpRoutePlanner rouplan, 
  8.             final HttpProcessor httpProcessor, 
  9.             final HttpRequestRetryHandler retryHandler, 
  10.             final RedirectHandler redirectHandler, 
  11.             final AuthenticationHandler targetAuthHandler, 
  12.             final AuthenticationHandler proxyAuthHandler, 
  13.             final UserTokenHandler userTokenHandler, 
  14.             final HttpParams params)  
  15.     { 
  16.         super(requestExec, conman, reustrat, kastrat, rouplan, httpProcessor, retryHandler, redirectHandler, targetAuthHandler, proxyAuthHandler, userTokenHandler, params); 
  17.  
  18.     } 
  19.     @Override 
  20.     protected RoutedRequest handleResponse(RoutedRequest roureq, 
  21.             HttpResponse response, 
  22.             HttpContext context) 
  23.                     throws HttpException, IOException 
  24.     { 
  25.         RoutedRequest req = super.handleResponse(roureq, response, context); 
  26.         if(req != null) 
  27.         { 
  28.             String redirectTarget = req.getRoute().getTargetHost().getHostName(); 
  29.             req.getRequest().getOriginal().setHeader("Host", redirectTarget);//开源代码Vevb.com 
  30.         } 
  31.         return req; 
  32.     } 
  33.  

这里修改了Host头为试图重定向的主机名,还需要修改 DefaultHttpClient,代码如下:

  1. public class RedirectHttpClient extends DefaultHttpClient 
  2.     @Override 
  3.     protected RequestDirector createClientRequestDirector( 
  4.             final HttpRequestExecutor requestExec, 
  5.             final ClientConnectionManager conman, 
  6.             final ConnectionReuseStrategy reustrat, 
  7.             final ConnectionKeepAliveStrategy kastrat, 
  8.             final HttpRoutePlanner rouplan, 
  9.             final HttpProcessor httpProcessor, 
  10.             final HttpRequestRetryHandler retryHandler, 
  11.             final RedirectHandler redirectHandler, 
  12.             final AuthenticationHandler targetAuthHandler, 
  13.             final AuthenticationHandler proxyAuthHandler, 
  14.             final UserTokenHandler stateHandler, 
  15.             final HttpParams params) { 
  16.         return new RedirectRequestDirector( 
  17.                 requestExec, 
  18.                 conman, 
  19.                 reustrat, 
  20.                 kastrat, 
  21.                 rouplan, 
  22.                 httpProcessor, 
  23.                 retryHandler, 
  24.                 redirectHandler, 
  25.                 targetAuthHandler, 
  26.                 proxyAuthHandler, 
  27.                 stateHandler, 
  28.                 params); 
  29.     } 

现在就能正常处理跳转了.

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表