heroku-python / flask-sockets

[DEPRECATED] Alternative: https://github.com/miguelgrinberg/flask-sock
MIT License
1.74k stars 164 forks source link

Suggestion: Access 'ws' out of context #27

Closed colin-riddell closed 8 years ago

colin-riddell commented 9 years ago

I think it would be really useful to allow use of the ws object (which I believe is the request.environ['wsgi.websocket'] ws object for a given route? ) outside of route functions.

My idea was to store the value from request.environ['wsgi.websocket'] into a dict in Socket object like: environment = environ['wsgi.websocket'] self.ws.url_ep_map[path] = environment

I would like to make a PR for this feature but couldn't get it to work. Please see a diff of my attempt and point out anything that could be done to make this work. I tried to make use of @ copy_current_request_context then pass the request into route() - then grab the ws from that, but doesn't work.

diff --git a/flask_sockets.py b/flask_sockets.py
index 0b74dc0..9e87c07 100644
--- a/flask_sockets.py
+++ b/flask_sockets.py
@@ -1,4 +1,5 @@
 # -*- coding: utf-8 -*-
+from flask import request, copy_current_request_context

 def log_request(self):
     log = self.server.log
@@ -36,6 +37,7 @@ class SocketMiddleware(object):
             handler = self.ws.url_map[path]
             environment = environ['wsgi.websocket']

+            self.ws.url_ep_map[path] = environment
             handler(environment)
             return []
         else:
@@ -46,22 +48,28 @@ class Sockets(object):

     def __init__(self, app=None):
         self.url_map = {}
+        self.url_ep_map = {}
         if app:
             self.init_app(app)

     def init_app(self, app):
         app.wsgi_app = SocketMiddleware(app.wsgi_app, self)

-    def route(self, rule, **options):
+    def route(self, rule, request, **options):

         def decorator(f):
             endpoint = options.pop('endpoint', None)
-            self.add_url_rule(rule, endpoint, f, **options)
+            @copy_current_request_context
+            def do_some_work():
+                env = request.environ['wsgi.websocket']
+                self.add_url_rule(rule, endpoint, f,env, **options)
+            gevent.spawn(do_some_work)
             return f
         return decorator

-    def add_url_rule(self, rule, _, f, **options):
+    def add_url_rule(self, rule, _, f,env, **options):
         self.url_map[rule] = f
+        self.url_ep_map[rule] = env

 # CLI sugar.
 if 'Worker' in locals():
kennethreitz commented 8 years ago

You need a WSGI context in order to access the environ that we are calling ws, as that code-path would need to be within the context of a request.