nginxflaskglobal-variablesgunicorn

Global variables in Flask fail with nginx


The following script is an attempt to run python random module with flask. The app works fine when served via gunicorn:

gunicorn --bind 0.0.0.0:5000 wsgi:app

On the contrary, when allowing web requests through nginx, validation fails. What happens is that a new secret number is generated, thus causing a systematic discrepancy between the entered number and the stored one.

My question: what could be going wrong with nginx whereas the code works fine as tested with gunicorn? I am not aware of any errors stemming from the log files.

The Flask view

app = Flask(__name__)

def gen_secret_number():
    return random.randint(1, 100)
    
secret_number = gen_secret_number()

@app.route('/', methods=['GET', 'POST'])
def guess_number():
    
    if request.method == 'POST':
        entered_value = int(request.form['number'])

        if entered_value == secret_number:
            message = "Well done"
            return render_template('index.html', message=message)
        elif entered_value < secret_number:
            message = "Too small"
        else:
            message = "Too big"
        return render_template('index.html', secret_number=secret_number, message=message)

    return render_template('index.html', secret_number=secret_number, message=None)

@app.route('/reset', methods=['POST'])
def reset():
    global secret_number
    secret_number = gen_secret_number()
    return redirect(url_for('guess_number'))

if __name__ == '__main__':
    app.run(debug=True)

The form:

<form method="post" action="{{ url_for('guess_number') }}">
    <label for="number">Enter your number :</label>
    <input type="number" id="number" name="number" required>
    <button type="submit">Guess</button>
    <h4>{{ secret_number}}</h4>
</form>

<form method="post" action="{{ url_for('reset') }}">
    <button type="submit">Restart</button>
</form>

Solution

  • In order to close the issue, I am going to answer myself, after being guided by the comment of @Sandeep Kulkarni. On the main view function (guess_number()), one should add:

    if 'secret_number' not in session:
        session['secret_number'] = gen_secret_number()
    

    In the reset function, one should replace global secret_number with session.pop('secret_number', None) in order to start with a new number.

    I would also recommend the reading of Handling Global Variables in Flask.