Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Grequests incompatible with Flask-SocketIO #290

Closed
ocervell opened this issue Jul 26, 2016 · 2 comments
Closed

Grequests incompatible with Flask-SocketIO #290

ocervell opened this issue Jul 26, 2016 · 2 comments
Labels

Comments

@ocervell
Copy link

ocervell commented Jul 26, 2016

Hi,

I am not able to make asynchronous requests with grequests from inside a socket.

My code is the following:

@socketio.on('api_query', namespace='/display')
def get_api(data):
    urls = get_urls(data)
    namespace = '/display'
    flask_context = {
        'app': app,
        'request': request,
        'sid': request.sid,
        'namespace': namespace
    }
    def hook_req(response, *args, **kwargs):
        if response.status_code != 200:
            logger_ui.error('%s | Receive API response failure' % response.status_code)
            return
        data = {
          'api_call': SOLID*2 + "<br>- " + response.url + "<br>" + SOLID*2,
          'response': response.json()
        }
        emit_with_context(flask_context, 'api_response', data)
    (grequests.get(u, hooks={'response': hook_req}, auth=(session['token'], '')) for u in urls)
    emit('end_stream')

def emit_with_context(flask_context, event, data={}):
    """ Send through SocketIO a message named 'event' with 'data' as a content.
    """
    if flask_context is None:
        return
    from flask.ext.socketio import emit
    app = flask_context['app']
    namespace = flask_context['namespace']
    sid = flask_context['sid']
    with app.test_request_context():
        request = flask_context['request']
        request.sid = sid
        if data:
            emit(event, data, namespace=namespace)
        else:
            emit(event, namespace=namespace)

This code works perfectly using requests module but I need asynchronous calls to speed up things. When I switch to grequests my API backend doesn't receive the requests anymore. My backend is able to receive asynchronous requests.

I'm running Flask-SocketIO with gevent.

Initially I thought this was related to #55 but it's been fixed and I'm running the Flask server without debug mode.

Any idea ?

@ocervell
Copy link
Author

ocervell commented Jul 26, 2016

I replaced grequests by unirest and it now works perfectly. I had to add the following on top of my file so that the emit_with_context calls would not block:

import eventlet
eventlet.monkey_patch()

New code is the same except that the following:
(grequests.get(u, hooks={'response': hook_req}, auth=(session['token'], '')) for u in urls)

has been replaced by:

for u in urls:
        unirest.get(u, callback=hook_req, auth=(session['token'], ''))

@miguelgrinberg
Copy link
Owner

@ocervell the problem is in the emit_with_context. You are using a test request context in there, that does not have enough information to make the emit() function work correctly.

Instead of emit() which is context-dependent, try using socketio.emit() and including the sid of the user or room you want to emit to. That should work even w/o a Flask context.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants