Yan Anisimov
Yan Anisimov

Reputation: 39

Which skeleton more correct

I use Torndo for my projects. I use this skeleton for server. Using this code I address to my methods via http://server/dev/Foo and http://server/dev/Bar. This code work in production

class MainHandler(SessionBaseHandler):

     def __init__(self, *args, **kwargs):
         global logger
         super(MainHandler, self).__init__(*args, **kwargs)

     @tornado.web.asynchronous
     @tornado.gen.coroutine
     def post(self,func_name):
         request = self.request.body
         func = getattr(self, func_name)
         response = yield tornado.gen.Task(func,request)           
         self.write(response)                
         self.finish()     

     def Foo(self, query, callback):
         callback({"queryFoo":query})        

     def Bar(self, query, callback):
         callback({"queryBar":query})     


class TornadoApplication(tornado.web.Application):

     def __init__(self):
         handlers = [
             (r"/dev/(.*)", acquiring.MainHandler),
         ]
         settings.update(session=session_settings)
         tornado.web.Application.__init__(self, handlers)


http_server = tornado.httpserver.HTTPServer(TornadoApplication())
http_server.listen(Config.get('WebServer','Port'))
tornado.ioloop.IOLoop.instance().start()        

But some times in documentation and articles describe this skeleton like this:

class MainHandlerFoo(SessionBaseHandler):

     def __init__(self, *args, **kwargs):
         global logger
         super(MainHandler, self).__init__(*args, **kwargs)    

     @tornado.web.asynchronous
     @tornado.gen.coroutine
     def post(self,func_name):
         request = self.request.body
         response = yield tornado.gen.Task(self._Foo,request)           
         self.write(response)                
         self.finish()     

     def _Foo(self, query, callback):
        callback({"queryFoo":query})                

class MainHandlerBar(SessionBaseHandler):

     def __init__(self, *args, **kwargs):
         global logger
         super(MainHandler, self).__init__(*args, **kwargs)

     @tornado.web.asynchronous
     @tornado.gen.coroutine
     def post(self,func_name):
         request = self.request.body
         response = yield tornado.gen.Task(self._Bar,request)           
         self.write(response)                
         self.finish()     

     def _Bar(self, query, callback):
         callback({"queryBar":query})                

class TornadoApplication(tornado.web.Application):

     def __init__(self):
         handlers = [
             (r"/dev/Foo", acquiring.MainHandlerFoo),
             (r"/dev/Bar", acquiring.MainHandlerBar),
         ]
         settings.update(session=session_settings)
         tornado.web.Application.__init__(self, handlers)


http_server = tornado.httpserver.HTTPServer(TornadoApplication())
http_server.listen(Config.get('WebServer','Port'))
tornado.ioloop.IOLoop.instance().start()        

So I found myself at a loss. What can be a problem when using my skeleton? Does my skeleton significant functional disadvantages before described in the documentation or it is simply a problem of style?

Upvotes: 0

Views: 600

Answers (1)

Remco Haszing
Remco Haszing

Reputation: 7829

The first method uses:

getattr(self, func_name)

Where func_name may match any value following the pattern .*. This means the user could call any method of your handler, including any methods of its bases classes. This will lead to unexpected results and could even be a potential security risk.

The user could call any of the following example URLs which are unintentionally exposed:

/dev/__init__
/dev/mro
/dev/put

Upvotes: 1

Related Questions