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); }
@Override public List<String> cookies() { synchronized (conn) { if (cookies == null) { cookies = new ArrayList<>(); cookies.addAll(response.headers().getAll(HttpHeaders.SET_COOKIE)); if (trailer != null) { cookies.addAll(trailer.trailingHeaders().getAll(HttpHeaders.SET_COOKIE)); } } return cookies; } }
void handleEnd(LastHttpContent trailer) { synchronized (conn) { conn.reportBytesRead(bytesRead); bytesRead = 0; request.reportResponseEnd(this); if (paused) { hasPausedEnd = true; pausedTrailer = trailer; } else { this.trailer = trailer; trailers = new HeadersAdaptor(trailer.trailingHeaders()); if (endHandler != null) { try { endHandler.handle(null); } catch (Throwable t) { handleException(t); } } } } }
@Override protected Object safeObject(Object msg) throws Exception { if (msg instanceof HttpContent) { HttpContent content = (HttpContent) msg; ByteBuf buf = content.content(); if (buf != Unpooled.EMPTY_BUFFER && buf.isDirect()) { ByteBuf newBuf = safeBuffer(content); if (msg instanceof LastHttpContent) { LastHttpContent last = (LastHttpContent) msg; return new AssembledLastHttpContent(newBuf, last.trailingHeaders()); } else { return new DefaultHttpContent(newBuf); } } } else if (msg instanceof WebSocketFrame) { ByteBuf payload = safeBuffer((WebSocketFrame) msg); if (msg instanceof BinaryWebSocketFrame) { return new DefaultWebSocketFrame( org.vertx.java.core.http.impl.ws.WebSocketFrame.FrameType.BINARY, payload); } else if (msg instanceof CloseWebSocketFrame) { return new DefaultWebSocketFrame( org.vertx.java.core.http.impl.ws.WebSocketFrame.FrameType.CLOSE, payload); } else if (msg instanceof PingWebSocketFrame) { return new DefaultWebSocketFrame( org.vertx.java.core.http.impl.ws.WebSocketFrame.FrameType.PING, payload); } else if (msg instanceof PongWebSocketFrame) { return new DefaultWebSocketFrame( org.vertx.java.core.http.impl.ws.WebSocketFrame.FrameType.PONG, payload); } else if (msg instanceof TextWebSocketFrame) { return new DefaultWebSocketFrame( org.vertx.java.core.http.impl.ws.WebSocketFrame.FrameType.TEXT, payload); } else if (msg instanceof ContinuationWebSocketFrame) { return new DefaultWebSocketFrame( org.vertx.java.core.http.impl.ws.WebSocketFrame.FrameType.CONTINUATION, payload); } else { throw new IllegalStateException("Unsupported websocket msg " + msg); } } return msg; }
@Override protected Object safeObject(Object msg, ByteBufAllocator allocator) throws Exception { if (msg instanceof HttpContent) { HttpContent content = (HttpContent) msg; ByteBuf buf = content.content(); if (buf != Unpooled.EMPTY_BUFFER && buf.isDirect()) { ByteBuf newBuf = safeBuffer(content, allocator); if (msg instanceof LastHttpContent) { LastHttpContent last = (LastHttpContent) msg; return new AssembledLastHttpContent( newBuf, last.trailingHeaders(), last.getDecoderResult()); } else { return new DefaultHttpContent(newBuf); } } } else if (msg instanceof WebSocketFrame) { ByteBuf payload = safeBuffer((WebSocketFrame) msg, allocator); boolean isFinal = ((WebSocketFrame) msg).isFinalFragment(); FrameType frameType; if (msg instanceof BinaryWebSocketFrame) { frameType = FrameType.BINARY; } else if (msg instanceof CloseWebSocketFrame) { frameType = FrameType.CLOSE; } else if (msg instanceof PingWebSocketFrame) { frameType = FrameType.PING; } else if (msg instanceof PongWebSocketFrame) { frameType = FrameType.PONG; } else if (msg instanceof TextWebSocketFrame) { frameType = FrameType.TEXT; } else if (msg instanceof ContinuationWebSocketFrame) { frameType = FrameType.CONTINUATION; } else { throw new IllegalStateException("Unsupported websocket msg " + msg); } return new WebSocketFrameImpl(frameType, payload, isFinal); } return msg; }
@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; } } }
@Override protected void encode(ChannelHandlerContext ctx, HttpObject msg, List<Object> out) throws Exception { boolean valid = false; boolean last = false; if (msg instanceof HttpRequest) { HttpRequest httpRequest = (HttpRequest) msg; SpdySynStreamFrame spdySynStreamFrame = createSynStreamFrame(httpRequest); out.add(spdySynStreamFrame); last = spdySynStreamFrame.isLast(); valid = true; } if (msg instanceof HttpResponse) { HttpResponse httpResponse = (HttpResponse) msg; if (httpResponse.headers().contains(SpdyHttpHeaders.Names.ASSOCIATED_TO_STREAM_ID)) { SpdySynStreamFrame spdySynStreamFrame = createSynStreamFrame(httpResponse); last = spdySynStreamFrame.isLast(); out.add(spdySynStreamFrame); } else { SpdySynReplyFrame spdySynReplyFrame = createSynReplyFrame(httpResponse); last = spdySynReplyFrame.isLast(); out.add(spdySynReplyFrame); } valid = true; } if (msg instanceof HttpContent && !last) { HttpContent chunk = (HttpContent) msg; chunk.content().retain(); SpdyDataFrame spdyDataFrame = new DefaultSpdyDataFrame(currentStreamId, chunk.content()); spdyDataFrame.setLast(chunk instanceof LastHttpContent); if (chunk instanceof LastHttpContent) { LastHttpContent trailer = (LastHttpContent) chunk; HttpHeaders trailers = trailer.trailingHeaders(); if (trailers.isEmpty()) { out.add(spdyDataFrame); } else { // Create SPDY HEADERS frame out of trailers SpdyHeadersFrame spdyHeadersFrame = new DefaultSpdyHeadersFrame(currentStreamId); for (Map.Entry<String, String> entry : trailers) { spdyHeadersFrame.headers().add(entry.getKey(), entry.getValue()); } // Write HEADERS frame and append Data Frame out.add(spdyHeadersFrame); out.add(spdyDataFrame); } } else { out.add(spdyDataFrame); } valid = true; } if (!valid) { throw new UnsupportedMessageTypeException(msg); } }