Thursday, December 24, 2015

Flask like routes in Falcon Python Framework

Disclaimer: This is not all my idea or code. The idea was implemented in a Tornado framework that I work on, and it came from one of the popular Tornado gists.

When I came into the Tornado app that had this implemented, I was pleasantly pleased to see how the routing worked. I have never worked with Flask, I only later found out that this was how Flask does it. Why was I pleased then?

As with Falcon, and many other frameworks, you have a file that starts your app up. In that file you manually include all of the handler classes, and then manually add each route. This is very verbose and with a big application, can make this file become overwhelming. That isn't the only problem though.

When I would want to work on a particular route in an application with verbose routes, I would have to open the app file, find the route, and see which handler it belonged to. Then I would have to open that handler file. Too many clicks for this lazy developer. With the route decorators, I just open the handler file I know I need to work on, and find the route I care about in there.

There are better reasons for this than just catering to the lazy developer though. With the autoload function I am able to import all the handlers automagically. With the route decorator I am able to the same with the routes. This makes for not only a nice clean readable app file, but when you add new routes and handlers, you don't have to go touching the app file at all. The least we can touch this file that can quickly turn into a monstrosity, the better. It is the file that starts the app. The last thing we want is to deploy new code and find that the app didn't restart because of an error in the app file.

So here is a gist of the route decorators and supporting functions to make this happen.
Add this file into your app root.
Then your app file will just need to look like this. 

You'll never have to touch your app file again unless you need to add more functionality upon start up of your app.

One caveat to this approach is that it won't work for custom routing. According to the docs you either use your custom router, or the default one. In the case that you want custom routing, you would just add the ability to accept more parameters into the route decorator, add them on  self._routes.append,  and finally in the add_routes function add them to your app.add_route call. I have not tested this, and hopefully you decide if you need custom routes before your app is built out.