Search code examples
pythonhttpwebsocketbottlegevent

Bottle-WebSocket: How to ensure an HTTP request is from the same session as ws connection?


I built an web application using Python Bottle framework. I used bottle-websocket plugin for WebSocket communication with clients. Here is a part of my code.

from bottle import Bottle, request, run
from bottle.ext.websocket import GeventWebSocketServer, websocket

class MyHandler():
    ...

class MyServer(Bottle):

    ...

    def _serve_websocket(self, ws):
        handler = MyHandler()
        some_data = request.cookies.get('some_key') # READ SOME DATA FROM HTTP REQUEST

        while True:
            msg = ws.receive()
            handler.do_sth_on(msg, some_data) # USE THE DATA FROM HTTP REQUEST
            ws.send(msg)

        del(handler)

if __name__ == '__main__':
    run(app=MyServer(), server=GeventWebSocketServer, host=HOST, port=PORT)

As the code shows, I need to read some data from the browser (cookies or anything in the HTTP request headers) and use it for WebSocket message processing.

How can I ensure the request is from the same browser session as the one where WebSocket connection comes?

NOTE

As I do not have much knowledge of HTTP and WebSocket, I'd love to here detailed answere as much as possible.


Solution

  • How can I ensure the request is from the same browser session as the one where WebSocket connection comes?

    Browser session is a bit abstract since HTTP does not have a concept of sessions. HTTP and RESTful APIs is designed to be stateless, but there is options.

    Usually, what you usually want to know is what user the request comes from. This is usually solved by authentication e.g. by using OpenID Connect and let the user send his JWT-token in the Authorization: header, this works for all HTTP requests, including when setting up a Websocket connection.

    bottle-oauthlib seem to be a library for authenticating end-users using OAuth2 / OpenID Connect.

    Another option is to identify the "browser session" using cookies but this depends on a state somewhere on the server side and is harder to implement on cloud native platforms like e.g. Kubernetes that prefer stateless workloads.