Skip to content

WebSocket

spangle supports WebSocket connection.

WebSocket view class

You can define a WebSocket endpoint the same as HTTP endpoint, but the name is on_ws .

@api.route("/websocket/{name}", routing="clone")
class WebSocket:
    async def on_ws(self, conn):
        name = use_params()["name"]
        await conn.accept()
        await conn.send(f"hello, {name}!")
        while True:
            data = await conn.receive(str)
            if data == "end":
                break
            await conn.send(f"you said `{data}` .")
        await conn.send("bye.")
        await conn.close(1000)

Note

HTTP Upgrade Request is processed in an ASGI server, so you don’t need to send 101 Switching Protocols manually.

Error handling for WebSocket

You can process WebSocket errors with ErrorHandler.

@api.handle(TypeError)
class Handler:
    async def on_ws_error(self, conn, e:TypeError):
        await conn.send("Invalid data.")
        await conn.close(1007)

Before and After WebSocket connection

Hooks before/after WebSocket connection.

@api.before_requesst
class CalledBefore:
    async def on_ws(self, conn):
        conn.state.value = 42

@api.after_requesst
class CalledAfter:
    async def on_ws(self, conn):
        conn.state.done = True

Note that after_request hooks are called after connection closing.

WebSocket Testing

WebSocket test cllient is also available.

async with api.client() as client:
    async with client.ws_connect("/websocket/spam") as connection:
        data = await connection.receive(str)
        assert data == "hello, spam!"
        await connection.send("async!")
        data = connection.receive(str)
        assert data == "you said `async!` ."