Skip to content
Advertisement

Can not get cookie from localhost websocket fast api

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

enter image description here

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.

With such crafted request: enter image description here

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
User contributions licensed under: CC BY-SA
8 People found this is helpful
Advertisement