在 nginx 反向代理后面处理 flask url_for
Handling flask url_for behind nginx reverse proxy
我有一个使用 nginx 进行反向 proxy/ssl 终止的 Flask 应用程序,但是在使用 url_for 并在 Flask 中重定向时我 运行 遇到了麻烦。
nginx.conf条目:
location /flaskapp {
proxy_pass http://myapp:8080/;
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
这个想法是用户导航到
https://localhost:port/flaskapp/some/location/here
并且应该作为
传递给烧瓶
http://localhost:8080/some/location/here
这在导航到定义的路线时相当有效,但是如果路线有 redirect(url_for('another_page'))
,浏览器将定向到
http://localhost:8080/another_page
失败了,当我真正想去的 URL 是:
https://localhost:port/flaskapp/another_page
我已经针对类似情况尝试了其他几个答案,但 none 似乎正在做我在这里所做的事情。我曾尝试使用 _external=True
、设置 app.config['APPLICATION_ROOT'] = '/flaskapp'
以及 nginx.conf
中不同 proxy_set_header
命令的多次迭代,但没有成功。
更复杂的是,我的 Flask 应用程序正在使用 flask-login
和 CSRF cookie。当我尝试设置 APPLICATION_ROOT
时,应用程序停止考虑由 flask-login
设置的 CSRF cookie 有效,我认为这与起源有关。
所以我的问题是,我该怎么做才能让 flask 向客户端返回 redirect()
时,nginx 明白给定的 URL 需要写入 flaskapp
进去了吗?
我设法通过一些更改修复它。
更改 1. 将 /flaskapp 添加到我的 flask 应用程序的路由中。这消除了 URL 重写的需要并大大简化了事情。
更改 2。nginx.conf 更改。我在位置块中添加了 logc 以将 http 请求重定向为 https,新的 conf:
location /flaskapp {
proxy_pass http://myapp:8080/;
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# New configs below
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Proto $scheme;
# Makes flask redirects use https, not http.
proxy_redirect http://$http_host/ https://$http_host/;
}
虽然我没有"solve"引入基于已知前缀的条件重写的问题,因为我只需要这个应用程序的一个前缀,所以将它烘焙到路由中是一种可接受的解决方案。
在你的情况下,我认为正确的做法是使用 werkzeug 的 ProxyFix 中间件,并让你的 nginx 代理设置适当的要求 headers(特别是 X-Forwarded-Prefix)。
这应该会使 url_for 像您预期的那样工作。
编辑:@Michael P 的回答片段
from werkzeug.middleware.proxy_fix import ProxyFix
app = Flask(__name__)
app.wsgi_app = ProxyFix(app.wsgi_app, x_for=1, x_host=1)
我有一个使用 nginx 进行反向 proxy/ssl 终止的 Flask 应用程序,但是在使用 url_for 并在 Flask 中重定向时我 运行 遇到了麻烦。
nginx.conf条目:
location /flaskapp {
proxy_pass http://myapp:8080/;
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
这个想法是用户导航到
https://localhost:port/flaskapp/some/location/here
并且应该作为
传递给烧瓶http://localhost:8080/some/location/here
这在导航到定义的路线时相当有效,但是如果路线有 redirect(url_for('another_page'))
,浏览器将定向到
http://localhost:8080/another_page
失败了,当我真正想去的 URL 是:
https://localhost:port/flaskapp/another_page
我已经针对类似情况尝试了其他几个答案,但 none 似乎正在做我在这里所做的事情。我曾尝试使用 _external=True
、设置 app.config['APPLICATION_ROOT'] = '/flaskapp'
以及 nginx.conf
中不同 proxy_set_header
命令的多次迭代,但没有成功。
更复杂的是,我的 Flask 应用程序正在使用 flask-login
和 CSRF cookie。当我尝试设置 APPLICATION_ROOT
时,应用程序停止考虑由 flask-login
设置的 CSRF cookie 有效,我认为这与起源有关。
所以我的问题是,我该怎么做才能让 flask 向客户端返回 redirect()
时,nginx 明白给定的 URL 需要写入 flaskapp
进去了吗?
我设法通过一些更改修复它。
更改 1. 将 /flaskapp 添加到我的 flask 应用程序的路由中。这消除了 URL 重写的需要并大大简化了事情。
更改 2。nginx.conf 更改。我在位置块中添加了 logc 以将 http 请求重定向为 https,新的 conf:
location /flaskapp {
proxy_pass http://myapp:8080/;
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# New configs below
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Proto $scheme;
# Makes flask redirects use https, not http.
proxy_redirect http://$http_host/ https://$http_host/;
}
虽然我没有"solve"引入基于已知前缀的条件重写的问题,因为我只需要这个应用程序的一个前缀,所以将它烘焙到路由中是一种可接受的解决方案。
在你的情况下,我认为正确的做法是使用 werkzeug 的 ProxyFix 中间件,并让你的 nginx 代理设置适当的要求 headers(特别是 X-Forwarded-Prefix)。
这应该会使 url_for 像您预期的那样工作。
编辑:@Michael P 的回答片段
from werkzeug.middleware.proxy_fix import ProxyFix
app = Flask(__name__)
app.wsgi_app = ProxyFix(app.wsgi_app, x_for=1, x_host=1)