miguelgrinberg / flask-sock

Modern WebSocket support for Flask.
MIT License
274 stars 24 forks source link

@sock.before_request functionality #17

Closed dsposito-ubtech closed 2 years ago

dsposito-ubtech commented 2 years ago

For my app's HTTP API endpoints, I use @blueprintname.before_request() to easily perform common actions automatically for all requests (e.g., authorization validation). How might I do the same with flask-sock when a client first connects?

I didn't have any luck using @sock.before_request and @sock.bp.before_request().

I also tried looking at the source code to see if I could help add this functionality myself. Can someone point me in the right direction?

Thanks!

miguelgrinberg commented 2 years ago

If you have an app-level before request handler, it will also be invoked for your websocket routes.

Or are you thinking in a before request handler that is specific to WebSocket routes? That doesn't seem that useful to me, since the whole point of a before request handler is to avoid repeating code across endpoints. This is normally not the case with WebSocket, since you usually have a single WS route in your app.

dsposito-ubtech commented 2 years ago

@miguelgrinberg Interesting. My application has several dozen REST API endpoints and related UI views for viewing a list of users, list of tasks, a specific task, etc. What I'm interested in doing is "upgrading" some of the UI views to use websockets so the content gets updated in real-time (without polling or a page refresh).

My thought was to have separate websocket endpoints similar to my REST endpoints:

Then when a UI view loads (I'm using Vue.js), it would start a websocket connected to the relevant endpoint to get data specific for that view. The connection would persist until the user navigates to a different UI url - in which case a new WS connection would start related to that view.

Is that approach different from what you've typically done? Otherwise, with a single WS endpoint each client would need to somehow specify what kind of data it wants to receive when it connects (e.g., items list page only wants to receive items list data - not task data).

Appreciate your input and efforts with flask-sock!

miguelgrinberg commented 2 years ago

@dsposito-ubtech To me that is a strange approach, because you have an SPA, so you can have a single WebSocket connection that provides data to all your views. Closing and reopening a WebSocket is inefficient and somewhat approaches HTTP.

Otherwise, with a single WS endpoint each client would need to somehow specify what kind of data it wants to receive when it connects

In your solution the client still specifies what data it wants to receive in the connection URL. How is that any different than indicating what it wants in a WebSocket message?

dsposito-ubtech commented 2 years ago

Fair enough - that does seem more efficient! :+1:

I'll do some more research to figure out how best to do this. My initial thoughts: after each websocket client connects, it will send a message to the server to tell it which data "topics" it wants to subscribe to. So as the SPA url/view changes it would send a new websocket message to the server to update its list of subscriptions (e.g., "I'm now on the Tasks list page - send me that data and no longer the Users list data).

I'm also planning to look into Socket.io to see if that may help with managing the connections, topics/events, etc.

Thanks again for your input on this - really appreciate all that you do for the Python community!

miguelgrinberg commented 2 years ago

@dsposito-ubtech the subscription style usage is actually fairly common and has a solid foundation in the Observer pattern. That sounds like a great way to do what you need. 👍