{"id":24732552,"url":"https://github.com/gonzalo123/asgi_ws","last_synced_at":"2026-04-20T06:02:55.147Z","repository":{"id":268695491,"uuid":"905174415","full_name":"gonzalo123/asgi_ws","owner":"gonzalo123","description":"Creating a standalone WebSocket Server with FastApi and JWT Authentication in Python","archived":false,"fork":false,"pushed_at":"2024-12-18T11:05:26.000Z","size":62,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-10-16T13:43:57.750Z","etag":null,"topics":["fastapi","jwt","python","websockets"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/gonzalo123.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-12-18T10:00:31.000Z","updated_at":"2025-03-01T13:59:10.000Z","dependencies_parsed_at":null,"dependency_job_id":"83a41fdb-19b4-4bd4-a71e-41fc3230b0d3","html_url":"https://github.com/gonzalo123/asgi_ws","commit_stats":null,"previous_names":["gonzalo123/asgi_ws"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/gonzalo123/asgi_ws","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gonzalo123%2Fasgi_ws","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gonzalo123%2Fasgi_ws/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gonzalo123%2Fasgi_ws/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gonzalo123%2Fasgi_ws/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/gonzalo123","download_url":"https://codeload.github.com/gonzalo123/asgi_ws/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gonzalo123%2Fasgi_ws/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32035276,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-20T00:18:06.643Z","status":"online","status_checked_at":"2026-04-20T02:00:06.527Z","response_time":94,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["fastapi","jwt","python","websockets"],"created_at":"2025-01-27T17:52:44.825Z","updated_at":"2026-04-20T06:02:55.125Z","avatar_url":"https://github.com/gonzalo123.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"## Creating a standalone WebSocket Server with FastApi and JWT Authentication in Python\n\nIn this post, I will show you how to create a WebSocket server in Python that uses JWT tokens for authentication. The server is designed to be independent of the main process, making it easy to integrate into existing applications. The client-side JavaScript will handle reconnections incrementally.\n\nThe WebSocket server will be created using FastApi, the web framework built on top of Starlette. This is the entrypoint.\n\n```python\nimport logging\n\nfrom fastapi import FastAPI\n\nfrom asgi_ws import setup_app\n\nlogging.basicConfig(\n    format='%(asctime)s [%(levelname)s] %(message)s',\n    level='INFO',\n    datefmt='%d/%m/%Y %X')\n\nlogger = logging.getLogger(__name__)\nSECRET_KEY = \"your_secret_key\"\n\napp = FastAPI()\n\napp = setup_app(\n    app=app,\n    base_path='/ws',\n    jwt_secret_key=SECRET_KEY,\n)\n```\n\nThe `setup_app` function is defined in the `lib.websockets` module. This function will set up the WebSocket server and the necessary routes.\n\n```python\ndef setup_app(app, jwt_secret_key: str, base_path='/ws', jwt_algorithm: str = \"HS256\"):\n    ws_router = get_ws_router(\n        jwt_secret_key=jwt_secret_key,\n        jwt_algorithm=jwt_algorithm,\n        base_path=base_path\n    )\n    current_dir = Path(__file__).parent\n    static_dir = current_dir / \"static/js\"\n\n    app.mount(\"/js\", StaticFiles(directory=static_dir), name=\"js\")\n    app.include_router(ws_router)\n\n    return app\n```\n\nThe `get_ws_router` function is defined in the same module. This function will create the WebSocket router and the necessary routes.\n\n```python\ndef get_ws_router(jwt_secret_key: str, base_path='ws', jwt_algorithm: str = \"HS256\"):\n    ws_router = APIRouter()\n\n    current_dir = Path(__file__).parent\n    static_dir = current_dir / \"static/js\"\n    ws_router.mount(f\"{base_path}/js\", StaticFiles(directory=static_dir), name=\"js\")\n\n    manager = ConnectionManager(jwt_secret_key=jwt_secret_key, jwt_algorithm=jwt_algorithm)\n\n    @ws_router.post(f\"{base_path}/emmit\")\n    async def emmit_endpoint(request: Request):\n        payload = await request.json()\n        await manager.broadcast(payload[\"channel\"], payload[\"payload\"])\n        return True\n\n    @ws_router.websocket(f\"{base_path}/\")\n    async def websocket_endpoint(websocket: WebSocket):\n        token = websocket.query_params.get(\"token\")\n        if not token:\n            await websocket.close(code=1008)\n            raise HTTPException(status_code=401, detail=\"Token required\")\n\n        await manager.connect(websocket, token)\n        try:\n            while True:\n                message: Message = await websocket.receive()\n                if message[\"type\"] == \"websocket.disconnect\":\n                    manager.disconnect(websocket)\n                    break\n        except WebSocketDisconnect:\n            manager.disconnect(websocket)\n\n    return ws_router\n```\n\nWebsockets are bidirectional communication channels that allow real-time data transfer between clients and servers, but I prefer to avoid the communication from the client to the server. When a client wants to send a message to the server, it will send an HTTP POST request to the `/emit` endpoint (via the main process). The server will then broadcast the message to all connected clients. The client will only receive messages from the server. Because of that we need a main wsgi process using FastApi or another web framework to handle the HTTP requests. \n\nThis an example with FastApi:\n\n```html\n\u003c!DOCTYPE html\u003e\n\u003chtml\u003e\n\u003chead\u003e\n    \u003ctitle\u003eChat\u003c/title\u003e\n\u003c/head\u003e\n\u003cbody\u003e\n\u003ch1\u003eWebSocket Chat\u003c/h1\u003e\n\n\u003cinput type=\"text\" id=\"messageText\" autocomplete=\"off\"/\u003e\n\u003cbutton onclick=\"sendMessage()\"\u003eSend\u003c/button\u003e\n\n\u003cul id='messages'\u003e\n\u003c/ul\u003e\n\u003cscript src=\"//localhost:8000/js/websockets.js\"\u003e\u003c/script\u003e\n\u003cscript\u003e\n    async function sendMessage() {\n        const channel = 'chat';\n        const url = `/emit/${channel}`;\n        const input = document.getElementById(\"messageText\");\n        const message = input.value;\n        input.value = '';\n        const body = JSON.stringify({channel: 'chat1', payload: message});\n        const headers = {'Content-Type': 'application/json'};\n\n        try {\n            const response = await fetch(url, {method: 'POST', headers: headers, body: body});\n        } catch (error) {\n            console.error('Error:', error);\n        }\n    }\n\n    (async function () {\n        const getToken = async () =\u003e {\n            const response = await fetch('/token');\n            const {token} = await response.json();\n            return token;\n        };\n\n        const messageCallback = (event) =\u003e {\n            const messages = document.getElementById('messages');\n            const message = document.createElement('li');\n            message.textContent = event.data;\n            messages.appendChild(message);\n        };\n\n        const wsManager = new WebSocketManager('ws://localhost:8000/ws/', getToken, messageCallback);\n        await wsManager.connect();\n    })();\n\n\u003c/script\u003e\n\u003c/body\u003e\n\u003c/html\u003e\n```\n\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgonzalo123%2Fasgi_ws","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgonzalo123%2Fasgi_ws","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgonzalo123%2Fasgi_ws/lists"}