@Override
  public void onError(NettyResponseFuture<?> future, Throwable e) {
    logger.warn("onError {}", e);

    try {
      WebSocketUpgradeHandler h = (WebSocketUpgradeHandler) future.getAsyncHandler();

      NettyWebSocket webSocket = NettyWebSocket.class.cast(h.onCompleted());
      if (webSocket != null) {
        webSocket.onError(e.getCause());
        webSocket.close();
      }
    } catch (Throwable t) {
      logger.error("onError", t);
    }
  }
  @Override
  public void onClose(NettyResponseFuture<?> future) {
    logger.trace("onClose");

    try {
      WebSocketUpgradeHandler h = (WebSocketUpgradeHandler) future.getAsyncHandler();
      NettyWebSocket webSocket = NettyWebSocket.class.cast(h.onCompleted());

      logger.trace("Connection was closed abnormally (that is, with no close frame being sent).");
      if (webSocket != null)
        webSocket.close(
            1006, "Connection was closed abnormally (that is, with no close frame being sent).");
    } catch (Throwable t) {
      logger.error("onError", t);
    }
  }
  @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);
    }
  }