Search code examples
tornado

Tornado: How to send default file if not found in StaticFileHandler


When a requested static file is not found, I want to send back a default file. eg. /images/dog.png -> /images/default.png.

After digging into the source code here.

if (os.path.isdir(absolute_path) and
    self.default_filename is not None):

Setting default_filename is used for request like /images/ -> /images/default.png.


Solution

  • Interesting validate_absolute_path function, why not override this to provide your default file if not exist ?

    import tornado 
    import tornado.web
    import tornado.ioloop
    
    import os
    
    DEFAULT_ABSPATH = os.path.dirname(os.path.abspath(__file__))
    
    class StaticFileOrDefaultHandler(tornado.web.StaticFileHandler):
    
        def validate_absolute_path(self, root, absolute_path):
            try:
                return super(StaticFileOrDefaultHandler, self).validate_absolute_path(root, absolute_path)
            except tornado.web.HTTPError as e:
                if e.status_code == 404:
                    return os.path.join(DEFAULT_ABSPATH, 'default.png')
                raise e
    
    
    app = tornado.web.Application([
        (r'/(.*)', StaticFileOrDefaultHandler, { 'path': DEFAULT_ABSPATH }),
    ])
    
    if __name__ == '__main__':
        app.listen(8888)
        tornado.ioloop.IOLoop.instance().start()
    

    edit

    To avoid override HTTPError(403) check with the status_code if the raised error is a 404.