Skip to content

websockets

Uses the websockets.asyncio server from websockets 13 and later.

import asyncio

from websockets.asyncio.server import ServerConnection, serve

from jsonrpcserver import Result, Success, async_dispatch, method


@method
async def ping() -> Result:
    return Success("pong")


async def handler(websocket: ServerConnection) -> None:
    async for message in websocket:
        request = message.decode() if isinstance(message, bytes) else message
        # Unlike HTTP, there's no need to answer a notification.
        # max_batch_size: see the Security page.
        if response := await async_dispatch(request, max_batch_size=100):
            await websocket.send(response)


async def main() -> None:
    # A bigger message closes the connection. The default is 1 MiB.
    async with serve(handler, "localhost", 8000, max_size=1_000_000) as server:
        await server.serve_forever()


if __name__ == "__main__":
    asyncio.run(main())

Unlike HTTP, a WebSocket doesn't need an answer to every message, so a notification gets nothing back. websockets closes the connection if a message is bigger than max_size. Its default is 1 MiB (1,048,576 bytes). The example sets 1,000,000, like the other examples. max_batch_size limits how many requests one batch can hold. See Security.

Requests on one connection are handled one at a time, in the order they arrive. To answer them concurrently, start a task for each message.

Try it

Save the example as websockets_server.py, install websockets (pip install websockets), and run it:

python websockets_server.py

websockets comes with an interactive client. Run python -m websockets ws://localhost:8000/ in another terminal and type a request, such as {"jsonrpc": "2.0", "method": "ping", "id": 1}.

From Python, jsonrpcclient's websockets example calls this server.