I’ve been doing scripting to some degree throughout my career, but rarely more than a simple script to accomplish a repetitive task. When I started at SolidFire I decided I needed to up my game, considering the entire product is built around API configuration and management.
Like many from the infrastructure side I chose Python to get started. I’d used Python before, but it had been a while and I’d forgotten most of the language. Luckily I came across the Python Fundamentals and Python - Beyond the Basics courses on Pluralsight by Austin Bingham and Robert Smallshire. While not necessarily targeted for the absolute beginner, these are fantastic courses that throughly cover the details of the language. With that and a bit of Googling, I was soon writing metaclasses and other reasonably advanced code.
My first projects involved generating HTML reports and sending them out via email. This is a simple enough task using a POP3 library and the Jinja2 templating engine and worked well for my needs. Eventually I got around to wanting a web interface so that the reports could be viewed on demand, rather than in an email. After going through a couple Python web frameworks, I found that Flask gave me the flexibility I wanted. Everything was well and good, until I wanted to add dynamic components to my pages.
A brief divergence into SPAs
While I don’t want to get too in-depth on Angular, I should explain that Angular is a single page app framework. This means that page changes don’t require the browser to request the entire HTML document from the server again. Typically, if new content is needed only the data is requested from the server via an XHR call2 and the DOM is manipulated to display the new content.
Using a blog post as an example. Assume we’re looking at the home page of a blog, a list of links to articles is displayed. We then click on one of the links:
If the site is using server side rendering (Ruby on Rails, Django, Flask, etc) the process happens something like this:
- The client (browser) sends a request for the page to the webserver.
- The server gets the post metadata and content from a database.
- The data is then combined with a template and transformed into HTML.
- The server sends the HTML back to the client, which discards the currently rendered page content and renders the new HTML.
In a SPA the process is like this:
- The client requests the article data from the server’s API via XHR.
- The server gets the data from the database and sends it back, formatted as JSON.
- The client takes the data and the template it has in memory and uses that to manipulate the current page to show the desired content. (The template may be preloaded or requested via a seperate XHR call.)
While there are a number of benefits (and some tradeoffs) of SPAs, the major advantages are only the necessary data needs to be transferred, rather that the entire page, and the page doesn’t need to completely reload.
Back to the topic at hand
All of that was simply too explain that to write an SPA, you need a server side application to handle API requests. As I was already using the Python-based Flask framework and most web frameworks can be used to send and receive JSON (aka provide an API), it seemed like the logical choice.
So I began writing my API in Flask. It was easy and worked well for the most part. I didn’t have any major complaints.
My minor complaints were:
- Figuring out which WSGI server to use for a production deployment can be confusing, especially since I’d been writing in Python3. (I ended up using gunicorn behind a NGINX proxy)
- Doing tasks asynchronously is not very straightforward in Python. While I’m certain it’s possible, since I was focusing on writing functionality, I didn’t spend a lot of time looking into it.
I decided to look for a primer on Pluralsight (surprising, I know) and came across Jonathan Mills RESTful Web Services with Node.js and Expres, perfect! Express is to Node a bit like Flask is to Python, a web framework that doesn’t dictate how your application should work. In fact, the route definitions felt very similar to Flask, except that instead of using decorators to tie routes to logic, callbacks are used. My API wasn’t very complicated as it wasn’t much more than a wrapper around MongoDB queries, so it didn’t take more than an evening to port it to Node/Express.
I was very pleased with the results. I didn’t do any benchmarking, but the API felt faster. Node itself includes a production worthy web server and is built from the ground up to be non-blocking, so I didn’t have to hassle with anything like gunicorn. Some of the API calls required multiple queries to the database (yay for non-relational databases!), this was quite slow in my synchronous Python script. Using the fantastic async library I was able to easily chain query execution together in series, parallel, or a combination, where approriate. As would be expected, this resulted in a massive speed up of those API requests.
I’ve recently moved my blog to Jekyll, so if I haven’t implemented comments by the time you read this, feel free to hit me up on Twitter, @vCabbage.
Disclosure: As a Cisco Champion, I received a year subscription to Pluralsight for free. However, I’ve been paying for my own subscription since they aquired Trainsignal and am a huge fan of the service.