FastAPI

An easy way to create Restful apis in python

Installation:

    pip install fastapi[all]   #this installs fast api and all options including uvicorn (the web host) similar to gunicorn

separate installations:

    pip install fastapi

    pip install uvicorn[standard]

   ... other dependencies

The separate installtion is more suitable for production server to keep the minimum.


Helloworld

Pretty similar to Flask. Create an app and decorate the get / post method for different path. 

The helloworld here use the root / path. The returned message is a json object (dictionary in python)

from fastapi import FastAPI

app = FastAPI()

@app.get("/")

async def root():

    return {"message": "Hello World"}


Run the app

uvicorn helloworld:app --host 127.0.0.1 --port 8080 --reload

again similar to gunicorn, points to the python file, the app instance, the host and port


Go to web browser open http://localhost:8080/


Restful API docs

The cool thing is it automatically generates the docs (JSON schema) for the api. 

Go to http://localhost:8080/docs

It will list all the apis available with the service

The JSON schema is at http://localhost:8080/openapi.json

With JSON schema describing the API, one can automatically generate code for calling the api.


GET with parameter

you can send parameters within the URL to the api, simply add a sayhi function

@app.get("/sayhi")

async def sayhi(msg):

    return {"received": msg}

From python, send a get request to the api. Note the parameter is part of the request url

import requests

api_url = "http://localhost:8080/sayhi?msg=good day"  

response = requests.get(api_url)

print(response.text)

The script will return {"received":"good day"}


POST with data

The API now receives data in the request body. This requires to define the structure of the data in the request body.

Use pydantic's data model to define the request body structure.

The echo api below simply expects a request body with name and msg in string format.

from fastapi import FastAPI

from pydantic import BaseModel

app = FastAPI()

class Info(BaseModel):

    name: str

    msg: str

@app.post("/echo/")

async def echo(info: Info):

    return info

Call the API with request body.

Pass in the JSON data.

import requests

api_url = "http://localhost:8080/echo"  

payload = {"name": 'john', "msg": 'good day'}

response = requests.post(api_url, json=payload)

response_data = response.json()

print(response_data)

The response is {'name': 'john', 'msg': 'good day'}


Run the app from Gunicorn

Uvicorn supports async request which is lacked in flask, but still it is not a workers manager.

So in production it needs to be run from a manager like Gunicorn, similar to running flask from Gunicorn.

Gunicorn is compatible with it, and only needs to specify the worker class as below

gunicorn helloworld:app --workers 4 --worker-class uvicorn.workers.UvicornWorker --bind 0.0.0.0:8080