Search code examples
google-app-enginewebapp2

webapp2.Route with optional leading part


I am learning the webapp2 framework with its powerful Route mechanism.

My application is supposed to accept URIs like these:

/poll/abc-123
/poll/abc-123/
/poll/abc-123/vote/       # post new vote
/poll/abc-123/vote/456    # view/update a vote

Polls may optionally be organized into categories, so all the above should work also like this:

/mycategory/poll/abc-123
/mycategory/poll/abc-123/
/mycategory/poll/abc-123/vote/
/mycategory/poll/abc-123/vote/456

My incorrect configuration:

app = webapp2.WSGIApplication([
    webapp2.Route('/<category>/poll/<poll_id><:/?>', PollHandler),
    webapp2.Route('/<category>/poll/<poll_id>/vote/<vote_id>', VoteHandler),
], debug=True)

Question: How could I fix my configuration?

If possible it should be optimized for GAE CPU-time/hosting fee. For example, it may be faster if I add two lines for each entry: one line with category and another one without category...


Solution

  • webapp2 has a mechanism to reuse common prefixes, but in this case they vary, so you can't avoid duplicating those routes, as in:

    app = webapp2.WSGIApplication([
        webapp2.Route('/poll/<poll_id><:/?>', PollHandler),
        webapp2.Route('/poll/<poll_id>/vote/<vote_id>', VoteHandler),
        webapp2.Route('/<category>/poll/<poll_id><:/?>', PollHandler),
        webapp2.Route('/<category>/poll/<poll_id>/vote/<vote_id>', VoteHandler),
    ], debug=True)
    

    You should not worry about adding many routes. They are really cheap to build and match. Unless you have tens of thousands, reducing the number of routes won't matter.

    A small note: the first route accepts an optional end slash. You could instead use the RedirectRoute to accept only one and redirect if the other is accessed, using the option strict_slash=True. This is not well documented but has been around for a while. See the explanation in the docstring.