Alexander Shorin avatar Alexander Shorin committed dff3c48

Preserve application and request contexts on dispatching response

Comments (0)

Files changed (2)

xmppflask/server.py

 
 JID = namedtuple('JID', 'user,domain,resource')
 
+
 def make_event_id(prefix):
     return '%s_%s' % (prefix, str(uuid.uuid1()).split('-')[0])
 
+
 def maybe_unicode(value):
     if value is None:
         return value
         return None
     return unicode(value)
 
+
 class XmppWsgiServerInterface(object):
     """Base XMPP interface for server."""
     #: Proxy to XMPP module. For interface internal usage only.
 
     def __init__(self, app, xmpp_interface):
         self.app = app
+        self.app_ctx = app.app_context()
         self.xmpp = xmpp_interface
         self.xmpp.register_handler('message', self.handle_message)
         self.xmpp.register_handler('presence', self.handle_presence)
     def serve_forever(self):
         self.xmpp.serve_forever()
 
+    def xmppwsgi_app(self, environ, notification_queue):
+        with self.app_ctx:
+            with self.app.request_context(environ):
+                response = self.app(environ, notification_queue)
+                self.dispatch_app_response(environ, response)
+
     def dispatch_app_response(self, environ, response):
         """Response object dispatcher."""
         rv = None
                     raise ValueError('unknown command %r' % cmd)
                 rv = func(environ, payload)
 
+    def process_notification_queue(self, queue):
+        for jid, resp in queue:
+            self.dispatch_app_response({'XMPP_JID': jid}, resp)
+
     def handle_message(self, message):
         """Handles message events."""
         environ = self.xmpp.make_environ(message)
         self.app.logger.debug(pformat(environ))
         if not environ['body']:
             return
-        if environ['XMPP_TIMESTAMP'] < time.time() - 3: # skip old messages
+        if environ['XMPP_TIMESTAMP'] < time.time() - 3:  # skip old messages???
             return
-        notification_queue = []
-        response = self.app(environ, notification_queue)
-        self.dispatch_app_response(environ, response)
-        for jid, resp in notification_queue:
-            self.dispatch_app_response({'XMPP_JID': jid}, resp)
+        queue = []
+        self.xmppwsgi_app(environ, queue)
+        self.process_notification_queue(queue)
 
     def send_message(self, environ, payload):
         """Sends XMPP messages.
         self.app.logger.debug(pformat(environ))
         if environ['from'] == environ['to']: # we don't want infinity loop there
             return
-        notification_queue = []
-        response = self.app(environ, notification_queue)
-        self.dispatch_app_response(environ, response)
-        for jid, resp in notification_queue:
-            self.dispatch_app_response({'XMPP_JID': jid}, resp)
+        queue = []
+        self.xmppwsgi_app(environ, queue)
+        self.process_notification_queue(queue)
 
     def send_presence(self, environ, payload):
         """Sends XMPP presence event.

xmppflask/tests/test_server.py

         self.assertEqual(payload['body'], 'PONG!')
         self.assertEqual(payload['type'], 'chat')
 
+    def test_preserve_req_ctx_for_generators(self):
+        app = self.server.app
+
+        @app.route('reqctx')
+        def reqctx():
+            from xmppflask import session
+            yield 'reqctx'
+            session.get('somevar')
+
+        environ = {'XMPP_JID': 'k.bx@ya.ru', 'MESSAGE': 'reqctx'}
+        self.server.xmppwsgi_app(environ, [])
+
+    def test_preserve_app_ctx_for_generators(self):
+        def appctx():
+            from xmppflask import g
+            yield 'appctx'
+            g.get('somevar')
+
+        environ = {'XMPP_JID': 'k.bx@ya.ru', 'MESSAGE': 'appctx'}
+        self.server.xmppwsgi_app(environ, [])
+
+
 if __name__ == '__main__':
     unittest.main()
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.