Wednesday, April 22, 2009

URL routing in Python web apps

There are two places to put URL routing information. The first is in your app.yaml, in the 'handlers' section. The second is in the python script that is called *from* the handlers section, at the end, where you create the webapp.WSGIApplication.

"So," you might think, "all I have to do is split my application into modules, assign modules to urls in app.yaml, and then assign sub-urls to classes when I create the webapp.WSGIApplication, right?" Wrong.

Say you are creating a backend for a Flex rich client application, and suppose you have something like this in your app.yaml:

handlers:
- url: /flex
  script: client.py

and then in your client.py:

application = webapp.WSGIApplication(
    [('/test', TestPage)],
    debug=True )

If you think that this will cause the TestPage class to be invoked for a URL like "http://localhost:8080/flex/test" then you are unfortunately wrong. Perhaps because Google's Getting Started documentation deals with pages that are available directly off the root, I naively thought that the url filters in the webapp.WSGIApplication got *added* to the end of those in app.yaml, so that you could use app.yaml for first-order routing, webapp.WSGIApplication for second order routing.

But no, the url mappings in webapp.WSGIApplication have to match the *full* url. App.yaml just points to the script that needs to do the work: the url fragment that it matches is not then stripped from the start of the url that's passed to the script.

So if I want to handle "http://localhost:8080/flex/test" in a TestPage class in client.py, I need to have something like:

handlers:
- url: /flex/.*
  script: client.py

in app.yaml and:

application = webapp.WSGIApplication(
    [('/flex/test', TestPage)],
    debug=True )

in client.py.

Why is this important? It's important because it means that your WSGIApplication scripts need to know how you are dividing up your url space, which I consider bad form. I can't, for example, change the base url for the data endpoints for my rich internet applications from "/flex" to "/ria" just by changing one line in app.yaml, which is what I would very much like to do. Instead I have to hunt through all my WSGIApplication scripts and change every single mapping in them as well.

No comments:

Post a Comment