【问题标题】:ws4py under cherrypy under WSGI: exception AttributeError: 'mod_wsgi.Input' object has no attribute 'rfile'WSGI下cherrypy下的ws4py:异常AttributeError: 'mod_wsgi.Input' object has no attribute 'rfile'
【发布时间】:2014-09-15 09:47:12
【问题描述】:

我正在尝试在 openshift.com 服务器上实现 websockets(应该支持它们)。

openshift.com 为我提供了一个 WSGI,所以我将我的 cherrypy 嵌入其中,以便我的 wsgi.pyscript 定义一个 application 对象。 此外,cherrypy 有一个 websocket 工具,由 ws4py 定义。

这是一个在 OpenShift 中的 WSGI 下工作的最小化 Cherrypy 应用程序,并且应该也使用 websockets!

import cherrypy
from ws4py.server.cherrypyserver import WebSocketPlugin, WebSocketTool
from ws4py.websocket import EchoWebSocket
import atexit
import logging

# see http://tools.cherrypy.org/wiki/ModWSGI
cherrypy.config.update({'environment': 'embedded'}) 
if cherrypy.__version__.startswith('3.0') and cherrypy.engine.state == 0:
    cherrypy.engine.start(blocking=False)
    atexit.register(cherrypy.engine.stop)

class Root(object):
    def index(self): return 'I work!'
    def ws(self): print('THIS IS NEVER PRINTED :(')
    index.exposed=True
    ws.exposed=True

# registering the websocket
conf={'/ws':{'tools.websocket.on': True,'tools.websocket.handler_cls': EchoWebSocket}}
WebSocketPlugin(cherrypy.engine).subscribe()
cherrypy.tools.websocket = WebSocketTool()  

#show stacktraces in console (for some reason this is not default in cherrypy+WSGI)
logger = logging.getLogger()
logger.setLevel(logging.INFO)
stream = logging.StreamHandler()
stream.setLevel(logging.INFO)
logger.addHandler(stream)

application = cherrypy.Application(Root(), script_name='', config=conf)

一切都很好,除了当我创建一个 websocket(连接到 ws://myserver:8000/ws ),这是我得到的堆栈跟踪:

 cherrypy/_cplogging.py, 214, HTTP Traceback (most recent call last):
   File "cherrypy/_cprequest.py", line 661, in respond
     self.hooks.run('before_request_body')
   File "cherrypy/_cprequest.py", line 114, in run
     raise exc
   File "cherrypy/_cprequest.py", line 104, in run
     hook()
   File "cherrypy/_cprequest.py", line 63, in __call__
     return self.callback(**self.kwargs)
   File "ws4py/server/cherrypyserver.py", line 200, in upgrade
     ws_conn = get_connection(request.rfile.rfile)
AttributeError: 'mod_wsgi.Input' object has no attribute 'rfile'

(我从文件名中手动删除了绝对路径) PS:我用python3.3cherrypy==3.5.0ws4py==0.3.4

我不清楚:

  • 如果这是在 WSGI 环境中时,cherrypy 和 ws4py 之间缺乏兼容性。
  • 如果是ws4py在WSGI环境下的问题
  • 如果是因为 Openshift websocket 的端口与 http 不同

PPS:这是一个完整的 OpenShift 项目,您可以自己运行并尝试:https://github.com/spocchio/wsgi-cherrypy-ws4py

【问题讨论】:

    标签: python-3.x openshift wsgi cherrypy ws4py


    【解决方案1】:

    我认为这根本不可能。 WSGI是同步协议(12),WebSocket协议是异步的。 Wiki 指出,对于 Python 应用程序接口,OpenShift 使用 WSGI (3)。唉。

    不过,我最近在 pub/sub 场景中使用了 ws4py,它在 CherryPy 标准 HTTP 服务器部署之上运行得非常好。因此,在没有应用程序接口限制的通用虚拟服务器上应该不是问题。

    【讨论】:

    • 我知道,在 Heroku 上它运行良好。不幸的是,他们在 websockets 上有 55 秒的超时,因此客户端必须至少每分钟保持一次连接(对于在后台运行的移动应用程序来说不是最佳选择)。
    • 虽然 WSGI 规范在技术上不允许这样做,但问题更多的是与所使用的 WSGI 服务器有关。 WebSocket 代码依赖于被实现为纯 Python WSGI 服务器的 WSGI 服务器上使用,该服务器直接处理客户端套接字本身。然后它绕过 WSGI 规范和 WSGI 服务器,向下获取客户端的实际套接字连接并直接通过它进行通信。换句话说,它正在使用邪恶的黑客。此 hack 不适用于 mod_wsgi,因为它不会暴露原始套接字连接。
    • 为了更清楚,我会补充一点,在 Python Openshift uses Apache webserver 的情况下,因此 mod_wsgi 用于 WSGI。格雷厄姆所说的“邪恶黑客”是documented in ws4py CherryPy module
    • 我确实不得不执行这样的 hack,我对此并不感到骄傲。不幸的是,WSGI 规范早在 WebSocket 之前就已经写好了,并且没有考虑到这个用例。希望有一天它会被修改以解决它。
    猜你喜欢
    • 2022-12-01
    • 2022-12-19
    • 2021-07-17
    • 1970-01-01
    • 1970-01-01
    • 2022-08-15
    • 1970-01-01
    • 2020-04-26
    • 2020-11-21
    相关资源
    最近更新 更多