如何将支持websocket的路径添加到正在运行的CherryPy应用程序?

时间:2013-08-30 23:13:14

标签: websocket cherrypy ws4py

我正在尝试使用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 config指令,以允许在ws://localhost:9000/other创建websockets。 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”和我没有使用“添加”路径“创建”的其他路径之间的区别:

> 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”上)?我可以做些什么来完成我追求的这种行为?

2 个答案:

答案 0 :(得分: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中删除该鸟。

答案 1 :(得分:0)

当请求命中某个index()页面处理程序时,301是CherryPy的默认行为/如果它的处理程序是index(),那么/ bird会重定向到/ bird /。

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

tools.trailing_slash.on: False

这应该可以解决问题。