Azure Function with FastAPI + Non HttpTriggers
Integrating FastAPI with Azure Functions can enhance the functionality of serverless applications, especially when you’re looking to create robust APIs with Python. While FastAPI doesn’t natively support Azure-specific triggers like Queue, Timer, or Blob, it’s possible to set up a workaround. This involves using the Azure Functions’ bindings and connecting them with FastAPI endpoints. By doing so, you can enjoy the benefits of FastAPI’s features, such as automatic Swagger documentation and data validation, while also leveraging Azure Functions’ powerful event-driven triggers.
Lets have a look how
Step 1 - Create a new Azure Function in VSCode
- Open Visual Studio Code
- Open a new folder
- Open the Command Pallete (Ctrl + Shift + P)
- Choose: Azure Function: Create Function
- Select: the folder where you want to add the code
- Select: Python as your coding language
- Select: Azure Function Model V2
- Select: Your Python Version (so make sure you have installed Python on your local PC/Mac)
- Select: HttpTrigger as template
- Choose a name for the function, call it something generic because all your FastAPI endpoints will be part of this (I leave it with http_trigger)
- And finally: Anonymous as authorization (you will need to implement your own security within your FastAPI endpoints)
Step 2 - Add a trigger function
This could be any other trigger then HTTP, but for the sake of he example we will use a blob
- Open the Command Pallete (Ctrl + Shift + P)
- Choose: Azure Function: Create Function
- Choose: Add BlobTrigger function to the main file
- Provide a name, container (of your storage account),
- Provide a container name (this is the container of your storage account)
- Provide a connection string app setting variable (connection string to your storage account)
This code was added to your function_app.py file
@app.blob_trigger(arg_name="myblob", path="mycontainer",
connection="AzureWebJobsStorage")
def BlobTrigger(myblob: func.InputStream):
logging.info(f"Python blob trigger function processed blob"
f"Name: {myblob.name}"
f"Blob Size: {myblob.length} bytes")
Step 3: Ready to convert
Step 3.1 - Requirements.txt
First we need to make sure that fastapi library is available for the code. So we need to add the library to our requirements.txt.
Add fastapi==0.111.1 (or when you read this blog it might be a newer version already) to the requirements.txt file
azure-functions==1.20.0
fastapi==0.111.1
By adding the version numbers to the packages you are sure that when a new version is released, that you have no breaking changes when you redeploy.
Step 3.2 - host.json
In the host.json we need to update the routePrefix, that way api endpoints do not have a prefix of api/ (Ex. http://func-example.azurewebsites.net/api/myfunction), but you can call them immediatly (Ex. http://func-example.azurewebsites.net/myfunction).
Your host file should look like this.
{
"version": "2.0",
"logging": {
"applicationInsights": {
"samplingSettings": {
"isEnabled": true,
"excludedTypes": "Request"
}
}
},
"extensionBundle": {
"id": "Microsoft.Azure.Functions.ExtensionBundle",
"version": "[4.*, 5.0.0)"
},
"extensions": {
"http": {
"routePrefix": ""
}
}
}
Step 3.4 - function_app.py
First of all start with adding your fastapi package
import fastapi
You will notice we already have a FunctionApp
app = func.FunctionApp(http_auth_level=func.AuthLevel.ANONYMOUS)
That you can leave like it is, but add underneith the following code, this initializes the FastAPI:
fastapi_app = fastapi.FastAPI(root_path="")
At this point you will reach the httpTrigger endpoint. To make it easy, you can remove all that code. (You can remove all the code starting from @app.route till but not including @app.blob_trigger)
Now at the end of your code file or in between the fastapi initialization and the blob trigger. We will add following code:
@app.function_name("http_trigger")
@app.route(route="{*route}", auth_level=func.AuthLevel.ANONYMOUS)
async def register_apis(req: func.HttpRequest) -> func.HttpResponse:
return await func.AsgiMiddleware(fastapi_app).handle_async(req)
On line 1, you can define the name that you want to give all the http triggers (this will only be visible in the Azure Portal as one of the functions) On line 2 we define the route, notice this is a variable because it needs to be able to handle all routes. The register_apis function will register the fastapi_app in the Azure Function app Middleware
At this point you can run/debug the code () And you will notice it returns your BlobTrigger and the http_trigger(FastAPI)
Step 3.5 - Add a fastapi route
- Create a folder routes in the root
- In that folder create a file hello_world.py
- Add following code to that file
import fastapi
router = fastapi.APIRouter()
@router.post("/hello_world")
async def chat() -> str:
return "Hello World via POST"
@router.get("/hello_world")
async def chat() -> str:
return "Hello World via GET"
On line 3 we initialize the fastapi Router. The APIRouter class in FastAPI is used to group path operations, allowing you to structure your app across multiple files. You can include it directly in your FastAPI app or nest it within another APIRouter. It’s a powerful tool for organizing routes and keeping your codebase clean and maintainable.
Because of our combination with Azure Functions we need to make use of this router class. Notice that 1 file can have multiple endpoints. In this example we have a POST and a GET statement.
If you run this, it will not work yet. Why? Because we still need to register the route in the fastapi app.
Go back to the function_app.py and import your route
from routes import hello_world
And finally register your route with the fastapi app
fastapi_app = fastapi.FastAPI(
root_path="",
version="v1")
fastapi_app.include_router(hello_world.router)
Time to run/debug. Notice that no functions are added to the list. All fastapi functions are behind the http_trigger.
But!!!
I have OpenAPI documentation, an awesome feature of FastAPI, out of the box. Just surf to your endpoint /docs (http://localhost:7071/docs)
Template?
Offcourse the full template can be found on my github. Just clone it and add your own endpoints
https://github.com/sammydeprez/fastapi-azure-function-template
Just share or tag me if you like this blog!