0

Using Python 3.9 and Quart 0.15.1, I'm trying to create a websocket route that will listen on a websocket for incoming request data, parse it, and send outbound response data to a client, over and over in a loop - until and unless the client sends a JSON struct with a given key "key" in the payload, at which point we can move on to further processing.

I can receive the initial inbound request from the client, parse it, and send outbound responses in a loop, but when I try to gather the second payload to parse for the presence of "key", things fall apart. It seems I can either await websocket.send_json() or await websocket.receive(), but not both at the same time.

The Quart docs suggest using async-timeout to (https://pgjones.gitlab.io/quart/how_to_guides/request_body.html?highlight=timeout) to timeout if the body of a request isn't received in the desired amount of time, so I thought I'd try to send messages in a while loop, with a brief period of time spent in await websocket.receive() before timing out if a response wasn't receive()'d:

@app.websocket('/listen')
async def listen():
    payload_requested = await websocket.receive()
    parsed_payload_from_request = json.loads(payload_requested)
    while "key" not in parsed_payload_from_request:
            response = "response string"
            await websocket.send_json(response)
            async with timeout (1):
                payload_requested = await websocket.receive()
                parsed_payload_from_request = json.loads(payload_requested)
    if "key" == "present": 
        do_stuff()

...but that doesn't seem to work, an asyncio.exceptions.CancelledError is thrown by the timeout.

I suspect there's a better way to accomplish this using futures and asyncio, but it's not clear to me from the docs.

1 Answers1

0

I think your code is timing out waiting for a message from the client. You may not need it in this case.

I've tried to write out code as you've described your needs and got this,

@app.websocket('/listen')
async def listen():
    while True:
        data = await websocket.receive_json()
        if "key" in data:
            await websocket.send_json({"key": "response"})
        else:
            do_stuff()
            return # websocket closes

does it do what you want, if not what goes wrong?

pgjones
  • 6,044
  • 1
  • 14
  • 12