@Override
  public void handle(Channel channel, NettyResponseFuture<?> future, Object e) throws Exception {

    if (e instanceof HttpResponse) {
      HttpResponse response = (HttpResponse) e;
      Channels.setAttribute(channel, new UpgradeCallback(future, channel, response));

    } else if (e instanceof WebSocketFrame) {

      final WebSocketFrame frame = (WebSocketFrame) e;
      WebSocketUpgradeHandler handler =
          WebSocketUpgradeHandler.class.cast(future.getAsyncHandler());
      NettyWebSocket webSocket = NettyWebSocket.class.cast(handler.onCompleted());
      invokeOnSucces(channel, handler);

      if (webSocket != null) {
        if (frame instanceof CloseWebSocketFrame) {
          Channels.setDiscard(channel);
          CloseWebSocketFrame closeFrame = CloseWebSocketFrame.class.cast(frame);
          webSocket.onClose(closeFrame.statusCode(), closeFrame.reasonText());
        } else {
          ByteBuf buf = frame.content();
          if (buf != null && buf.readableBytes() > 0) {
            try {
              NettyResponseBodyPart part =
                  nettyConfig
                      .getBodyPartFactory()
                      .newResponseBodyPart(buf, frame.isFinalFragment());
              handler.onBodyPartReceived(part);

              if (frame instanceof BinaryWebSocketFrame) {
                webSocket.onBinaryFragment(part);
              } else if (frame instanceof TextWebSocketFrame) {
                webSocket.onTextFragment(part);
              } else if (frame instanceof PingWebSocketFrame) {
                webSocket.onPing(part);
              } else if (frame instanceof PongWebSocketFrame) {
                webSocket.onPong(part);
              }
            } finally {
              buf.release();
            }
          }
        }
      } else {
        logger.debug("UpgradeHandler returned a null NettyWebSocket ");
      }
    } else {
      logger.error("Invalid message {}", e);
    }
  }