/** * Create a new HTTP Asynchronous Client using the specified * {@link DefaultAsyncHttpClientConfig} configuration. This configuration * will be passed to the default {@link AsyncHttpClient} that will be * selected based on the classpath configuration. * * @param config a {@link DefaultAsyncHttpClientConfig} */ public DefaultAsyncHttpClient(AsyncHttpClientConfig config) { this.config = config; this.noRequestFilters = config.getRequestFilters().isEmpty(); allowStopNettyTimer = config.getNettyTimer() == null; nettyTimer = allowStopNettyTimer ? newNettyTimer(config) : config.getNettyTimer(); channelManager = new ChannelManager(config, nettyTimer); requestSender = new NettyRequestSender(config, channelManager, nettyTimer, new AsyncHttpClientState(closed)); channelManager.configureBootstraps(requestSender); }
@Override public void close() { if (closed.compareAndSet(false, true)) { try { channelManager.close(); } catch (Throwable t) { LOGGER.warn("Unexpected error on ChannelManager close", t); } if (allowStopNettyTimer) { try { nettyTimer.stop(); } catch (Throwable t) { LOGGER.warn("Unexpected error on HashedWheelTimer close", t); } } } }
@Override protected void cancelled() { logger.debug("Subscriber cancelled, ignoring the rest of the body"); try { future.done(); } catch (Exception t) { // Never propagate exception once we know we are done. logger.debug(t.getMessage(), t); } // The subscriber cancelled early - this channel is dead and should be closed. channelManager.closeChannel(channel); }
void finishUpdate(NettyResponseFuture<?> future, Channel channel, boolean close) { future.cancelTimeouts(); if (close) { channelManager.closeChannel(channel); } else { channelManager.tryToOfferChannelToPool(channel, future.getAsyncHandler(), true, future.getPartitionKey()); } try { future.done(); } catch (Exception t) { // Never propagate exception once we know we are done. logger.debug(t.getMessage(), t); } }
public Future<Channel> updatePipelineForHttpTunneling(ChannelPipeline pipeline, Uri requestUri) { Future<Channel> whenHanshaked = null; if (pipeline.get(HTTP_CLIENT_CODEC) != null) pipeline.remove(HTTP_CLIENT_CODEC); if (requestUri.isSecured()) { if (!isSslHandlerConfigured(pipeline)) { SslHandler sslHandler = createSslHandler(requestUri.getHost(), requestUri.getExplicitPort()); whenHanshaked = sslHandler.handshakeFuture(); pipeline.addBefore(INFLATER_HANDLER, SSL_HANDLER, sslHandler); } pipeline.addAfter(SSL_HANDLER, HTTP_CLIENT_CODEC, newHttpClientCodec()); } else { pipeline.addBefore(AHC_HTTP_HANDLER, HTTP_CLIENT_CODEC, newHttpClientCodec()); } if (requestUri.isWebSocket()) { pipeline.addAfter(AHC_HTTP_HANDLER, AHC_WS_HANDLER, wsHandler); pipeline.remove(AHC_HTTP_HANDLER); } return whenHanshaked; }
Bootstrap bootstrap = channelManager.getBootstrap(request.getUri(), useProxy, useSSl); channelManager.preemptChannel(partitionKey); channelPreempted = true; channelManager.abortChannelPreemption(partitionKey);
channelManager.drainChannelAndOffer(channel, future, initialConnectionKeepAlive, initialPartitionKey); requestSender.sendNextRequest(nextRequest, future); channelManager.closeChannel(channel); requestSender.sendNextRequest(nextRequest, future);
private void finishUpdate(final NettyResponseFuture<?> future, Channel channel, boolean expectOtherChunks) throws IOException { future.cancelTimeouts(); boolean keepAlive = future.isKeepAlive(); if (expectOtherChunks && keepAlive) channelManager.drainChannelAndOffer(channel, future); else channelManager.tryToOfferChannelToPool(channel, keepAlive, future.getPartitionKey()); try { future.done(); } catch (Throwable t) { // Never propagate exception once we know we are done. logger.debug(t.getMessage(), t); } }
@Override public void write(Channel channel, NettyResponseFuture<?> future) throws IOException { @SuppressWarnings("resource") // netty will close the FileChannel FileChannel fileChannel = new RandomAccessFile(file, "r").getChannel(); boolean noZeroCopy = ChannelManager.isSslHandlerConfigured(channel.pipeline()) || config.isDisableZeroCopy(); Object body = noZeroCopy ? new ChunkedNioFile(fileChannel, offset, length, config.getChunkedFileChunkSize()) : new DefaultFileRegion(fileChannel, offset, length); channel.write(body, channel.newProgressivePromise()) .addListener(new WriteProgressListener(future, false, length)); channel.writeAndFlush(LastHttpContent.EMPTY_LAST_CONTENT, channel.voidPromise()); } }
public void drainChannelAndOffer(Channel channel, NettyResponseFuture<?> future) { drainChannelAndOffer(channel, future, future.isKeepAlive(), future.getPartitionKey()); }
/** * Always make sure the channel who got cached support the proper protocol. * It could only occurs when a HttpMethod. CONNECT is used against a proxy * that requires upgrading from http to https. */ public void verifyChannelPipeline(ChannelPipeline pipeline, Uri uri, String virtualHost) throws GeneralSecurityException { boolean sslHandlerConfigured = isSslHandlerConfigured(pipeline); if (uri.isSecured()) { if (!sslHandlerConfigured) addSslHandler(pipeline, uri, virtualHost); } else if (sslHandlerConfigured) pipeline.remove(SSL_HANDLER); }
public void drainChannelAndOffer(Channel channel, NettyResponseFuture<?> future, boolean keepAlive, Object partitionKey) { Channels.setAttribute(channel, newDrainCallback(future, channel, keepAlive, partitionKey)); }
public SslHandler addSslHandler(ChannelPipeline pipeline, Uri uri, String virtualHost, boolean hasSocksProxyHandler) { String peerHost; int peerPort; if (virtualHost != null) { int i = virtualHost.indexOf(':'); if (i == -1) { peerHost = virtualHost; peerPort = uri.getSchemeDefaultPort(); } else { peerHost = virtualHost.substring(0, i); peerPort = Integer.valueOf(virtualHost.substring(i + 1)); } } else { peerHost = uri.getHost(); peerPort = uri.getExplicitPort(); } SslHandler sslHandler = createSslHandler(peerHost, peerPort); if (hasSocksProxyHandler) { pipeline.addAfter(SOCKS_HANDLER, SSL_HANDLER, sslHandler); } else { pipeline.addFirst(SSL_HANDLER, sslHandler); } return sslHandler; }
@Override protected void onSuccess(List<InetSocketAddress> addresses) { NettyConnectListener<T> connectListener = new NettyConnectListener<>(future, NettyRequestSender.this, channelManager, connectionSemaphore); NettyChannelConnector connector = new NettyChannelConnector(request.getLocalAddress(), addresses, asyncHandler, clientState); if (!future.isDone()) { // Do not throw an exception when we need an extra connection for a redirect // FIXME why? This violate the max connection per host handling, right? channelManager.getBootstrap(request.getUri(), request.getNameResolver(), proxy) .addListener((Future<Bootstrap> whenBootstrap) -> { if (whenBootstrap.isSuccess()) { connector.connect(whenBootstrap.get(), connectListener); } else { abort(null, future, whenBootstrap.cause()); } }); } }
public void upgradeProtocol(ChannelPipeline pipeline, String scheme, String host, int port) throws IOException, GeneralSecurityException { if (pipeline.get(HTTP_HANDLER) != null) pipeline.remove(HTTP_HANDLER); if (isSecure(scheme)) if (isSslHandlerConfigured(pipeline)) { pipeline.addAfter(SSL_HANDLER, HTTP_HANDLER, newHttpClientCodec()); } else { pipeline.addFirst(HTTP_HANDLER, newHttpClientCodec()); pipeline.addFirst(SSL_HANDLER, createSslHandler(host, port)); } else pipeline.addFirst(HTTP_HANDLER, newHttpClientCodec()); if (isWebSocket(scheme)) { pipeline.addAfter(HTTP_PROCESSOR, WS_PROCESSOR, wsProcessor); pipeline.remove(HTTP_PROCESSOR); } }
Bootstrap bootstrap = channelManager.getBootstrap(request.getUri(), useProxy); channelManager.preemptChannel(partitionKey); channelPreempted = true; channelManager.abortChannelPreemption(partitionKey);
channelManager.drainChannelAndOffer(channel, future, initialConnectionKeepAlive, initialPartitionKey); requestSender.sendNextRequest(nextRequest, future); channelManager.closeChannel(channel); requestSender.sendNextRequest(nextRequest, future);
private void finishUpdate(final NettyResponseFuture<?> future, Channel channel, boolean expectOtherChunks) throws IOException { future.cancelTimeouts(); boolean keepAlive = future.isKeepAlive(); if (expectOtherChunks && keepAlive) channelManager.drainChannelAndOffer(channel, future); else channelManager.tryToOfferChannelToPool(channel, keepAlive, future.getPartitionKey()); try { future.done(); } catch (Throwable t) { // Never propagate exception once we know we are done. logger.debug(t.getMessage(), t); } }
if (body instanceof RandomAccessBody && !ChannelManager.isSslHandlerConfigured(channel.pipeline()) && !config.isDisableZeroCopy() && getContentLength() > 0) { msg = new BodyFileRegion((RandomAccessBody) body);
@SuppressWarnings({"rawtypes", "unchecked"}) public void replayRequest(final NettyResponseFuture<?> future, FilterContext fc, Channel channel) { Request newRequest = fc.getRequest(); future.setAsyncHandler(fc.getAsyncHandler()); future.setChannelState(ChannelState.NEW); future.touch(); LOGGER.debug("\n\nReplaying Request {}\n for Future {}\n", newRequest, future); try { future.getAsyncHandler().onRetry(); } catch (Exception e) { LOGGER.error("onRetry crashed", e); abort(channel, future, e); return; } channelManager.drainChannelAndOffer(channel, future); sendNextRequest(newRequest, future); }