Creating a RESTful API with Python and aiohttp

Elliot Forbes Elliot Forbes ⏰ 3 Minutes 📅 Oct 28, 2017

This tutorial was built on top of Python 3.6

In this tutorial we’ll be building a very simple RESTful based API using aio-libs/aiohttp which is an asynchronous http client/server framework.

Getting Started with aiohttp

Before we go into how we can use aiohttp to create a simple RESTful API, it’s important to know exactly what the framework is and what it can do for us. To start with, it features excellent support of the HTTP protocol as well as for websockets which makes it ideal for working with popular websocket libraries such as Socket.io. If you are interested in seeing how to implement a simple client/server socketio based solution check out this tutorial: Python Socket.io with aiohttp Tutorial.

The key part of the aiohttp framework is that it works in an asynchronous manner, it can concurrently handle hundreds of requests per second without too much hassle. In comparison to frameworks such as flask, it’s incredibly performant.

Installing aiohttp

In order to install aiohttp you can run the following pip command:

pip install aiohttp

Writing a Simple API

To get us started writing a simple API we are going to write a handler function; async def handle(request): which will return a json based response whenever it is called. We’ll then create an app object by calling app = web.Application() and then we’ll set up our app’s router and add a GET request endpoint that calls handle whenever "/" is hit. Finally we call web.run_app(app) in order to kick off our newly defined aiohttp API.

## filename: app.py

from aiohttp import web
import json

async def handle(request):
    response_obj = { 'status' : 'success' }
    return web.Response(text=json.dumps(response_obj))

app = web.Application()
app.router.add_get('/', handle)

web.run_app(app)

Testing our API

We can then run our new REST API by calling python app.py which should start our app on http://0.0.0.0 a.k.a http://localhost on port 8080 by default.

 $ python3.6 app.py
======== Running on http://0.0.0.0 ========
(Press CTRL+C to quit)

When you navigate to http://localhost:8080 you should see our {"status": "success"} being returned in the browser.

POST Requests and Query Parameters

Now that we’ve successfully defined a very basic, single endpoint API we can now start to build on top of this and start exposing different routes that use different verbs. Let’s create a simple POST request endpoint that takes in name via a query parameter. We’ll want the final URL of this endpoint to look like so: http://localhost:8080/user?name=elliot. Let’s define the handler function new_user(request) now.

async def new_user(request):
    try:
        ## happy path where name is set
        user = request.query['name']
        ## Process our new user
        print("Creating new user with name: " , user)

        response_obj = { 'status' : 'success' }
        ## return a success json response with status code 200 i.e. 'OK'
        return web.Response(text=json.dumps(response_obj), status=200)
    except Exception as e:
        ## Bad path where name is not set
        response_obj = { 'status' : 'failed', 'reason': str(e) }
        ## return failed with a status code of 500 i.e. 'Server Error'
        return web.Response(text=json.dumps(response_obj), status=500)

Once we have successfully defined this new handler function we will have to register it in our routes like so:

app.router.add_post('/user', new_user)

Try run your application now and send a POST request to http://localhost:8080/user?name=test and you should see the following output in the console:

 $ python3.6 app.py
======== Running on http://0.0.0.0 ========
(Press CTRL+C to quit)
Creating new user with name:  test

You should also receive the same success json as well as a 200 status.

Video Tutorial