Search code examples
pythonwebsockettornadorequesthandler

Call Tornado WebSocketHandler from Requesthandler


I am using Tornado Webserver and want to internally call a WebSocketHandler from a RequestHandler.

It is not possible to use the redirect /redirectHandler functionality, because the WebSocketHandler class to call ("IndexHandlerDynamic1" in the example below) will be created with a classFactory.

Using the definition of Requesthandler (here) my example looks like:

class IndexHandlerDynamic1(tornado.web.WebSocketHandler):
    def initialize(self):
        print "Forwarded to Websocket"
    def open(self):
        print "WebSocket opened"
class IndexHandlerDistributor(tornado.web.RequestHandler):
    def get(self, channelId):
        IndexHandlerDynamic1(self.application, self.request)

If I request the related url he jumps into IndexHandlerDistributor and IndexHandlerDynamic1.initialize() is called.

But on Clientside the Browser console outputs the following error:

Error during WebSocket handshake: Unexpected response code: 200 

Obviously the socket connection is not opened correctly, what's my mistake ?

EDIT:

Thanks to Ben for his help!

Sadly I still have trouble to route the user to a dynamically created class named like a url parameter. I hope you can understand my problem by having a look on my example:

app = tornado.web.Application( 
        [(r"/", IndexHandler)] + 
        [(r"/channel/(?P<channelId>[^\/]+)?", ClassFactory(channelId))] 
        ) 

How to use channelId as a parameter for my call of ClassFactory as Requesthandler?

Or is there maybe another way to dynamically change the routing of my application while the application is running? If so, i could use this way to solve my initial task.


Solution

  • The problem is that you're attaching two RequestHandlers to the same request. I'm not sure that dynamically creating handler classes is a great idea, but if you want to do it just pass your factory function (which is not itself a RequestHandler) to the url routing table. The routing table doesn't necessarily need a RequestHandler subclass, it just needs an object which can be called with (app, request) and return a RequestHandler instance.