Deploy a Fastapi site on Azure Functions

By: gmarr

Published On: 2022-04-11

Some housekeeping before the actual note:

First

Here's the GitHub with the base project.

Second

These wonderful articles explain in-depth how Azure functions work and how to use them in combination with FastAPI.

Now to the article!

I want to start this note by saying, Azure Functions are amazing. They let you do all kinds of amazing things by just publishing a URL. On this note, I would like to discuss how I'm using these functions in combination with FastAPI, my favorite framework ever (Remix, I ❤ too, but fastapi came first, sorry).

The premise is that you code a function in python (or js or c#, they support almost everything really). Then you publish this function in the cloud. Once is there you can trigger it through an HTTP call, for example. The magic behind this code is that it can scale to infinity and Azure will take care of the heavy lifting.

You can also code a function in conjunction with a CRON job and let it run every time period you like, everything without the need of creating a VM.

In summary, Azure functions are cool, that's all I'm saying.

Now, to the code!

In this example, I coded the most basic FastAPI app you can think of. You can visit it here

This is our file structure:

├── main
│   ├── __init__.py
│   ├── function.json
├── host.json
├── requirements.txt
// host.json
{
  "version": "2.0",
  "logging": {
    "applicationInsights": {
      "samplingSettings": {
        "isEnabled": true,
        "excludedTypes": "Request"
      }
    }
  },
  "extensionBundle": {
    "id": "Microsoft.Azure.Functions.ExtensionBundle",
    "version": "[2.*, 3.0.0)"
  },
  "extensions": 
  {
    "http": 
    {
        "routePrefix": ""
    }
  }
}
## main.py

import fastapi
import azure.functions as func

app = fastapi.FastAPI()

@app.get("/hello/{name}")
async def get_names(name:str):
    return{
        "name":f"Hello, my name is {name}"
    }

def main(req:func.HttpRequest, context:func.Context) -> func.HttpResponse:
    return func.AsgiMiddleware(app).handle(req, context)
### requirements.txt
azure-functions
fastapi
nest-asyncio
// function.json
{
  "scriptFile": "__init__.py",
  "bindings": [
    {
      "authLevel": "anonymous",
      "type": "httpTrigger",
      "direction": "in",
      "name": "req",
      "methods": [
        "get",
        "post",
        "patch",
        "delete"
      ],
      "route": "{*route}"
    },
    {
      "type": "http",
      "direction": "out",
      "name": "$return"
    }
  ]
}