FastAPI browser demo¶
For the shared RPC walkthrough with framework tabs, see the quick start.
Install the server framework and optional Python client:
pip install 'wsrpc-asgi[fastapi,client]' uvicorn
FastAPI and a browser¶
The complete server is in examples/main/server.py.
It exposes uuid4, serves the bundled JavaScript client and a browser page.
Static paths are resolved relative to the example file, so the server does
not depend on the current directory.
import uuid
from pathlib import Path
from fastapi import FastAPI, WebSocket
from fastapi.staticfiles import StaticFiles
from wsrpc_asgi import STATIC_DIR, WebSocketAsync
class Socket(WebSocketAsync):
pass
async def get_random_uuid(socket: Socket) -> str:
return str(uuid.uuid4())
def create_app() -> FastAPI:
Socket.add_route("uuid4", get_random_uuid)
app = FastAPI()
@app.websocket("/ws/")
async def rpc(websocket: WebSocket):
await Socket.serve(websocket)
app.mount("/js", StaticFiles(directory=STATIC_DIR), name="js")
app.mount("/", StaticFiles(directory=Path(__file__).parent, html=True))
return app
app = create_app()
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="127.0.0.1", port=8000)
From this documentation checkout, after installing the ASGI library and FastAPI (see the framework guide):
uv run --no-sync python asgi/examples/main/server.py
Open http://127.0.0.1:8000/web-client.html. The browser connects to /ws/
and requests a UUID. Its source is:
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>WSRPC quick start</title>
<script src="/js/wsrpc.min.js"></script>
</head>
<body>
<label>UUID <input id="result" readonly></label>
<button id="generate" type="button">Generate UUID</button>
<p id="error" role="alert"></p>
<script>
const url = new URL("/ws/", window.location.href);
url.protocol = window.location.protocol === "https:" ? "wss:" : "ws:";
const rpc = new WSRPC(url.toString());
rpc.connect();
document.getElementById("generate").addEventListener("click", async () => {
document.getElementById("error").textContent = "";
try {
document.getElementById("result").value = await rpc.call("uuid4");
} catch (error) {
document.getElementById("error").textContent = error.message || String(error);
}
});
</script>
</body>
</html>
Python client¶
In another terminal run:
uv run --no-sync python asgi/examples/main/client.py
import asyncio
from wsrpc_asgi import WSRPCClient
async def main(endpoint: str = "ws://127.0.0.1:8000/ws/") -> None:
async with WSRPCClient(endpoint) as client:
print(await client.proxy.uuid4())
if __name__ == "__main__":
asyncio.run(main())
A peer can also expose callbacks. The larger
server demo calls the Python client’s joke route.
Run the server and client in separate terminals:
uv run --no-sync python asgi/examples/server.py
uv run --no-sync python asgi/examples/client.py
For Starlette, Django, Channels, Quart, Litestar, Falcon, Sanic, BlackSheep or a standalone endpoint see framework integrations.