pincoin
pincoin

Reputation: 765

fastapi sub-dependencies passing parameters and returning results

I am now developing with FastAPI and SQLAlchemy Core 1.4.

I've got my API function.

async def do_something(
    ...
    current_user: dict = Depends(get_superuser),
    conn: AsyncConnection = Depends(engine_begin),
):
   ...

do_something API depends on get_superuser and SQLAlchemy connection by engine_begin.

I am planning on sub-dependencies like this:

do_something -> get_superuser -> get_current_user

get_current_user dependency is not required to access database during JWT validation.

However, get_superuser is required to access database to check permissions or something else.

async def get_superuser(
    current_user: dict = Depends(get_current_user),
    conn: AsyncConnection = Depends(engine_connect),
) -> dict:
    ...

    return {
        "superuser": row._mapping,
        "conn": conn,
    }

I was able to make get_superuser depends on get_current_user and engine_begin, and returned dict { superuser: dict, conn: connection } as shown above.

Personally it does not make sense if get_superuser returns database connection, too.

I tried to put the path decorator dependencies=[Depends(engine_begin)] Then, I could not get the connection handle.

Another solution might be double dependencies like do_something depends on engine_begin and get_superuser depends on engine_begin. I think it will cause another problem due to nested transaction begin.

I would like to know if there is a clear way to check authorization/permission after authentication.

Thank you.

Upvotes: 1

Views: 3572

Answers (1)

MatsLindh
MatsLindh

Reputation: 52892

FastAPI will not evaluate a dependency multiple times - so your database connection will only be initialized once.

There shouldn't be any issue with having multiple dependency references such as conn: AsyncConnection = Depends(engine_connect). It just says that "I need the dependency returned by this function"; any subsequent calls will return the same created dependency.

If one of your dependencies is declared multiple times for the same path operation, for example, multiple dependencies have a common sub-dependency, FastAPI will know to call that sub-dependency only once per request.

And it will save the returned value in a "cache" and pass it to all the "dependants" that need it in that specific request, instead of calling the dependency multiple times for the same request.

In an advanced scenario where you know you need the dependency to be called at every step (possibly multiple times) in the same request instead of using the "cached" value, you can set the parameter use_cache=False when using Depends

So your assumption "I think it will cause another problem due to nested transaction begin." is wrong: it's the suggested way of handling requiring the same dependency in multiple locations.

This allows you to compose your dependencies in a very visible and helpful way, and they only get resolved if they're actually necessary somewhere in the hierarchy.

Upvotes: 3

Related Questions