当我在gunicorn上运行Flask应用程序时设置app.wsgi_app = ProxyFix(app.wsgi_app)会发生什么?

问题描述 投票:0回答:3

我使用 Flask 构建了一个基本的 Web 应用程序,并且能够使用其本机 http 服务器从虚拟机运行它。我很快意识到,通过这种设置,请求会被阻塞(我无法对资源发出并发请求;任何新请求都会等到较早的请求完成),并决定尝试使用gunicorn来运行应用程序来解决这个问题。我遵循了文档,特别是使用这一行运行:

gunicorn -w 4 -b 127.0.0.1:4000 myproject:app 

但是,这样做却无法启动,并抱怨没有 WSGI 应用程序。在网上查了一下,我发现很多人都发布了示例,包括以下内容:

from werkzeug.contrib.fixers import ProxyFix
app.wsgi_app = ProxyFix(app.wsgi_app)

我添加了这一点,它解决了我的问题。我很困惑,因为这显然是为了解决 HTTP 代理后面的服务问题,但是添加 Gunicorn 会强加 HTTP 代理吗?或者我总是在代理后面,而这对于 Flask 的内置服务器来说并不重要?

此外,Werkzeug 关于 Fixers 的文档警告“出于安全原因,请勿在非代理设置中使用此中间件。”考虑到修复显然是必要的,我可以假设我正在设置代理吗?

python flask wsgi gunicorn werkzeug
3个回答
7
投票

有点晚了,但是这里(Flask v1)是文档中关于 ProxyFix 的内容。

v2 文档

解释一下:在 HTTP 代理后面使用 Gunicorn 部署服务器,您将需要重写一些标头,以便应用程序可以工作。 Werkzeug 附带了一个修复程序,可以解决一些常见的设置。

from werkzeug.middleware.proxy_fix import ProxyFix

app.wsgi_app = ProxyFix(app.wsgi_app, x_proto=1, x_host=1)

4
投票

您需要显示定义 Flask 应用程序“app”的代码。

“app”在哪里定义?您是从另一个文件导入它吗?

这是我重现该问题的尝试:

$ cat myproject.py
from flask import Flask

app = Flask(__name__)

@app.route("/")
def index():
    return "ok"

$ bin/gunicorn -w 4 -b 127.0.0.1:4000 myproject:app &
[1] 27435

2014-03-04 12:18:36 [27435] [INFO] Starting gunicorn 18.0
2014-03-04 12:18:36 [27435] [INFO] Listening at: http://127.0.0.1:4000 (27435)
2014-03-04 12:18:36 [27435] [INFO] Using worker: sync
2014-03-04 12:18:36 [27441] [INFO] Booting worker with pid: 27441
2014-03-04 12:18:36 [27442] [INFO] Booting worker with pid: 27442
2014-03-04 12:18:36 [27445] [INFO] Booting worker with pid: 27445
2014-03-04 12:18:36 [27448] [INFO] Booting worker with pid: 27448

$ curl http://127.0.0.1:4000/
ok

如您所见,它运行良好。在这种情况下你绝对不需要 ProxyFix。


0
投票

假设您所说的“使用其本机http服务器的虚拟机”的意思是您在同一虚拟机上运行类似nginx的东西作为反向代理/http服务器,然后将其指向

localhost:4000
。您收到的错误与此线程中的
ModuleNotFoundError
错误类似。并且您通过虚拟机的 IP 地址从另一台计算机访问该应用程序:您需要使用 ProxyFix,因为 nginx 充当 http 请求的(反向)代理服务器,连接到本地主机,然后发送任何内容向命中 nginx 的客户端吐出信息。

如果您不这样做,并且您的应用程序有自己的本机http服务器,则可以更改gunicorn的绑定方式并将其设置为

-b 0.0.0.0:4000

以启用远程连接。这会将其绑定到所有可用的 IP 地址,因此,如果您的虚拟机有多个 IP 地址,则当请求发送到端口 4000 时,它将响应其中的任何一个。如果您只希望它侦听特定地址,则可以在其中输入该地址。设置 
-b 127.0.0.1:4000
 意味着它只会侦听端口 4000 上来自 
localhost
 的连接,这使得它作为虚拟机上的 Web 应用程序毫无用处。

但是如果这被暴露在互联网上,你就不应该这样做。你应该做第一件事。

如果您不使用代理,则有关不使用中间件的警告适用于此处。 proxy_fix 需要知道它前面有多少个代理,这样它就不会盲目地信任在您的请求和服务该请求的gunicorn 服务器中间从潜在不需要/恶意设备发送给它的标头。将提供的值设置为高于gunicorn服务器前面的代理数量还允许将伪造的标头传递给gunicorn。对于您的情况来说,这可能不是问题,但如果您打算将此应用程序放在互联网上,那么您需要了解这一点。

© www.soinside.com 2019 - 2024. All rights reserved.