Skip to content

Commit 64cdeb2

Browse files
committed
Incremental fix for #102 [websocket] Support redirect
1 parent b81fe77 commit 64cdeb2

File tree

1 file changed

+80
-64
lines changed

1 file changed

+80
-64
lines changed

src/main/java/com/ning/http/client/providers/netty/NettyAsyncHttpProvider.java

Lines changed: 80 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)