2

我正在尝试使用 ws4py 在 CherryPy 中动态创建/销毁“支持 websocket”的路径。这是一个演示问题的完整程序:

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

class Nothing(object):
    @cherrypy.expose
    def index(self):
        pass

class Root(object):
    @cherrypy.expose
    def index(self):
        return "Tweep tweep!"

    @cherrypy.expose
    def add(self, bird):
        # Try to create a new websocket-capable path.
        cherrypy.tree.mount(Nothing(), "/bird/" + bird, config={"": {"tools.websocket.on": True, "tools.websocket.handler_cls": EchoWebSocket}})

    @cherrypy.expose
    def remove(self, bird):
        # Remove a previously created websocket-capable path.
        del cherrypy.tree.apps["/bird/" + bird]

    @cherrypy.expose
    def other(self):
        pass

cherrypy.config.update({"server.socket_host": "localhost", "server.socket_port": 9000})
WebSocketPlugin(cherrypy.engine).subscribe()
cherrypy.tools.websocket = WebSocketTool()

cherrypy.quickstart(Root(), "/", config={"/other": {"tools.websocket.on": True,"tools.websocket.handler_cls": EchoWebSocket}})

这是我可以构建的最简单的示例:将 Root 类放置为主应用程序,以及 ws4py 配置指令以允许在ws://localhost:9000/other. 该add()方法创建一个新应用程序并将其安装在适当的路径上,以模拟“/other”应用程序的设置。

启动服务器后,我可以在 Chrome 的 JavaScript 控制台中执行此操作:

> w = new WebSocket("ws://localhost:9000/other")
WebSocket {binaryType: "blob", extensions: "", protocol: "", onclose: null, onerror: null…}
> w.onmessage = function (d) { console.log(d.data); }
function (d) { console.log(d.data); }
> w.send("testing 1 2 3")
true
testing 1 2 3

太棒了,它有效!

现在,http://localhost:9000/add/eagle在我的浏览器中访问后(导致创建新路径),我在控制台中得到以下交换:

> w = new WebSocket("ws://localhost:9000/bird/eagle")
WebSocket {binaryType: "blob", extensions: "", protocol: "", onclose: null, onerror: null…}
WebSocket connection to 'ws://localhost:9000/bird/eagle' failed: Unexpected response code: 301

嗯...为什么我会得到 301?只是为了显示“/bird/eagle”和我没有使用“add”路径“创建”的其他路径之间的区别:

> w = new WebSocket("ws://localhost:9000/bird/pelican")
WebSocket {binaryType: "blob", extensions: "", protocol: "", onclose: null, onerror: null…}
WebSocket connection to 'ws://localhost:9000/bird/pelican' failed: Unexpected response code: 404

404 是有道理的;服务器上没有这样的路径。但是为什么我在安装一个专门为此 websocket 创建目的的新应用程序后会得到 301 呢?为什么它的行为与服务器启动时设置的行为不同(在路径“/other”上)?为了实现我所追求的这种行为,我可以做些什么不同的事情?

4

2 回答 2

1

虽然我不明白为什么我会得到 301,但我确实想出了如何真正按照我想要的方式进行这项工作。诀窍似乎是我无法在处理程序对象的“索引”路径上安装 websocket 处理程序。相反,您需要在其他命名路径上执行此操作。我的示例程序仅在两个地方进行了更改:

(1) "Nothing" 类获得了一个新方法:

@cherrypy.expose
def ws(self):
    pass

(2) 挂载动态创建的处理程序的行改变了它的挂载点:

cherrypy.tree.mount(Nothing(), "/bird/" + bird, config={"/ws": {"tools.websocket.on": True, "tools.websocket.handler_cls": EchoWebSocket}})

现在一切都很好。我可以在“add/” URL 中添加一只鸟,然后从控制台实例化一个 websocket 对象并通过它进行通信,最后我可以在“remove/” URL 中删除鸟。

于 2013-09-05T17:44:46.050 回答
0

当请求确实命中 index() 页面处理程序时,301 是 CherryPy 的默认行为/因此 /bird 将重定向到 /bird/ 如果它的处理程序是 index()。

您可以通过为定义索引的类禁用 trailing_slah 工具来禁用此行为。

tools.trailing_slash.on: False

这应该可以解决问题。

于 2013-09-08T11:54:37.753 回答