Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

fastapi dependency vs middleware

Tags:

python

fastapi

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?

like image 763
Prabhat Avatar asked Mar 15 '21 05:03

Prabhat


People also ask

What is the use of middleware in FastAPI?

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.

What are dependencies in FastAPI?

"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".

How to add middleware in FastAPI?

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.

Is FastAPI asgi?

As FastAPI is based on Starlette and implements the ASGI specification, you can use any ASGI middleware.

Can you add middleware to fastapi applications?

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.

How do I declare dependencies in fastapi?

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.

What is the difference between dependency and middleware?

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).

When does the context variable get reset in fastapi?

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.


2 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

like image 166
lsabi Avatar answered Oct 17 '22 16:10

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!

like image 4
piyushere Avatar answered Oct 17 '22 17:10

piyushere