Search code examples
pythonroutestornadostaticfilehandler

Default file in Tornado's StaticFileHandler


I have following Application configuration:

settings = {
    'default_handler_class': BaseHandler
}

app = web.Application([
        (r'/', IndexHandler),
        (r'/ws', SocketHandler),
        (r'/js/(.*)', web.StaticFileHandler, {'path': 'assets/js', 'default_filename': 'templates/error.html'}),
        (r'/css/(.*)', web.StaticFileHandler, {'path': 'assets/css'}),
        (r'/images/(.*)', web.StaticFileHandler, {'path': 'assets/images'})
    ], **settings)

When I type in http://localhost:8888/js/d3.min.js the file is served, but when I mispell file name and provide http://localhost:8888/js/d3.mi.js for example I would like to obtain my default error page which is located at templates/error.html. For URL like http://localhost:8888/not/existing it works fine but the http://localhost:8888/js/d3.mi.js gives me just plain 404: Not Found.

I found following part in documentation:

To serve a file like index.html automatically when a directory is requested, set static_handler_args=dict(default_filename="index.html") in your application settings, or add default_filename as an initializer argument for your StaticFileHandler.

However I can't understand where I should specify mentioned code. The 'default_filename': 'templates/error.html' in my code doesn't work.


Solution

  • default_filename

    The file specified in default_filename should be in given static path. So if you move error.html to assets/js directory, than navigate to /js/ you will see content of error.html.

    Basically this functionality is a helper with limited usecase (imho). More at https://stackoverflow.com/a/27891339/681044.

    Custom error pages

    Every request handler handles/renders errors in write_error function. This is the recommended way to create custom error pages:

    class MyStaticFileHandler(tornado.web.StaticFileHandler):
    
        def write_error(self, status_code, *args, **kwargs):
            # custom 404 page
            if status_code in [404]:
                self.render('templates/error.html')
            else:
                super().write_error(status_code, *args, **kwargs)