Flask 在 gunicorn + nginx 下的 redirect(url_for) 错误

18 投票
5 回答
14785 浏览
提问于 2025-04-17 21:42

我在我的Flask应用中遇到了一个关于重定向(redirect(url_for))的问题。

每当我使用重定向,比如写成redirect(url_for("index"))时,应用就会从domain.com/app跳转到ip-addr/app,而这个ip-addr是我自己电脑的IP地址,而不是服务器的地址。

这让我非常困惑,我不知道问题到底出在哪里,因为这个问题只在服务器上出现,而在本地测试时没有任何问题。

具体情况:

我使用的是这里找到的反向代理设置 http://flask.pocoo.org/snippets/35/。我的nginx配置是这样的:

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/;
        }

我用gunicorn来运行我的Flask应用,作为一个upstart任务。有没有什么提示可以帮助我解决这个问题?

补充:

我稍微查了一下,发现这个git报告也有类似的问题,https://github.com/omab/django-social-auth/issues/157

Nginx - Gunicorn通过本地地址(127.0.0.1:1234)服务给Nginx。不幸的是,当我通过社交平台进行身份验证时,社交认证发送的重定向URL是127.0.0.1:1234/twitter/complete,这显然无法被客户端的浏览器解析。

看起来我的Flask应用没有收到更新重定向路由的通知。

5 个回答

-1

我遇到过类似的问题。当我用gunicorn运行我的服务器时,它在执行@return redirect(url_for(‘login’))的时候崩溃了。想要解决这个问题,可以去看看这个链接:Flask应用在用gunicorn和nginx运行时在重定向时崩溃

1

我在这个问题上花了两个晚上,最后用这个方法解决了它:http://blog.macuyiko.com/post/2016/fixing-flask-url_for-when-behind-mod_proxy.html,我的代理设置如下:

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

而且ReverseProxy类运行得非常好,关键在于“script_name”,这个在这里的代码片段中并没有包含:http://flask.pocoo.org/snippets/35/。我猜flask页面上的代码片段是适用于ngnix的,而这个是针对apache2代理的。如果有人再次遇到同样的问题,希望这能帮到你(包括未来的我)

5

我也遇到过同样的问题。你的解决方案需要让应用程序知道它运行在哪个域名下,这就需要为每个环境设置一个配置变量。我发现这里的解决办法其实是重新写nginx的proxy_pass头部,像这样:

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;
   }
16

我找到了解决办法。我需要对所有的重定向使用 redirect(url_for(location, _external=True))

看起来 url_for(x, _external=True) 会把我在 nginx 里设置的所有变量都用来构建网址,而 url_for(x) 则没有这样做。

这个方法在服务器和本地开发中都有效。

12

加上 include proxy_params 解决了我的问题。

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

撰写回答