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?
A "middleware" is a function that works with every request before it is processed by any specific path operation. And also with every response before returning it. It takes each request that comes to your application. It can then do something to that request or run any needed code.
"Dependency Injection" means, in programming, that there is a way for your code (in this case, your path operation functions) to declare things that it requires to work and use: "dependencies".
As FastAPI is actually Starlette underneath, you could use BaseHTTPMiddleware that allows you to implement a middleware class (you may want to have a look at this post as well). Below are given two variants of the same approach to do that, where the add_middleware() function is used to add the middleware class.
As FastAPI is based on Starlette and implements the ASGI specification, you can use any ASGI middleware.
You can add middleware to FastAPI applications. A "middleware" is a function that works with every request before it is processed by any specific path operation. And also with every response before returning it. It takes each request that comes to your application. It can then do something to that request or run any needed code.
As dependencies will also be called by FastAPI (the same as your path operation functions ), the same rules apply while defining your functions. You can use async def or normal def. And you can declare dependencies with async def inside of normal def path operation functions, or def dependencies inside of async def path operation functions, etc.
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).
Its happens after the request has been handled and session is being closed. The problem is that FastAPI would reset the context variable in the set_request_id () middleware function before the remove_session method in db_session () dependency is called.
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
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!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With