4

When a user logs into my sample application I add a username key into the session object and I hang a user object off of the global "g" object. See below.

@app.route('/login/', methods=['GET', 'POST'])
def login():
    """Logs the user in."""

    error = None
    if request.method == 'POST':
        print("login hit")
        user = get_user(request.form['username'])
        if user is None:
            error = 'Invalid username'
            print error
        elif not check_password_hash(user.password, request.form['password']):
            error = 'Invalid password'
            print error
        else:
            flash('You were logged in')
            print "logged in"
            session['username'] = request.form['username']
            g.user = request.form['username']
            print error, "error"
            return redirect(url_for('main'))

Now, if the user logs in successfully (which is what is happening), he will redirect to the main page. This will teardown the old request and spawn a new one. The problem is that when a new request starts the session is wiped. I am printing out the session keys and they are all empty. This only happens on heroku, not on my local machine. What am I doing wrong.

  @app.before_request
    def before_request():
        print session.keys(), session.values()  # shows [] []
        print("before request")
        print ('username' in session, "in session?")
        g.db = connect_db()
        g.user = None
        if "username" in session:
            g.user = get_user(session['username'])
The Internet
  • 7,959
  • 10
  • 54
  • 89
  • The issue was gunicorn. Once I removed that, heroku ran the app fine. – The Internet Nov 29 '12 at 20:03
  • 1
    Did you use gunicorn with multiple workers? If that's the case sessions simply won't transfer between different workers. You'd need some kind of middle layer storage, like Redis, to handle sessions across multiple workers/servers. This is something you should do anyway as scaling the application would be impossible with just one worker on one server. – moodh Nov 30 '12 at 10:59
  • Yes, I think there were multiple workers. It spawned multiple process threads. I'm unsure how to use redis with gunicorn. Any advice on where to start? I don't expect this app to scale much. – The Internet Nov 30 '12 at 22:08
  • @TheInternet I'm new to flask and I might be having similar problems with you. Which alternative to gunicorn did you use? Can you provide links on how to set that up? – krato Sep 27 '16 at 11:43

2 Answers2

6

Well, seeing as this indeed would be the answer due to multiple workers I'll move it from the comments part. :) You don't want redis at the gunicorn layer, rather in your application. These four links should help you out:

1) First, enable/install Redis in Heroku

2) Then check this out (will replace Flasks entire session driver with one based on redis): This might be overkill, I'd simply use redis as a key-storage value in the app (check my third link) but you might like this approach.

3) Not as related but shows some usage examples (queue system for flask with redis)

4) Basic redis tutorial for python

These three links should get you started, if it's not enough I'll dig up some more examples so just ask if you need them!

moodh
  • 2,661
  • 28
  • 42
1

try including this in you app.py

from flask import session
from flask_session import Session 
app.secret_key = 'A0AKR5TGD\ R~XHH!jmN]LWX/,?RT'
app.config["SESSION_PERMANENT"] = True
app.config["SESSION_TYPE"] = "filesystem"
Session(app)

don't provide any information about the directory

  • 1
    Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Dec 01 '21 at 03:10