fastapi dependency vs middleware

Question:

Am new to fastapi. I have worked with multiple web frameworks in other languages and found the common pattern of middlewares for various purposes. e.g. If I have an API route that I want to authenticate then I would use a middleware that does the authentication. If I want to augment the incoming request I would use a middleware. FastAPI does have middlewares (A very small section in docs) but also has dependencies. I was looking to authenticate my API routes and started looking for examples and all the examples I find use dependencies. What (dependency or middleware) would be recommended way to authenticate an API route and why?

Asked By: Prabhat

||

Answers:

The way I see it:

  • Dependency: you use it to run code for preparing variables, authentication and so on.
  • Middleware: you need to check some stuff first and reject or forward the request to your logic.

The middleware can be seen as a superset of a Dependency, as the latter is a sort of middleware that returns a value which can be used in the request. Though, in the middleware, you can log your requests or cache the results and access the response of the request (or even forward the request, call some other API and so on).

TL;DR

A Dependency is a sort of common logic that is required before processing the request (e.g. I need the user id associated to this token), while a Middleware can do that, it can also access the response to that request. Dependencies are the preferred way to create a middleware for authentication

Answered By: lsabi

In a general sense, the answer given by @lsabi is correct.

In the context of FastAPI though, there’s no way of defining a middleware on a particular API router (as of Aug 2022).
All the middlewares are usually on global app level (though you can write your own logic to apply it on only a specific route by regex/filtering, not very clean solution imo), and if that’s the only way you want to go, you have to create a separate application for each route (using mounts), and then you can write their own middlewares, as explained here:
https://github.com/tiangolo/fastapi/issues/1174#issuecomment-605508353

But for route dependencies, this statement isn’t entirely true:

The middleware can be seen as a superset of a Dependency

Even though, dependencies by defination don’t reject/forward stuff, In FastAPI, you can always raise an exception (might be HTTPException) from a dependency which will cause it to reject the request, before it reaches to the route handler.

so you can do something like:

async def auth_middleware(request: Request):
   # your code to check if user is authenticated
   # ...
   raise HTTPException(
        status_code=status.HTTP_401_UNAUTHORIZED,
        detail="Not authenticated bruh"
    )

router = APIRouter(dependencies=[Depends(auth_middleware)])

now, before executing any route handler defined on the router, first it will run the auth_middleware function. Which is exactly how a middleware is supposed to work.

The only caveat here is that, because it’s a dependency, it has to run before the route handler.
So if your use case requires you to handle something after, this wouldn’t work.
I didn’t come across any such requirement, selective gzipping might be one example, but you shouldn’t be gzipping your http response in python anyway.

Hope that helps!

Answered By: piyushere
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.