private void handleChunk( HttpContent chunk, // final Channel channel, // final NettyResponseFuture<?> future, // AsyncHandler<?> handler) throws IOException, Exception { boolean interrupt = false; boolean last = chunk instanceof LastHttpContent; // Netty 4: the last chunk is not empty if (last) { LastHttpContent lastChunk = (LastHttpContent) chunk; HttpHeaders trailingHeaders = lastChunk.trailingHeaders(); if (!trailingHeaders.isEmpty()) { interrupt = handler.onHeadersReceived(new HttpResponseHeaders(trailingHeaders, true)) != State.CONTINUE; } } ByteBuf buf = chunk.content(); if (!interrupt && !(handler instanceof StreamedAsyncHandler) && (buf.readableBytes() > 0 || last)) { HttpResponseBodyPart part = config.getResponseBodyPartFactory().newResponseBodyPart(buf, last); interrupt = updateBodyAndInterrupt(future, handler, part); } if (interrupt || last) finishUpdate(future, channel, !last); }
private boolean exitAfterHandlingHeaders( Channel channel, NettyResponseFuture<?> future, HttpResponse response, AsyncHandler<?> handler, HttpResponseHeaders responseHeaders, HttpRequest httpRequest) throws IOException, Exception { return !response.headers().isEmpty() && handler.onHeadersReceived(responseHeaders) != State.CONTINUE; }
private boolean handleHanderAndExit( Channel channel, NettyResponseFuture<?> future, AsyncHandler<?> handler, HttpResponseStatus status, HttpResponseHeaders responseHeaders, HttpResponse response) throws Exception { if (!future.getAndSetStatusReceived(true) && (handler.onStatusReceived(status) != STATE.CONTINUE || handler.onHeadersReceived(responseHeaders) != STATE.CONTINUE)) { finishUpdate(future, channel, HttpHeaders.isTransferEncodingChunked(response)); return true; } return false; }
@Override public void handle(final Channel channel, final NettyResponseFuture<?> future, final Object e) throws Exception { future.touch(); // The connect timeout occurred. if (future.isCancelled() || future.isDone()) { channels.finishChannel(channel); return; } NettyRequest nettyRequest = future.getNettyRequest(); AsyncHandler<?> handler = future.getAsyncHandler(); ProxyServer proxyServer = future.getProxyServer(); try { if (e instanceof HttpResponse) { HttpResponse response = (HttpResponse) e; LOGGER.debug("\n\nRequest {}\n\nResponse {}\n", nettyRequest.getHttpRequest(), response); future.setPendingResponse(response); return; } if (e instanceof HttpContent) { HttpResponse response = future.getPendingResponse(); future.setPendingResponse(null); if (handler != null) { if (response != null && handleResponseAndExit( channel, future, handler, nettyRequest.getHttpRequest(), proxyServer, response)) { return; } HttpContent chunk = (HttpContent) e; boolean interrupt = false; boolean last = chunk instanceof LastHttpContent; if (last) { LastHttpContent lastChunk = (LastHttpContent) chunk; HttpHeaders trailingHeaders = lastChunk.trailingHeaders(); if (!trailingHeaders.isEmpty()) { interrupt = handler.onHeadersReceived( new ResponseHeaders( future.getURI(), future.getHttpHeaders(), trailingHeaders)) != STATE.CONTINUE; } } ByteBuf buf = chunk.content(); try { if (!interrupt && (buf.readableBytes() > 0 || last)) { interrupt = updateBodyAndInterrupt( future, handler, nettyConfig.getBodyPartFactory().newResponseBodyPart(buf, last)); } } finally { // FIXME we shouldn't need this, should we? But a leak was reported there without it?! buf.release(); } if (interrupt || last) { finishUpdate(future, channel, !last); } } } } catch (Exception t) { if (hasIOExceptionFilters && t instanceof IOException && requestSender.applyIoExceptionFiltersAndReplayRequest( future, IOException.class.cast(t), channel)) { return; } try { channels.abort(future, t); } finally { finishUpdate(future, channel, false); throw t; } } }