Search code examples
pythonwebapp2

python webapp2 nested PathPrefixRoute


Is there a (simple) way to build the url's for webapp2 in a way that would allow a structure like below? I couldn't see a way to pass on the PathPrefixRoute from the parent, but something like PathPrefixRoute('(/v1)', [PathPrefixRoute('$1/app1', would be cool.

urls = [
    PathPrefixRoute('/v1', [
        PathPrefixRoute('/app1', [  
            # /v1/app1/index
            Route('/index', 'v1.app1.index.Main')
        ]),
        PathPrefixRoute('/app2', [  
            # /v1/app2/index
            Route('/index', 'v1.app2.index.Main')
        ])
    ]),
    PathPrefixRoute('/v2', [
        PathPrefixRoute('/app1', [
            # /v2/app1/index
            Route('/index', 'v2.app1.index.Main')
        ])
    ])
]

application = webapp2.WSGIApplication(routes=urls)

Solution

  • I ended up writing my own custom server off uwsgi. The routing mechanism I use I have pasted below but the full application is 318 lines of goodness and can handle 100's of RPS (that's all i tested to but feel it could handle 1000's RPS) on a basic 1 core server.

    Feel free to comment good, bad and ugly thoughts.

    class Static:
        def __init__(self, s): self._s = s
        def __str__(self): return self._s
    
    SITES = {
        '(127.0.0.1|localhost)': {
            '/': 'default.index.Home'
        },
        '(example.com)': {
            '/': 'example.index.Home',
            '/static': Static('example'),
            '/console': {
                '/': 'example.console.Home',
                '/login': 'example.console.Login'
            }
        }
    }
    
    def get_location(self):
        http_host = self.env.get('HTTP_HOST', '').split(':')[0]  # host:port
        if not http_host: raise HttpException(404, "Empty Site")
        path_info = self.env.get('PATH_INFO')
        if not path_info: raise HttpException(404, "Empty Path")
        for site in SITES:
            if re.match(site, http_host, re.I):
                paths = SITES[site]
                parts = path_info.split('/')[1:]  # first is always blank
                for part in parts:
                    p = paths.copy()
                    for path in p:
                        if re.match(path + '$', '/' + part, re.I):
                            if isinstance(p[path], basestring):
                                return p[path]
                            paths = p[path]
                            break
                        paths = None
                    if not paths: break
                raise HttpException(404, "Unknown Path")
        raise HttpException(404, "Unknown Site")