Search code examples
pythoncherrypy

CherryPy access restrictions with static files


I have a CherryPy server that dispenses a few static HTML/JS/etc. files to /foosball, plus some JSON through a REST API to /.

import cherrypy

config = {
    'global': {
        'server.socket_host': '0.0.0.0',
        'server.socket_port': # my port here,
        'tools.json_in.on': True
    },
    '/foosball': {
        'tools.staticdir.on': True,
        'tools.staticdir.root': '/var/www/html',
        'tools.staticdir.dir': 'foosball',
        'tools.staticdir.index': 'index.html'
    }
}

@cherrypy.popargs('player_id')
class RESTClient_Player(object):
    # stuff

class RESTClient_Game(object):
    # stuff

class RESTClient:
    players = RESTClient_Player()
    games = RESTClient_Game()

    @cherrypy.expose
    def index(self):
        http_method = getattr(self, cherrypy.request.method)
        return (http_method)()

cherrypy.quickstart(RESTClient(), '/', config)

I also want to keep these pages protected by a basic access restriction scheme, so I've been examining the excellent tutorial CherryPy provides.

Trouble is, the documentation is geared towards authenticating non-static pages, the kind explicitly declared by def statements. I tried and failed to adapt this documentation to the files in /foosball, but without success. /foosball always ends up loading without any authentication request.

What can I add to give static files some access restriction ability?

Thanks!


EDIT: I got pointed towards auth_tool. With the below config block, I was able to lock up the REST API portion with a login screen, but all static files in /foosball are still openly accessible:

def check_login_and_password(login, password):
    cherrypy.log(login)
    cherrypy.log(password)

    return

config = {
    'global': {
        'server.socket_host': '0.0.0.0',
        'server.socket_port': # my port here,
        'tools.json_in.on': True,
        'tools.sessions.on': True,
        'tools.session_auth.on': True,
        'tools.session_auth.check_username_and_password': check_login_and_password
    },
    '/foosball': {
        'tools.staticdir.on': True,
        'tools.staticdir.root': '/var/www/html',
        'tools.staticdir.dir': 'foosball',
        'tools.staticdir.index': 'index.html',
        'tools.sessions.on': True,
        'tools.session_auth.on': True,
        'tools.session_auth.check_username_and_password': check_login_and_password
    }
}

Solution

  • Instead of using the "staticdir" in your config, you can create a function in your class that will return static files. If you do that, you can wrap authentication around your function.

    import cherrypy
    from cherrypy.lib.static import serve_file
    import os
    
    class Hello(object):
        @cherrypy.expose
        def index(self):
            return "Hello World"
    
        @cherrypy.expose
        def static(self, page):
            return serve_file(os.path.join(current_dir, 'static', page), content_type='text/html')
    
    
    if __name__ == '__main__':
        current_dir = os.path.dirname(os.path.abspath(__file__))
        cherrypy.quickstart(Hello())