@Override protected void channelRead( final C connection, final ContextImpl context, final ChannelHandlerContext chctx, final Object msg) throws Exception { if (msg instanceof HttpObject) { DecoderResult result = ((HttpObject) msg).getDecoderResult(); if (result.isFailure()) { chctx.pipeline().fireExceptionCaught(result.cause()); return; } } if (connection != null) { // we are reading from the channel // We need to do this since it's possible the server is being used from a worker context context.execute(() -> doMessageReceived(connection, chctx, msg), true); } else { // We execute this directly as we don't have a context yet, the context will have to be set // manually // inside doMessageReceived(); try { doMessageReceived(null, chctx, msg); } catch (Throwable t) { chctx.pipeline().fireExceptionCaught(t); } } }
@Override public void channelRead0( ChannelHandlerContext channelHandlerContext, FullHttpRequest fullHttpRequest) throws Exception { DecoderResult decoderResult = fullHttpRequest.decoderResult(); if (!decoderResult.isSuccess()) { _sendError(channelHandlerContext, BAD_REQUEST); return; } if (fullHttpRequest.method() == GET) { processGetRequest(channelHandlerContext, fullHttpRequest); } else if (fullHttpRequest.method() == HEAD) { processHeadRequest(channelHandlerContext, fullHttpRequest); } else { _sendError(channelHandlerContext, BAD_REQUEST); } }
@Override protected void decode(ChannelHandlerContext ctx, HttpObject msg, MessageBuf<Object> out) throws Exception { FullHttpMessage currentMessage = this.currentMessage; if (msg instanceof HttpMessage) { assert currentMessage == null; HttpMessage m = (HttpMessage) msg; // Handle the 'Expect: 100-continue' header if necessary. // TODO: Respond with 413 Request Entity Too Large // and discard the traffic or close the connection. // No need to notify the upstream handlers - just log. // If decoding a response, just throw an exception. if (is100ContinueExpected(m)) { ctx.write(CONTINUE.duplicate()); } if (!m.getDecoderResult().isSuccess()) { removeTransferEncodingChunked(m); this.currentMessage = null; out.add(BufUtil.retain(m)); return; } if (msg instanceof HttpRequest) { HttpRequest header = (HttpRequest) msg; this.currentMessage = currentMessage = new DefaultFullHttpRequest( header.getProtocolVersion(), header.getMethod(), header.getUri(), Unpooled.compositeBuffer(maxCumulationBufferComponents)); } else if (msg instanceof HttpResponse) { HttpResponse header = (HttpResponse) msg; this.currentMessage = currentMessage = new DefaultFullHttpResponse( header.getProtocolVersion(), header.getStatus(), Unpooled.compositeBuffer(maxCumulationBufferComponents)); } else { throw new Error(); } currentMessage.headers().set(m.headers()); // A streamed message - initialize the cumulative buffer, and wait for incoming chunks. removeTransferEncodingChunked(currentMessage); } else if (msg instanceof HttpContent) { assert currentMessage != null; // Merge the received chunk into the content of the current message. HttpContent chunk = (HttpContent) msg; CompositeByteBuf content = (CompositeByteBuf) currentMessage.content(); if (content.readableBytes() > maxContentLength - chunk.content().readableBytes()) { // TODO: Respond with 413 Request Entity Too Large // and discard the traffic or close the connection. // No need to notify the upstream handlers - just log. // If decoding a response, just throw an exception. throw new TooLongFrameException( "HTTP content length exceeded " + maxContentLength + " bytes."); } // Append the content of the chunk if (chunk.content().isReadable()) { chunk.retain(); content.addComponent(chunk.content()); content.writerIndex(content.writerIndex() + chunk.content().readableBytes()); } final boolean last; if (!chunk.getDecoderResult().isSuccess()) { currentMessage.setDecoderResult(DecoderResult.failure(chunk.getDecoderResult().cause())); last = true; } else { last = chunk instanceof LastHttpContent; } if (last) { this.currentMessage = null; // Merge trailing headers into the message. if (chunk instanceof LastHttpContent) { LastHttpContent trailer = (LastHttpContent) chunk; currentMessage.headers().add(trailer.trailingHeaders()); } // Set the 'Content-Length' header. currentMessage .headers() .set(HttpHeaders.Names.CONTENT_LENGTH, String.valueOf(content.readableBytes())); // All done out.add(currentMessage); } } else { throw new Error(); } }