@Override
    public void channelRead0(ChannelHandlerContext ctx, HttpObject in) {
      // Make sure that we increase refCnt because we are going to process it async. The other end has to release
      // after processing.
      responseParts.offer(ReferenceCountUtil.retain(in));
      if (in instanceof HttpResponse && in.decoderResult().isSuccess()) {
        isKeepAlive = HttpUtil.isKeepAlive((HttpResponse) in);
      } else if (in.decoderResult().isFailure()) {
        Throwable cause = in.decoderResult().cause();
        if (cause instanceof Exception) {
          exception = (Exception) cause;
        } else {
          exception =
              new Exception("Encountered Throwable when trying to decode response. Message: " + cause.getMessage());
        }
        invokeFutureAndCallback("CommunicationHandler::channelRead0 - decoder failure");
      }
      if (in instanceof LastHttpContent) {
        if (isKeepAlive) {
          invokeFutureAndCallback("CommunicationHandler::channelRead0 - last content");
        } else {
          // if not, the future will be invoked when the channel is closed.
          ctx.close();
        }
      }
    }
Custom handler that receives the response.
ambry-test-utils/src/main/java/com/github/ambry/rest/NettyClient.java