@@ -1969,6 +1969,81 @@ private static final boolean validateWebSocketRequest(Request request, AsyncHand
19691969 return true ;
19701970 }
19711971
1972+ private boolean redirect (Request request ,
1973+ NettyResponseFuture <?> future ,
1974+ HttpResponse response ,
1975+ final ChannelHandlerContext ctx ) throws Exception {
1976+
1977+ int statusCode = response .getStatus ().getCode ();
1978+ boolean redirectEnabled = request .isRedirectOverrideSet () ? request .isRedirectEnabled () : config .isRedirectEnabled ();
1979+ if (redirectEnabled && (statusCode == 302
1980+ || statusCode == 301
1981+ || statusCode == 303
1982+ || statusCode == 307 )) {
1983+
1984+ if (future .incrementAndGetCurrentRedirectCount () < config .getMaxRedirects ()) {
1985+ // We must allow 401 handling again.
1986+ future .getAndSetAuth (false );
1987+
1988+ String location = response .getHeader (HttpHeaders .Names .LOCATION );
1989+ URI uri = AsyncHttpProviderUtils .getRedirectUri (future .getURI (), location );
1990+ boolean stripQueryString = config .isRemoveQueryParamOnRedirect ();
1991+ if (!uri .toString ().equalsIgnoreCase (future .getURI ().toString ())) {
1992+ final RequestBuilder nBuilder = stripQueryString ?
1993+ new RequestBuilder (future .getRequest ()).setQueryParameters (null )
1994+ : new RequestBuilder (future .getRequest ());
1995+
1996+ if (!(statusCode < 302 || statusCode > 303 )
1997+ && !(statusCode == 302
1998+ && config .isStrict302Handling ())) {
1999+ nBuilder .setMethod ("GET" );
2000+ }
2001+ final URI initialConnectionUri = future .getURI ();
2002+ final boolean initialConnectionKeepAlive = future .getKeepAlive ();
2003+ future .setURI (uri );
2004+ String newUrl = uri .toString ();
2005+ if (future .getNettyRequest ().getUri ().startsWith (WEBSOCKET )) {
2006+ newUrl = newUrl .replace (HTTP , WEBSOCKET );
2007+ }
2008+
2009+ log .debug ("Redirecting to {}" , newUrl );
2010+ for (String cookieStr : future .getHttpResponse ().getHeaders (HttpHeaders .Names .SET_COOKIE )) {
2011+ Cookie c = AsyncHttpProviderUtils .parseCookie (cookieStr );
2012+ nBuilder .addOrReplaceCookie (c );
2013+ }
2014+
2015+ for (String cookieStr : future .getHttpResponse ().getHeaders (HttpHeaders .Names .SET_COOKIE2 )) {
2016+ Cookie c = AsyncHttpProviderUtils .parseCookie (cookieStr );
2017+ nBuilder .addOrReplaceCookie (c );
2018+ }
2019+
2020+ AsyncCallable ac = new AsyncCallable (future ) {
2021+ public Object call () throws Exception {
2022+ if (initialConnectionKeepAlive && ctx .getChannel ().isReadable () &&
2023+ connectionsPool .offer (AsyncHttpProviderUtils .getBaseUrl (initialConnectionUri ), ctx .getChannel ())) {
2024+ return null ;
2025+ }
2026+ finishChannel (ctx );
2027+ return null ;
2028+ }
2029+ };
2030+
2031+ if (response .isChunked ()) {
2032+ // We must make sure there is no bytes left before executing the next request.
2033+ ctx .setAttachment (ac );
2034+ } else {
2035+ ac .call ();
2036+ }
2037+ nextRequest (nBuilder .setUrl (newUrl ).build (), future );
2038+ return true ;
2039+ }
2040+ } else {
2041+ throw new MaxRedirectException ("Maximum redirect reached: " + config .getMaxRedirects ());
2042+ }
2043+ }
2044+ return false ;
2045+ }
2046+
19722047 private final class HttpProtocol implements Protocol {
19732048 // @Override
19742049 public void handle (final ChannelHandlerContext ctx , final MessageEvent e ) throws Exception {
@@ -2145,69 +2220,7 @@ public Object call() throws Exception {
21452220 return ;
21462221 }
21472222
2148- boolean redirectEnabled = request .isRedirectOverrideSet () ? request .isRedirectEnabled () : config .isRedirectEnabled ();
2149- if (redirectEnabled && (statusCode == 302
2150- || statusCode == 301
2151- || statusCode == 303
2152- || statusCode == 307 )) {
2153-
2154- if (future .incrementAndGetCurrentRedirectCount () < config .getMaxRedirects ()) {
2155- // We must allow 401 handling again.
2156- future .getAndSetAuth (false );
2157-
2158- String location = response .getHeader (HttpHeaders .Names .LOCATION );
2159- URI uri = AsyncHttpProviderUtils .getRedirectUri (future .getURI (), location );
2160- boolean stripQueryString = config .isRemoveQueryParamOnRedirect ();
2161- if (!uri .toString ().equalsIgnoreCase (future .getURI ().toString ())) {
2162- final RequestBuilder nBuilder = stripQueryString ?
2163- new RequestBuilder (future .getRequest ()).setQueryParameters (null )
2164- : new RequestBuilder (future .getRequest ());
2165-
2166- if (!(statusCode < 302 || statusCode > 303 )
2167- && !(statusCode == 302
2168- && config .isStrict302Handling ())) {
2169- nBuilder .setMethod ("GET" );
2170- }
2171- final URI initialConnectionUri = future .getURI ();
2172- final boolean initialConnectionKeepAlive = future .getKeepAlive ();
2173- future .setURI (uri );
2174- final String newUrl = uri .toString ();
2175-
2176- log .debug ("Redirecting to {}" , newUrl );
2177- for (String cookieStr : future .getHttpResponse ().getHeaders (HttpHeaders .Names .SET_COOKIE )) {
2178- Cookie c = AsyncHttpProviderUtils .parseCookie (cookieStr );
2179- nBuilder .addOrReplaceCookie (c );
2180- }
2181-
2182- for (String cookieStr : future .getHttpResponse ().getHeaders (HttpHeaders .Names .SET_COOKIE2 )) {
2183- Cookie c = AsyncHttpProviderUtils .parseCookie (cookieStr );
2184- nBuilder .addOrReplaceCookie (c );
2185- }
2186-
2187- AsyncCallable ac = new AsyncCallable (future ) {
2188- public Object call () throws Exception {
2189- if (initialConnectionKeepAlive && ctx .getChannel ().isReadable () &&
2190- connectionsPool .offer (AsyncHttpProviderUtils .getBaseUrl (initialConnectionUri ), ctx .getChannel ())) {
2191- return null ;
2192- }
2193- finishChannel (ctx );
2194- return null ;
2195- }
2196- };
2197-
2198- if (response .isChunked ()) {
2199- // We must make sure there is no bytes left before executing the next request.
2200- ctx .setAttachment (ac );
2201- } else {
2202- ac .call ();
2203- }
2204- nextRequest (nBuilder .setUrl (newUrl ).build (), future );
2205- return ;
2206- }
2207- } else {
2208- throw new MaxRedirectException ("Maximum redirect reached: " + config .getMaxRedirects ());
2209- }
2210- }
2223+ if (redirect (request , future , response , ctx )) return ;
22112224
22122225 if (!future .getAndSetStatusReceived (true ) && updateStatusAndInterrupt (handler , status )) {
22132226 finishUpdate (future , ctx , response .isChunked ());
@@ -2300,7 +2313,7 @@ public void handle(ChannelHandlerContext ctx, MessageEvent e) throws Exception {
23002313 }
23012314 } catch (FilterException efe ) {
23022315 abort (future , efe );
2303- } // @Override
2316+ }
23042317
23052318 }
23062319
@@ -2313,6 +2326,9 @@ public void handle(ChannelHandlerContext ctx, MessageEvent e) throws Exception {
23132326 return ;
23142327 }
23152328
2329+ future .setHttpResponse (response );
2330+ if (redirect (request , future , response , ctx )) return ;
2331+
23162332 final org .jboss .netty .handler .codec .http .HttpResponseStatus status =
23172333 new org .jboss .netty .handler .codec .http .HttpResponseStatus (101 , "Web Socket Protocol Handshake" );
23182334
0 commit comments