经过长时间的不成功的研究-我发现了很多主题相似的帖子,但没有一个能够解决我的问题-我也试图寻求帮助。
我正在码头工人内部使用gunicorn(和一个工人-w 1)和flask socket.io运行flask socket.io应用程序:
启动方式:"gunicorn", "-k", "geventwebsocket.gunicorn.workers.GeventWebSocketWorker", "-w", "1", "app:app", "-b", "0.0.0.0:5000"
相应的python代码(async_mode为“ gevent”:socketio = SocketIO(app, async_mode=async_mode)
socketio.run(app, host="0.0.0.0", port=5000, debug=True)
我正在前面运行一个nginx代理,只要我仅使用http,它就可以很好地工作。但是,当我切换到https时,出现很多HTTP 400错误,并且websockets停止工作。
我做了很多研究,发现了nginx选项,以及暗示只可以由一个工人来操作gunicorn。在我找到Miguel的这个简短选择之前,没有一个有效。socketio = SocketIO(app, async_mode=async_mode,engineio_logger=True)
我确实添加了这个信息,并且在gunicorn日志上终于收到一条消息。htts://mydomain is not within the accepted origins
经过几个小时的搜索,这使我进入了讨论
因此,我最终将cors选项添加到了我的socketio构造函数中:socketio = SocketIO(app, async_mode=async_mode,cors_allowed_origins="*")
瞧,一切都很好!
不知道这是否与大多数在可能未检测到主机名或其他名称的容器中运行有关。但是,当我仍在研究时,我开始输入此“问题”,并认为这对于遇到类似问题的其他人可能是一个有趣的发现(因为我遇到了许多类似的要求)。
以下是更为有效安全的做法
我找到了解决此问题的更标准的方法(无需在您的代码中使用硬编码的域,也无需使用冒险的'*'
)。
您可以使用werkzeug的ProxyFix,它可以解决许多在代理后面运行应用程序的问题。
例如,我 在应用程序中使用url_for
with _external=True
。没有ProxyFix
我,则使用带有http
协议的网址而不是所需的网址https
。ProxyFix
只要将代理服务器配置为传递X-Forwarded-*
标头,就可以解决该问题以及您的原始问题。
用法示例:
from flask import Flask
from flask_socketio import SocketIO
from werkzeug.middleware.proxy_fix import ProxyFix
app = Flask(__name__)
app.secret_key = 'TODO: replace with a randomly generate secret key' # TODO: you can find how here: https://stackoverflow.com/questions/34902378/where-do-i-get-a-secret-key-for-flask
socketio = SocketIO(app)
app.wsgi_app = ProxyFix(app.wsgi_app, x_for=1, x_proto=1)
socketio.run(app)
我的Nginx配置:
server {
listen 443 ssl http2;
server_name my.domain.com;
<ssl stuff>
location / {
include proxy_params;
proxy_pass http://127.0.0.1:8000;
}
location /socket.io {
include proxy_params;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
proxy_pass http://127.0.0.1:8000/socket.io;
}
}
server {
if ($host = my.domain.com) {
return 301 https://$host$request_uri;
} # managed by Certbot
listen 80;
server_name my.domain.com;
}
与/etc/nginx/proxy_params
:
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;