Create middleware for specific route – Python

If you are creating an API in Python, and came across a problem where you have to create a middleware but for only specific route. For example, you are creating a user authentication system and want to create a middleware that checks if the user is logged-in. But you want to use that middleware for only few routes, not for all routes. Then this tutorial is for you.

This can be done by creating subapps in Python. To create a subapp in Python, first we need to create a file where we will save the global variable of our subapp.

Create a file, let’s say config.py, and write the following code in it.

# config.py

from fastapi import FastAPI

my_middleware_app = FastAPI()

Now create a file for our middleware, I am naming it my_middleware.py. Following will be the code of this file.

from fastapi import Request
from config import my_middleware_app

from fastapi.responses import JSONResponse
from fastapi.encoders import jsonable_encoder

@my_middleware_app.middleware("http")
async def my_func(request: Request, call_next):
	if "Authorization" in request.headers:
		print(request.headers["Authorization"])

		request.state.name = "Adnan"
		response = await call_next(request)
		return response
	else:
		return JSONResponse(content=jsonable_encoder("Authorization header not provided."))

Explanation:

  1. First, it imports the subapp “my_middleware_app” from “config” module.
  2. Then it imports “JSONResponse” and “jsonable_encoder” from “fastapi” modules. They will be required to send the response back to the client.
  3. Then we are creating a middleware using our subapp “my_middleware_app”.
  4. In this, we are checking if the request has “Authorization” header provided.
    • To learn more about authorization in Python, check our tutorial on user authentication.
  5. If not, then we are sending an error.
  6. If provided, then we are attaching a “name” variable with the request and pass it to the route.

Now let me show you, how the route can use this middleware and how route can access the “name” variable.

Following will be the content of our main.py file where the route will be created.

# main.py

from fastapi import FastAPI, Request
from config import my_middleware_app
import my_middleware

app = FastAPI()

@my_middleware_app.post("/my-route")
def my_route(request: Request):
	return request.state.name

app.mount("/", my_middleware_app)

We first imported the subapp module and the middleware.

Then we created an instance of FastAPI (the main app).

After that, we are creating a post route using our subapp. In this route, we are using the “name” variable we created in our middleware.

To send value from middleware to route, we can use request.state object.

And lastly, we are mounting the subapp to our main app.

Creating a middleware and using it just for specific route in Python is a bit confusing sometimes. So if you face any problem in following this, please do not hesitate to get in touch with me.