Eventlet and Spotipy Authentication issue on heroku

63 views Asked by At

I am having an issue authenticating my user in my Heroku Flask application when my procfile contains

web: gunicorn --worker-class eventlet -w 1 app:app

If I change the procfile to the following I have no issue with the authentication.

web: gunicorn  app:app

Below is my code for authenticating the user. When using web: gunicorn --worker-class eventlet -w 1 app:app in my Procfile the user is redirected to a page like https://accounts.spotify.com/en/authorize?client_id=8247cd9f7e43..... and I receive an internal server error. When I change the Procfile to web: gunicorn app:app the user authenticates correctly and they are redirected to the home page.

@app.route('/', methods=['GET'])
def index():
    cache_handler = spotipy.cache_handler.FlaskSessionCacheHandler(session)
    auth_manager = spotipy.oauth2.SpotifyOAuth(scope='user-read-currently-playing playlist-modify-private',
                                               cache_handler=cache_handler,
                                               show_dialog=True)
    
    if 'code' in request.args:
        code = request.args['code']
        print("Code is", code)
        # Log a message
        logging.info("Code is %s", code)
        # Step 2. Being redirected from Spotify auth page
        auth_manager.get_access_token(code)
        logging.info("Code is %s", code)
     
    if not auth_manager.validate_token(cache_handler.get_cached_token()):
        # Step 1. Display sign-in link when no token
        auth_url = auth_manager.get_authorize_url()
        return f'<h2><a href="{auth_url}">Sign in</a></h2>'

    # Step 3. Signed in, display data
    spotify = spotipy.Spotify(auth_manager=auth_manager)
    # Render the index.html template with the text entry box, submit button, and Spotify data
    return render_template('index.html')

I am using Flask-SocketIO within this application so I need to be able to use eventlet. Any help would be appreciated. The issue doesn't appear to be the Redirect URI as it's working without eventlet.

1

There are 1 answers

0
mruss24 On BEST ANSWER

If you encounter conflicts between Flask-SocketIO (with Eventlet) and the Spotipy library, another approach you can try is to use the Gevent library. Gevent is another asynchronous library similar to Eventlet, and it might be more compatible with the requests library used by Spotipy.

Follow these steps to modify your Flask application to use Gevent:

1. Update Your Procfile: Modify your Procfile to use the Gevent worker with Gunicorn. Replace the existing contents of your Procfile with the following:

web: gunicorn -k geventwebsocket.gunicorn.workers.GeventWebSocketWorker -w 1 app:app

2. Install Gevent: You need to install gevent and gevent-websocket in your virtual environment. You can do this with pip:

pip install gevent gevent-websocket

3. Modify Your Flask Application: Initialize your SocketIO object with async_mode='gevent'. Also, perform monkey patching at the beginning of your application but use gevent instead of eventlet. Here's how your code might look:

import spotipy
from flask_socketio import send, emit, SocketIO
import logging
import gevent

socketio = SocketIO(app, async_mode='gevent')