Flask: unable to access current_app from inside socket.io listener

I am trying to access current_app from within the listener so that I can use the application configuration values ​​for which the channel must subscribe. However, I get "RuntimeError: working out of application context".

Here is the code in question:

from flask import Blueprint, Response, request, current_app from socketio import socketio_manage from socketio.namespace import BaseNamespace from redis import StrictRedis import pprint socketapp = Blueprint('socketapp', __name__) class MessageNamespace(BaseNamespace): def listener(self): pprint.pprint(current_app.config) r = StrictRedis() p = r.pubsub() p.subscribe('message-channel') messages = r.lrange('message', 0, -1) self.emit('message-message', ''.join(messages)) for m in p.listen(): if m['type'] == 'message': self.emit('message-message', m['data']) def on_subscribe(self): self.spawn(self.listener) @socketapp.route('/socket.io/<path:remaining>') def socketio(remaining): try: socketio_manage(request.environ, {'/messages': MessageNamespace}, request) except BaseException: pass return Response() @socketapp.route('/message', methods=['GET']) def say(): msg = request.args.get('msg', None) if msg: r = StrictRedis(host=current_app.config['REDIS_HOST']) r.rpush('message', msg) r.publish('message-channel', msg) return Response('Message sent!') else: return Response('Please specify your message in the "msg" parameter') 
+4
source share
2 answers

current_app is only valid when processing an HTTP request (this is a proxy that temporarily points to the actual application object). You need to either access the real application object from this module, or steal a link to it using current_app._get_current_object() .

+7
source

Sean's passage does not work for me. I wrote the following hack based on it:

 @bp.route('/<path:remaining>') def socketio(remaining): app = current_app._get_current_object() try: # Hack: set app instead of request to make it available in the namespace. socketio_manage(request.environ, {'': ChatNamespace}, app) except: app.logger.error("Exception while handling socket.io connection", exc_info=True) return Response() class ChatNamespace(BaseNamespace, RoomsMixin, BroadcastMixin): def __init__(self, environ, ns_name, request=None): self.context = None if request: # Hack: initialize context with app that was set instead of request. Then miss it in parent constructor call. app = request self.context = app.request_context(environ) self.context.push() app.preprocess_request() super(ChatNamespace, self).__init__(environ, ns_name) def log(self, message): # Now we can access app and other goodies. self.context.app.logger.info("[{0}] {1}".format(self.socket.sessid, message)) def disconnect(self, *args, **kwargs): if self.context: self.context.pop() super(ChatNamespace, self).disconnect(*args, **kwargs) 
+1
source

All Articles