Step 4: The Routing


Next up is routing. Routing is the process of matching and parsing the URL to something we can use. Werkzeug provides a flexible integrated routing system which we can use for that. The way it works is that you create a Map instance and add a bunch of Rule objects. Each rule has a pattern it will try to match the URL against and an “endpoint”. The endpoint is typically a string and can be used to uniquely identify the URL. We could also use this to automatically reverse the URL, but that’s not what we will do in this tutorial.

Just put this into the constructor:

self.url_map = Map([
    Rule('/', endpoint='new_url'),
    Rule('/<short_id>', endpoint='follow_short_link'),
    Rule('/<short_id>+', endpoint='short_link_details')
])

Here we create a URL map with three rules. / for the root of the URL space where we will just dispatch to a function that implements the logic to create a new URL. And then one that follows the short link to the target URL and another one with the same rule but a plus (+) at the end to show the link details.

So how do we find our way from the endpoint to a function? That’s up to you. The way we will do it in this tutorial is by calling the method on_ + endpoint on the class itself. Here is how this works:

def dispatch_request(self, request):
    adapter = self.url_map.bind_to_environ(request.environ)
    try:
        endpoint, values = adapter.match()
        return getattr(self, 'on_' + endpoint)(request, **values)
    except HTTPException, e:
        return e

We bind the URL map to the current environment and get back a URLAdapter. The adapter can be used to match the request but also to reverse URLs. The match method will return the endpoint and a dictionary of values in the URL. For instance the rule for follow_short_link has a variable part called short_id. When we go to http://localhost:5000/foo we will get the following values back:

endpoint = 'follow_short_link'
values = {'short_id': u'foo'}

If it does not match anything, it will raise a NotFound exception, which is an HTTPException. All HTTP exceptions are also WSGI applications by themselves which render a default error page. So we just catch all of them down and return the error itself.

If all works well, we call the function on_ + endpoint and pass it the request as argument as well as all the URL arguments as keyword arguments and return the response object that method returns.