0

Warning: Apologies for the long post

We are currently running a flask server with a couchdb backend. We have a few API endpoints that provide user information. We've used flask-login for user management. THe user_loader checks the user database on each request:

@login_manager.user_loader
def load_user(id):
    mapping = g.couch.get('_design/authentication')
    mappingDD = ViewDefinition('_design/authentication','auth2',mapping['views']['userIDMapping']['map'])
    for row in mappingDD[id]:
        return userModel.User(row.value)

We also have a segment that has a websocket to enable chat between the server and the client. The code below I took after seeing the authentication section of the flask-socketio documentation:

def authenticated_only(f):
    @functools.wraps(f)
    def wrapped(*args, **kwargs):
        if not current_user.is_authenticated:
            disconnect()
        else:
            return f(*args, **kwargs)
    return wrapped

I have the following code for my web socket:

@app.route('/sampleEndPoint/')
def chatRoom():
    return render_template('randomIndex.html', async_mode=socketio.async_mode)

@socketio.on('connect', namespace='/test')
@authenticated_only
def test_connect():
    app.logger.debug(session)
    emit('my_response', {'data': 'Connected'})

@socketio.on('disconnect_request', namespace='/test')
@authenticated_only
def disconnect_request():
    session['receive_count'] = session.get('receive_count', 0) + 1
    emit('my_response',{'data': 'Disconnected!', 'count': session['receive_count']})
    disconnect()

@socketio.on('disconnect', namespace='/test')
@authenticated_only
def test_disconnect():
    print('Client disconnected', request.sid)

Everything works well in the other routes. However, I get the following error when I connect to the websocket:

File "/home/sunilgopikrishna/insurance_brokerage/perilback/main.py", line 144, in load_user mapping = g.couch.get('_design/authentication') File "/home/sunilgopikrishna/.local/lib/python3.5/site-packages/werkzeug/local.py", line 343, in getattr return getattr(self._get_current_object(), name) AttributeError: '_AppCtxGlobals' object has no attribute 'couch'

I read in the flask-socketio documentation that login_required does not work with socketio.

Is there a workaround for this? Any help is appreciated.

Regards, Galeej

galeej
  • 535
  • 9
  • 23

1 Answers1

1

I read in the flask-socketio documentation that login_required does not work with socketio

Sure, but you are not using login_required in your socketio events, so that is not the problem here.

The problem is that you probably have a before_request handler that sets g.couch. The "before" and "after" handlers only run for HTTP requests, they do not run for Socket.IO, because in this protocol there is no concept of requests, there is just a single long-term connection.

So basically, you need to find another way to access your database connection in your user loader handler that does not rely on a before_request handler.

Miguel Grinberg
  • 65,299
  • 14
  • 133
  • 152
  • Hi Miguel, I went through some of your answers on the github repo... I did the following: 1. I first removed the url for the websocket in the user_loader to disable the websocket hitting the user_loader everytime and 2. I removed all forms of authentication and stored the necessary variables as session variables. Since a user has to login when he/she hits the websocket, things are ok for now :). – galeej Feb 28 '17 at 08:17