Flask socketio与werkzeug DispatcherMiddleware和多个WSGI应用程序:无连接

时间:2017-11-01 17:31:54

标签: flask websocket subdomain wsgi flask-socketio

我有一个设置,我想在一台服务器上运行多个WSGI应用程序,并使用Flask-SocketIO socketio-server在其中一个应用程序中进行通信。

我已经通过带有eventlet的gunicorn提供了我的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工作?

问题是当尝试连接到/ socketio时,与socketio服务器的javascript连接收到404错误。

我是否需要将Javascript端交给我的应用程序的子域? 如果是这种情况,连接字符串将如何查看? 现在我的连接字符串如下所示:Javascript端的'http://' + document.domain + ':' + location.port + '/'

PS: 我这样做的原因是我需要从与应用程序其余部分相同的域提供Pyro4网关,否则浏览器会对我对REST调用pyro4应用同源策略限制。因此,如果这太复杂,并且有更简单的方法来达到我的最终目标,那么我也是开放的。

3 个答案:

答案 0 :(得分:1)

我用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的应用程序,那么我认为最好有单独的命名空间。

答案 1 :(得分:0)

Socket.IO端点默认为/socket.io。由于您应用的第一个入口点是DispatcherMiddleware,因此不会映射到应用程序。

我没试过这个,但是如果你在/socket.io前缀下的调度程序中间件上为你的应用添加一个重复条目,那么Socket.IO请求将被路由到正确的位置。

答案 2 :(得分:0)

我解决了我的问题,但遗憾的是,这不是一个真正的修复,而是更多的解决方法。

我的应用程序不在默认路由上的原因是另一个wsgi-app(pyro httpgateway)正在进行一些重定向,当我尝试将它放在/pyro时导致无限重定向路由。

我现在修改了部分代码,并将pyro应用程序放在上面提到的路径上,同时将我的应用程序保留在主路径/上。

这允许SocketIO适用于我的主应用程序,尽管如上所述更多的是解决方法而不是完整修复。