public Protocol( ChannelManager channelManager, AsyncHttpClientConfig config, NettyAsyncHttpProviderConfig nettyConfig, NettyRequestSender requestSender) { this.channelManager = channelManager; this.config = config; this.requestSender = requestSender; this.nettyConfig = nettyConfig; hasResponseFilters = !config.getResponseFilters().isEmpty(); hasIOExceptionFilters = !config.getIOExceptionFilters().isEmpty(); timeConverter = config.getTimeConverter(); }
private void addGeneralHeaders(final Request request, final HttpRequestPacket requestPacket) { if (request.hasHeaders()) { final FluentCaseInsensitiveStringsMap map = request.getHeaders(); for (final Map.Entry<String, List<String>> entry : map.entrySet()) { final String headerName = entry.getKey(); final List<String> headerValues = entry.getValue(); if (isNonEmpty(headerValues)) { for (int i = 0, len = headerValues.size(); i < len; i++) { requestPacket.addHeader(headerName, headerValues.get(i)); } } } } final MimeHeaders headers = requestPacket.getHeaders(); if (!headers.contains(Header.Connection)) { // final boolean canCache = context.provider.clientConfig.getAllowPoolingConnection(); requestPacket.addHeader(Header.Connection, /*(canCache ? */ "keep-alive" /*: "close")*/); } if (!headers.contains(Header.Accept)) { requestPacket.addHeader(Header.Accept, "*/*"); } if (!headers.contains(Header.UserAgent)) { requestPacket.addHeader(Header.UserAgent, config.getUserAgent()); } }
public NettyAsyncHttpProvider(AsyncHttpClientConfig config) { this.config = config; NettyAsyncHttpProviderConfig nettyConfig = config.getAsyncHttpProviderConfig() instanceof NettyAsyncHttpProviderConfig ? // (NettyAsyncHttpProviderConfig) config.getAsyncHttpProviderConfig() : new NettyAsyncHttpProviderConfig(); allowStopNettyTimer = nettyConfig.getNettyTimer() == null; nettyTimer = allowStopNettyTimer ? newNettyTimer() : nettyConfig.getNettyTimer(); channelManager = new ChannelManager(config, nettyConfig, nettyTimer); requestSender = new NettyRequestSender(config, channelManager, nettyTimer, closed); channelManager.configureBootstraps(requestSender, closed); }
private void addCookies(final Request request, final HttpRequestPacket requestPacket) { final Collection<Cookie> cookies = request.getCookies(); if (isNonEmpty(cookies)) { StringBuilder sb = new StringBuilder(128); org.glassfish.grizzly.http.Cookie[] gCookies = new org.glassfish.grizzly.http.Cookie[cookies.size()]; convertCookies(cookies, gCookies); CookieSerializerUtils.serializeClientCookies( sb, false, config.isRfc6265CookieEncoding(), gCookies); requestPacket.addHeader(Header.Cookie, sb.toString()); } }
public void close() { if (closed.compareAndSet(false, true)) { try { channelManager.close(); // FIXME shouldn't close if not allowed config.executorService().shutdown(); if (allowStopNettyTimer) nettyTimer.stop(); } catch (Throwable t) { LOGGER.warn("Unexpected error on close", t); } } }
@SuppressWarnings({"rawtypes", "unchecked"}) protected boolean exitAfterProcessingFilters( // Channel channel, // NettyResponseFuture<?> future, // AsyncHandler<?> handler, // HttpResponseStatus status, // HttpResponseHeaders responseHeaders) throws IOException { if (hasResponseFilters) { FilterContext fc = new FilterContext.FilterContextBuilder() .asyncHandler(handler) .request(future.getRequest()) .responseStatus(status) .responseHeaders(responseHeaders) .build(); for (ResponseFilter asyncFilter : config.getResponseFilters()) { try { fc = asyncFilter.filter(fc); // FIXME Is it worth protecting against this? if (fc == null) { throw new NullPointerException("FilterContext is null"); } } catch (FilterException efe) { requestSender.abort(channel, future, efe); } } // The handler may have been wrapped. future.setAsyncHandler(fc.getAsyncHandler()); // The request has changed if (fc.replayRequest()) { requestSender.replayRequest(future, fc, channel); return true; } } return false; }
protected boolean exitAfterHandlingRedirect( // Channel channel, // NettyResponseFuture<?> future, // HttpResponse response, // Request request, // int statusCode) throws Exception { if (followRedirect(config, request) && REDIRECT_STATUSES.contains(statusCode)) { if (future.incrementAndGetCurrentRedirectCount() >= config.getMaxRedirects()) { throw new MaxRedirectException("Maximum redirect reached: " + config.getMaxRedirects()); } else { // We must allow 401 handling again. future.getAndSetAuth(false); HttpHeaders responseHeaders = response.headers(); String location = responseHeaders.get(HttpHeaders.Names.LOCATION); Uri uri = Uri.create(future.getUri(), location); if (!uri.equals(future.getUri())) { final RequestBuilder requestBuilder = new RequestBuilder(future.getRequest()); if (!config.isRemoveQueryParamOnRedirect()) requestBuilder.addQueryParams(future.getRequest().getQueryParams()); // if we are to strictly handle 302, we should keep the original method (which browsers // don't) // 303 must force GET if ((statusCode == FOUND.code() && !config.isStrict302Handling()) || statusCode == SEE_OTHER.code()) requestBuilder.setMethod("GET"); // in case of a redirect from HTTP to HTTPS, future attributes might change final boolean initialConnectionKeepAlive = future.isKeepAlive(); final String initialPoolKey = channelManager.getPartitionId(future); future.setUri(uri); String newUrl = uri.toUrl(); if (request.getUri().getScheme().startsWith(WEBSOCKET)) { newUrl = newUrl.replaceFirst(HTTP, WEBSOCKET); } logger.debug("Redirecting to {}", newUrl); for (String cookieStr : responseHeaders.getAll(HttpHeaders.Names.SET_COOKIE)) { Cookie c = CookieDecoder.decode(cookieStr, timeConverter); if (c != null) requestBuilder.addOrReplaceCookie(c); } Callback callback = channelManager.newDrainCallback( future, channel, initialConnectionKeepAlive, initialPoolKey); if (HttpHeaders.isTransferEncodingChunked(response)) { // We must make sure there is no bytes left before // executing the next request. // FIXME investigate this Channels.setAttribute(channel, callback); } else { // FIXME don't understand: this offers the connection to the pool, or even closes it, // while the // request has not been sent, right? callback.call(); } Request redirectRequest = requestBuilder.setUrl(newUrl).build(); // FIXME why not reuse the channel is same host? requestSender.sendNextRequest(redirectRequest, future); return true; } } } return false; }