Search code examples
pythonnginxflaskhttp-status-code-403production

root Flask app route hits 403 forbidden in production (nginx, uwsgi)


Basically I have a single views.py with all my routes in it. They all work great on production except for one... the homepage at the root location '/'

from views.py

@app.route('/', methods = ['GET'])
def homepage():

    return render_template("/client/homepage.html")

@app.route('/admin/', methods = ['GET'])
@login_required
def admin():

    submissions = Campaign.query.all()

    return render_template("admin.html",
        title = 'Admin',
        submissions = submissions)

Instead of displaying the page, I get a 403 forbidden message.

From the nginx logs:

directory index of "/srv/www/cc/app/" is forbidden

Anyone know what's wrong with my flask route which would cause this change in behavior from '/admin/' to '/'?

EDIT

I've found multiple posts online about this issue, and one of the suggestions was to turn autoindex on within nginx. I did this, and it gave me a directory of the root location... which makes me think that the issue may be that nginx simply isn't passing the request to uwsgi. But i'm not sure what to do about that.


Solution

  • Turned out it was the way I'd written my nginx.conf.

    After pouring over the documentation on try_files, It became apparent to me that i needed to simply add

    error_page 403 = @cc;

    to my location block. The reason being apparently that the try_files directive will try to match each request directly in the order in which they're listed, so in my case my location @cc was the last. Nginx was finding a match for / and only / based on the $uri, and was then trying to display the page accordingly. Since I have all my uwsgi stuff in my @cc location, I had to redirect the request there with the error_page 403 = @cc; bit.

    Here's the final product:

    nginx.conf

    server {
        listen      80;
        server_name localhost;
        charset     utf-8;
        client_max_body_size 5M;
        root /srv/www/cc/app;
    
        location / { 
            try_files $uri $uri/ @cc;
            error_page 403 = @cc;
        }
        location /uploads/ {
            expires max;
        }
        location /static/ {
            expires max;
        }
        location @cc {
            include uwsgi_params;
            uwsgi_pass unix:/tmp/uwsgi.sock;
        }
    }