tarasko / picows

Ultra-fast websocket client and server for asyncio
MIT License
134 stars 8 forks source link

How to send str json format ping #20

Open River-Shi opened 6 hours ago

River-Shi commented 6 hours ago

It seems bybit requires user to send custom ping in str type not byte type.

image

Its offical sdk using self.custom_ping_message = json.dumps({"op": "ping"}) which returns a str type. However, I am using orjson.dumps({"op": "ping"} which returns byte type and the websocket will return b'\x03\xe9'. How to solve it?

class Listener(WSListener):
    def __init__(self, logger, specific_ping_msg: bytes = None):
        self._log = logger
        self.msg_queue = asyncio.Queue()
        self._specific_ping_msg = specific_ping_msg

    def send_user_specific_ping(self, transport: WSTransport):
        if self._specific_ping_msg:
            transport.send(WSMsgType.TEXT, self._specific_ping_msg)
        else:
            transport.send_ping()

    def on_ws_connected(self, transport: WSTransport):
        self._log.info("Connected to Websocket...")

    def on_ws_disconnected(self, transport: WSTransport):
        self._log.info("Disconnected from Websocket.")

    def on_ws_frame(self, transport: WSTransport, frame: WSFrame):
        try:
            if frame.msg_type == WSMsgType.PING:
                transport.send_pong(
                    frame.get_payload_as_bytes()
                )  # if enabled auto pong, we don't need to send pong manually
                return
            # msg = orjson.loads(frame.get_payload_as_bytes())
            self.msg_queue.put_nowait(
                frame.get_payload_as_bytes()
            )  # I think we should decode the frame in the handler
        except Exception as e:
            self._log.error(f"Error processing message: {str(e)}")

However, If I send json.dumps({"op": "ping"}), I got:

Traceback (most recent call last):
  File "picows/picows.pyx", line 1080, in picows.picows.WSProtocol._auto_ping_loop
  File "picows/picows.pyx", line 344, in picows.picows.WSListener.send_user_specific_ping
  File "/root/tradebot-pro/tradebot/base.py", line 371, in send_user_specific_ping
    transport.send(WSMsgType.TEXT, self._specific_ping_msg)
  File "picows/picows.pyx", line 453, in picows.picows.WSTransport.send
  File "picows/picows.pyx", line 473, in picows.picows.WSTransport.send
  File "picows/picows.pyx", line 154, in picows.picows._unpack_bytes_like
TypeError: a bytes-like object is required, not 'str'
River-Shi commented 6 hours ago

It seems bybit requires user to send custom ping in str type not byte type.

image

Its offical sdk using self.custom_ping_message = json.dumps({"op": "ping"}) which returns a str type. However, I am using orjson.dumps({"op": "ping"} which returns byte type and the websocket will return b'\x03\xe9'. How to solve it?

class Listener(WSListener):
    def __init__(self, logger, specific_ping_msg: bytes = None):
        self._log = logger
        self.msg_queue = asyncio.Queue()
        self._specific_ping_msg = specific_ping_msg

    def send_user_specific_ping(self, transport: WSTransport):
        if self._specific_ping_msg:
            transport.send(WSMsgType.TEXT, self._specific_ping_msg)
        else:
            transport.send_ping()

    def on_ws_connected(self, transport: WSTransport):
        self._log.info("Connected to Websocket...")

    def on_ws_disconnected(self, transport: WSTransport):
        self._log.info("Disconnected from Websocket.")

    def on_ws_frame(self, transport: WSTransport, frame: WSFrame):
        try:
            if frame.msg_type == WSMsgType.PING:
                transport.send_pong(
                    frame.get_payload_as_bytes()
                )  # if enabled auto pong, we don't need to send pong manually
                return
            # msg = orjson.loads(frame.get_payload_as_bytes())
            self.msg_queue.put_nowait(
                frame.get_payload_as_bytes()
            )  # I think we should decode the frame in the handler
        except Exception as e:
            self._log.error(f"Error processing message: {str(e)}")

However, If I send json.dumps({"op": "ping"}), I got:

Traceback (most recent call last):
  File "picows/picows.pyx", line 1080, in picows.picows.WSProtocol._auto_ping_loop
  File "picows/picows.pyx", line 344, in picows.picows.WSListener.send_user_specific_ping
  File "/root/tradebot-pro/tradebot/base.py", line 371, in send_user_specific_ping
    transport.send(WSMsgType.TEXT, self._specific_ping_msg)
  File "picows/picows.pyx", line 453, in picows.picows.WSTransport.send
  File "picows/picows.pyx", line 473, in picows.picows.WSTransport.send
  File "picows/picows.pyx", line 154, in picows.picows._unpack_bytes_like
TypeError: a bytes-like object is required, not 'str'

It is also wield, I receiving success ping message when sending byte type ping.

image image

But still receiving the b'\x03\xe9' and one successful ping return corresponds to the error message b'\x03\xe9'.