I’m testing websockets to work with cookies and trying to get them in fast api. I manually installed them in chrome but I get an empty dictionary inside the application. I used the fast api documentation templates and slightly redesigned it
My html
html = """ <!DOCTYPE html> <html> <head> <title>Chat</title> </head> <body> <h1>WebSocket Chat</h1> <form action="" onsubmit="sendMessage(event)"> <label>Item ID: <input type="text" id="itemId" autocomplete="off" value="foo"/></label> <label>Token: <input type="text" id="token" autocomplete="off" value="some-key-token"/></label> <button onclick="connect(event)">Connect</button> <hr> <label>Message: <input type="text" id="messageText" autocomplete="off"/></label> <button>Send</button> </form> <ul id='messages'> </ul> <script> var ws = null; function connect(event) { var itemId = "1000" var token = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJfaWQiOiI2MjlmYmU3ZGNjMzQxMGFiNWE2MmZkOWYiLCJ1c2VyIjoiQmk4eVVhOG5TS1dFRm8weEJjYWkwRUtDU2E3TyJ9.7hE3qIcFoLLoDqQSliaHXhSPs4FW75fNafumPdKHPmI" ws = new WebSocket("ws://localhost:8000/ws/" + itemId + "/?token=" + token); ws.onmessage = function(event) { var messages = document.getElementById('messages') var message = document.createElement('li') var content = document.createTextNode(event.data) message.appendChild(content) messages.appendChild(message) }; event.preventDefault() } function sendMessage(event) { var input = document.getElementById("messageText") ws.send(input.value) input.value = '' event.preventDefault() } </script> </body> </html> """
My websocket
class ConnectionManager: def __init__(self): self.active_connections: list = [] async def connect(self, websocket: WebSocket): await websocket.accept() self.active_connections.append(websocket) def disconnect(self, websocket: WebSocket): self.active_connections.remove(websocket) async def send_personal_message(self, message: str, websocket: WebSocket): await websocket.send_text(message) async def broadcast(self, message: str): for connection in self.active_connections: await connection.send_text(message) manager = ConnectionManager() @app.websocket("/ws/{project_id}/") async def test_websocket(websocket: WebSocket, project_id: int, token: str = Depends(authorization.get_user_websocket_token) ): print(websocket.cookies) await manager.connect(websocket) try: while True: project = await db["storages"].find_one({"project_id": project_id}) if token in project["users"]: print(True) data = await websocket.receive_text() await manager.send_personal_message(f"You wrote: {data}", websocket) await manager.broadcast(f"Client says: {data}") except WebSocketDisconnect: manager.disconnect(websocket) await manager.broadcast(f"Client left the chat")
print(websocket.cookies) returns an empty dictionary {}
Advertisement
Answer
Cookies are domain-defined, so you should point at localhost:8000 and there define that Cookie, not 127.0.0.1:8000.
Maybe it’s easier to check them in Postman.
They will be available at websocket.cookies
for sure.
websocket.cookies
under the hood checks Cookie
header:
@property def cookies(self) -> typing.Dict[str, str]: if not hasattr(self, "_cookies"): cookies: typing.Dict[str, str] = {} cookie_header = self.headers.get("cookie") if cookie_header: cookies = cookie_parser(cookie_header) self._cookies = cookies return self._cookies