Search code examples
pythonredissocket.ioflaskgevent

Flask: Unable to access current_app from within socket.io listener


I am trying to access current_app from within the listener so that I can use app config values for which channel to subscribe to. However I receive "RuntimeError: working outside 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')

Solution

  • current_app is only valid while an HTTP request is being processed (it's a proxy that transiently points to the actual app object). You'll need to either get access to the actual app object from this module or steal a reference to it via current_app._get_current_object().