Skip to content

Commit a8f500d

Browse files
author
Stephane Landelle
committed
Reuse channel when possible on redirect, close AsyncHttpClient#796
1 parent 2535007 commit a8f500d

File tree

2 files changed

+40
-27
lines changed
  • providers
    • netty3/src/main/java/org/asynchttpclient/providers/netty3/handler
    • netty4/src/main/java/org/asynchttpclient/providers/netty4/handler

2 files changed

+40
-27
lines changed

providers/netty3/src/main/java/org/asynchttpclient/providers/netty3/handler/Protocol.java

Lines changed: 18 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -47,10 +47,8 @@
4747
import org.asynchttpclient.filter.FilterContext;
4848
import org.asynchttpclient.filter.FilterException;
4949
import org.asynchttpclient.filter.ResponseFilter;
50-
import org.asynchttpclient.providers.netty3.Callback;
5150
import org.asynchttpclient.providers.netty3.NettyAsyncHttpProviderConfig;
5251
import org.asynchttpclient.providers.netty3.channel.ChannelManager;
53-
import org.asynchttpclient.providers.netty3.channel.Channels;
5452
import org.asynchttpclient.providers.netty3.future.NettyResponseFuture;
5553
import org.asynchttpclient.providers.netty3.request.NettyRequestSender;
5654
import org.asynchttpclient.uri.Uri;
@@ -171,22 +169,28 @@ protected boolean exitAfterHandlingRedirect(//
171169

172170
requestBuilder.setHeaders(propagatedHeaders(future.getRequest()));
173171

174-
Callback callback = channelManager.newDrainCallback(future, channel, initialConnectionKeepAlive, initialPoolKey);
172+
final Request nextRequest = requestBuilder.setUrl(newUrl).build();
173+
174+
logger.debug("Sending redirect to {}", request.getUri());
175+
176+
if (future.isKeepAlive() && !HttpHeaders.isTransferEncodingChunked(response) && !response.isChunked()) {
177+
178+
boolean redirectToSameHost = request.getUri().getScheme().equals(nextRequest.getUri().getScheme())
179+
&& request.getUri().getHost().equals(nextRequest.getUri().getHost())
180+
&& request.getUri().getPort() == nextRequest.getUri().getPort();
181+
182+
if (redirectToSameHost) {
183+
future.setReuseChannel(true);
184+
} else {
185+
channelManager.drainChannelAndOffer(channel, future, initialConnectionKeepAlive, initialPoolKey);
186+
}
175187

176-
if (HttpHeaders.isTransferEncodingChunked(response)) {
177-
// We must make sure there is no bytes left before
178-
// executing the next request.
179-
// FIXME investigate this
180-
Channels.setAttribute(channel, callback);
181188
} else {
182-
// FIXME don't understand: this offers the connection to the pool, or even closes it, while the
183-
// request has not been sent, right?
184-
callback.call();
189+
// redirect + chunking = WAT
190+
channelManager.closeChannel(channel);
185191
}
186192

187-
Request redirectRequest = requestBuilder.setUrl(newUrl).build();
188-
// FIXME why not reuse the channel is same host?
189-
requestSender.sendNextRequest(redirectRequest, future);
193+
requestSender.sendNextRequest(nextRequest, future);
190194
return true;
191195
}
192196
}

providers/netty4/src/main/java/org/asynchttpclient/providers/netty4/handler/Protocol.java

Lines changed: 22 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -171,22 +171,31 @@ protected boolean exitAfterHandlingRedirect(//
171171

172172
requestBuilder.setHeaders(propagatedHeaders(future.getRequest()));
173173

174-
Callback callback = channelManager.newDrainCallback(future, channel, initialConnectionKeepAlive, initialPoolKey);
174+
final Request nextRequest = requestBuilder.setUrl(newUrl).build();
175+
176+
logger.debug("Sending redirect to {}", request.getUri());
177+
178+
if (future.isKeepAlive() && !HttpHeaders.isTransferEncodingChunked(response)) {
179+
180+
boolean redirectToSameHost = request.getUri().getScheme().equals(nextRequest.getUri().getScheme())
181+
&& request.getUri().getHost().equals(nextRequest.getUri().getHost())
182+
&& request.getUri().getPort() == nextRequest.getUri().getPort();
183+
184+
if (redirectToSameHost) {
185+
future.setReuseChannel(true);
186+
requestSender.drainChannelAndExecuteNextRequest(channel, future, nextRequest);
187+
188+
} else {
189+
channelManager.drainChannelAndOffer(channel, future, initialConnectionKeepAlive, initialPoolKey);
190+
requestSender.sendNextRequest(nextRequest, future);
191+
}
175192

176-
if (HttpHeaders.isTransferEncodingChunked(response)) {
177-
// We must make sure there is no bytes left before
178-
// executing the next request.
179-
// FIXME investigate this
180-
Channels.setAttribute(channel, callback);
181193
} else {
182-
// FIXME don't understand: this offers the connection to the pool, or even closes it, while the
183-
// request has not been sent, right?
184-
callback.call();
194+
// redirect + chunking = WAT
195+
channelManager.closeChannel(channel);
196+
requestSender.sendNextRequest(nextRequest, future);
185197
}
186-
187-
Request redirectRequest = requestBuilder.setUrl(newUrl).build();
188-
// FIXME why not reuse the channel is same host?
189-
requestSender.sendNextRequest(redirectRequest, future);
198+
190199
return true;
191200
}
192201
}

0 commit comments

Comments
 (0)