带有 werkzeug DispatcherMiddleware 和多个 WSGI 应用程序的 Flask socketio:无连接
Flask socketio with werkzeug DispatcherMiddleware and multiple WSGI apps: no connection
我有一个设置,我想在一台服务器上 运行 多个 WSGI 应用程序,并使用 Flask-SocketIO socketio-server 在其中一个应用程序中进行通信。
我已经通过 gunicorn 和 eventlet 为我的 WSGI 应用程序提供服务,正如 Flask-SocketIO 手册使用以下命令所建议的那样:
gunicorn --worker-class eventlet -w 1 myapp:application
这可以正常运行应用程序,设置的内部代码如下所示 (__init__.py
):
from flask import Flask
from werkzeug.wsgi import DispatcherMiddleware
from Pyro4.utils.httpgateway import pyro_app as gateway
from myapp.extensions import socketio
from myapp.views.vue_js import vue
from config import PYRO_REGEX
def configure_blueprints(app):
app.register_blueprint(vue)
def register_extensions(app):
socketio.init_app(app)
app = Flask(__name__, instance_relative_config=True, template_folder='static', static_url_path='')
app.config.from_object('config')
configure_blueprints(app)
register_extensions(app)
# Set up WSGI application middleware to serve both the pyro httpgateway and this application
# through the same server
application = DispatcherMiddleware(gateway, {
'/app': app
})
这可以正常工作,但我的应用程序现在没有 websocket 连接了。如何让 Flask-SocketIO 在此配置下工作?
问题是 javascript 到 socketio 服务器的连接在尝试连接到 /socketio 时出现 404 错误。
我是否需要将我的应用程序的子域交给 Javascript 端?
如果是这种情况,连接字符串将如何查看?
现在我的连接字符串如下所示: Javascript 侧 'http://' + document.domain + ':' + location.port + '/'
PS:
我这样做的原因是我需要从与应用程序其余部分相同的域为 Pyro4 网关提供服务,否则浏览器会对我对 pyro4 的 REST 调用应用同源策略限制。因此,如果这太复杂了,并且存在更简单的方法来实现我的最终目标,我也对此持开放态度。
Socket.IO 端点默认为 /socket.io
。由于您的应用程序的第一个入口点是 DispatcherMiddleware
,因此不会映射到应用程序。
我没试过,但也许如果您在 /socket.io
前缀下的调度程序中间件上为您的应用程序添加重复条目,那么 Socket.IO 请求将被路由到正确的位置.
我有点解决了我的问题,但很遗憾,这不是真正的解决方法,而是一种解决方法。
我的应用程序不在默认路由上的原因是另一个 wsgi-app(pyro httpgateway)正在做一些重定向,当我尝试将它放在 /pyro
路线.
我现在已经修改了那部分代码,并将 pyro 应用程序放在上面提到的路径上,同时将我的应用程序保持在主路径上 /
。
这允许 SocketIO 为我的主要应用程序工作,尽管如上所述更多的是解决方法而不是完整的修复。
我用 DispatchMiddleware 做了一些实验,其中一个安装是使用 socket.io
的 Flask 应用程序
self.app.wsgi_app = DispatcherMiddleware(self.app.wsgi_app,{'/aaa/bbb':sockioapp,
'/ccc/ddd':normalapp})
这里,sockioapp
是一个启用了SocketIO的Flask对象,normalapp
不是。
因此 sockioapp
的 url 将是 http://localhost:3000/aaa/bbb
,而 socket.io 端点是 /socket.io
,它无法建立连接(如预期的那样)-我想将端点更改为 /aaa/bbb/socket.io
为此,我添加了 Socket.IO 客户端的路径。
socket = io.connect({transports: ["websocket"], path:"/aaa/bbb/socket.io" });
现在是 SocketIO 服务器。我不确定我是否必须这样做。我希望 DispatcherMiddleware
会神奇地将 /aaa/bbb
路径添加到 /socket.io
,事实似乎是这样。所以服务器保持不变,不需要添加路径。
socketio = SocketIO(socketioapp, host="0.0.0.0")
这就够了。服务器端的一切都被神奇地处理,无需更改调度程序中间件。
如果您有多个应用程序使用 socket.io,我认为拥有单独的命名空间是个好主意。
我有一个设置,我想在一台服务器上 运行 多个 WSGI 应用程序,并使用 Flask-SocketIO socketio-server 在其中一个应用程序中进行通信。
我已经通过 gunicorn 和 eventlet 为我的 WSGI 应用程序提供服务,正如 Flask-SocketIO 手册使用以下命令所建议的那样:
gunicorn --worker-class eventlet -w 1 myapp:application
这可以正常运行应用程序,设置的内部代码如下所示 (__init__.py
):
from flask import Flask
from werkzeug.wsgi import DispatcherMiddleware
from Pyro4.utils.httpgateway import pyro_app as gateway
from myapp.extensions import socketio
from myapp.views.vue_js import vue
from config import PYRO_REGEX
def configure_blueprints(app):
app.register_blueprint(vue)
def register_extensions(app):
socketio.init_app(app)
app = Flask(__name__, instance_relative_config=True, template_folder='static', static_url_path='')
app.config.from_object('config')
configure_blueprints(app)
register_extensions(app)
# Set up WSGI application middleware to serve both the pyro httpgateway and this application
# through the same server
application = DispatcherMiddleware(gateway, {
'/app': app
})
这可以正常工作,但我的应用程序现在没有 websocket 连接了。如何让 Flask-SocketIO 在此配置下工作?
问题是 javascript 到 socketio 服务器的连接在尝试连接到 /socketio 时出现 404 错误。
我是否需要将我的应用程序的子域交给 Javascript 端?
如果是这种情况,连接字符串将如何查看?
现在我的连接字符串如下所示: Javascript 侧 'http://' + document.domain + ':' + location.port + '/'
PS: 我这样做的原因是我需要从与应用程序其余部分相同的域为 Pyro4 网关提供服务,否则浏览器会对我对 pyro4 的 REST 调用应用同源策略限制。因此,如果这太复杂了,并且存在更简单的方法来实现我的最终目标,我也对此持开放态度。
Socket.IO 端点默认为 /socket.io
。由于您的应用程序的第一个入口点是 DispatcherMiddleware
,因此不会映射到应用程序。
我没试过,但也许如果您在 /socket.io
前缀下的调度程序中间件上为您的应用程序添加重复条目,那么 Socket.IO 请求将被路由到正确的位置.
我有点解决了我的问题,但很遗憾,这不是真正的解决方法,而是一种解决方法。
我的应用程序不在默认路由上的原因是另一个 wsgi-app(pyro httpgateway)正在做一些重定向,当我尝试将它放在 /pyro
路线.
我现在已经修改了那部分代码,并将 pyro 应用程序放在上面提到的路径上,同时将我的应用程序保持在主路径上 /
。
这允许 SocketIO 为我的主要应用程序工作,尽管如上所述更多的是解决方法而不是完整的修复。
我用 DispatchMiddleware 做了一些实验,其中一个安装是使用 socket.io
的 Flask 应用程序self.app.wsgi_app = DispatcherMiddleware(self.app.wsgi_app,{'/aaa/bbb':sockioapp,
'/ccc/ddd':normalapp})
这里,sockioapp
是一个启用了SocketIO的Flask对象,normalapp
不是。
因此 sockioapp
的 url 将是 http://localhost:3000/aaa/bbb
,而 socket.io 端点是 /socket.io
,它无法建立连接(如预期的那样)-我想将端点更改为 /aaa/bbb/socket.io
为此,我添加了 Socket.IO 客户端的路径。
socket = io.connect({transports: ["websocket"], path:"/aaa/bbb/socket.io" });
现在是 SocketIO 服务器。我不确定我是否必须这样做。我希望 DispatcherMiddleware
会神奇地将 /aaa/bbb
路径添加到 /socket.io
,事实似乎是这样。所以服务器保持不变,不需要添加路径。
socketio = SocketIO(socketioapp, host="0.0.0.0")
这就够了。服务器端的一切都被神奇地处理,无需更改调度程序中间件。
如果您有多个应用程序使用 socket.io,我认为拥有单独的命名空间是个好主意。