Learn how to build your own JSON speaking REST API using the asynchronous Tornado networking library.
It wouldn’t be an overstatement to say that REST APIs power the web. Everything from social networks to the apps that help you order pizza is powered by REST APIs. In fact, mobile apps, enterprise applications, and even games need to talk to servers once in a (very short) while. There’s no point in limiting REST API tutorials to just web developers.
Tornado & Motor
Tornado is a mature, battle-tested web framework written in Python. Motor is an async driver for MongoDB that integrates really well with Tornado. These are going to be the two main tools we will be working as we create our superhero API.
Prerequisites and initial setup
Before we begin, please ensure that you have:
- python>=3.6 installed on your machine.
- The venv module along with pip installed.
- mongodb up and running at localhost:27017.
- A decent text editor or IDE.
On Ubuntu and similar systems, venv and pip can be easily installed using:
$ sudo apt install python3-pip python3-venv
Create a virtual environment for our new project.
$ mkdir heroes $ cd heros $ python3 -m venv env
Install the project dependencies.
$ source env/bin/activate $ pip install tornado motor
Initial App Configuration
Create a folder named heroes inside the project folder (which is confusingly also named heroes but this is how things are!). This folder will contain our .py files.
- In the app.py file, we create an instance of tornado.web.Application and make the tornado.httpserver.HTTPServer serve it.
- The handlers.py file contains the request handlers that inherit from tornado.web.RequestHandler.
- The HomeHandler implements the get method so that it can handle GET requests. Tornado automatically sends the response as JSON when a dictionary is passed as a parameter to the write method.
- The ErrorHandler implements the prepare method which is called before the get or any other method. In this case, we send back an error message and finish the response.
Firing up the Motor
Connecting the MongoDB driver to Tornado is simpler than most web frameworks.
- Attach an instance of the MotorClient to the Application object.
- Use the heroes database.
- Refactor the handlers to inherit from a BaseHandler. This step is not required, but it will save us from a lot of duplicate code in the future.
An API for Super Heroes
Add a /heroes endpoint that allows CRUD operations for the hero resource.
- Add the /heroes routes to the Application instance in app.py.
- Add the prepare method in the BaseHandler that automatically parses the request body as JSON for POST and PUT requests.
- Add the HeroesHandler class with get, put, delete, and post methods.
Two routes are added to the app. One for the /heroes endpoint and another for the /heroes/<hero_id> endpoint. While the former is the general endpoint for the resource, the latter is used for operations on a single item.
The changes in handlers.py are too many to show in a diff. Please check the complete source code listing below.
- The get method returns all the heroes for the /heroes route. For the /heroes/<hero_id> route, the details of a single hero are returned.
- The get method also implements a basic form of paging.
- The post method creates a new hero in the database. The name is required while the other fields are optional.
- The put method is used to replace an existing hero with a different one.
- Also, note the use of async/await syntax for asynchronous database operations.
Final Project Structure
A tree view of the heroes project folder.
heroes ├── heroes │ ├── app.py │ ├── handlers.py │ └── __pycache__ └── env ├── bin ├── include ├── lib ├── lib64 -> lib └── pyvenv.cfg
7 directories, 3 files
Running the Application
- Ensure that the mongod process is running at localhost:27017.
- Open a terminal in the project root folder and run:
$ source env/bin/activate $ export PORT=8080 $ export MONGO_CONNECT_URI=mongodb://localhost:27017 $ python3 -m heroes.app
The API server should now be up and running. Let’s hit the endpoints and check the results.
Consuming the REST API
httpie is a great library for consuming APIs from the command line. You can install it using:
$ pip install httpie
We have built a really cool REST API but it is far from being production-ready. Our API can be a lot more robust and user-friendly. If you want to learn more,
- Check out this article on Restful API Design by Mahesh Haldar.
- Skim through the documentation of Tornado.
- Keep an eye out for more Python tutorials by me!
Thanks for reading, drop a few claps if you enjoyed it. Check out some other posts I’ve written, follow and reach out to me on Linkedin.