Question

I am having a problem with the redirect(url_for) function in my flask app.

Any redirect(url_for("index")) line redirects the application from domain.com/app to ip-addr/app, where the ip-addr is my own client machines ip, not the server's.

This has gotten me very confused, and I don't know where exactly the issue occurs, as it only happens on the server and not on any local testing.

Details:

I am using the reverse proxy setup found here http://flask.pocoo.org/snippets/35/. My nginx config is setup like so

location /app {
                proxy_set_header X-Script-Name /app;
                proxy_set_header Host $http_host;
                proxy_set_header X-Forwarded-Host $proxy_add_x_forwarded_for;
                proxy_redirect off;
                proxy_set_header X-Real-IP $remote_addr;
                proxy_set_header X-Scheme $scheme;
                proxy_connect_timeout 60;
                proxy_read_timeout 60;
                proxy_pass http://localhost:8000/;
        }

I have gunicorn running my flask app as a upstart task. Any hints?

EDIT:

So I dug around a bit and found that the this git report had similar issues, https://github.com/omab/django-social-auth/issues/157.

Nginx - Gunicorn serving to Nginx via localhost (127.0.0.1:1234). Unfortunately, when I authenticate with social platforms, the redirect URL social-auth is sending them to is 127.0.0.1:1234/twitter/complete, which obviously can't be resolved by the client's browser.

It seems my Flask app is not getting the memo to update its redirect routes.

Was it helpful?

Solution 2

Adding include proxy_params fixed it for me.

location / {
    proxy_pass http://...;
    include proxy_params;
}

OTHER TIPS

I found a solution. I had to use redirect(url_for(location, _external=True)) for all my redirects.

It seems url_for(x, _external=True) will take all variables in my nginx proxy_set_header to construct the url, while the url_for(x) is not doing that.

This works for both server and local development.

Had the same problem. Your solution is makes it necessary for the app to know which domain it's running by setting it on a config var for each environment. I found HERE that the solution is actually to rewrite the headers on nginx proxy_pass like so:

location /api {
       # Define the location of the proxy server to send the request to
       proxy_pass http://web:8000;

       # Redefine the header fields that NGINX sends to the upstream server
       proxy_set_header Host $host;
       proxy_set_header X-Real-IP $remote_addr;
       proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

       # Define the maximum file size on file uploads
       client_max_body_size 5M;
   }

I've lost 2 nights in this, I finally solved it using this solution: http://blog.macuyiko.com/post/2016/fixing-flask-url_for-when-behind-mod_proxy.html, my proxy settings:

ProxyPass /crm http://localhost:5013/
ProxyPassReverse /crm http://localhost:5013/

And the ReverseProxy class worked perfectly, the trick was the "script_name" that it's not originally included in the snippet from here: http://flask.pocoo.org/snippets/35/ I guess the snipped from flask page works with ngnix and this is for apache2 proxy. Hope this helps if someone comes here again with the same issue (future me included)

I had similar issue. My server was crashing at @return redirect(url_for(‘login’)), when I run it using gunicorn. For the solution go to Flask app running with gunicorn and nginx is crashing at redirecting point

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top