Fastapi: [QUESTION] Should I set use_cache=False in Security/Depends or is it set implicitly?

Created on 26 Jun 2020  路  4Comments  路  Source: tiangolo/fastapi

First check

  • [x] I added a very descriptive title to this issue.
  • [x] I used the GitHub search to find a similar issue and didn't find it.
  • [x] I searched the FastAPI documentation, with the integrated search.
  • [x] I already searched in Google "How to X in FastAPI" and didn't find any information.
  • [x] I already read and followed all the tutorial in the docs and didn't find an answer.
  • [x] I already checked if it is not related to FastAPI but to Pydantic.
  • [x] I already checked if it is not related to FastAPI but to Swagger UI.
  • [x] I already checked if it is not related to FastAPI but to ReDoc.
  • [x] After submitting this, I commit to one of:

    • Read open issues with questions until I find 2 issues where I can help someone and add a comment to help there.

    • I already hit the "watch" button in this repository to receive notifications and I commit to help at least 2 people that ask questions in the future.

    • Implement a Pull Request for a confirmed bug.

Example

Hi, great web-framework, great work! :fire: I am in process of moving one of the backends from Flask to FastAPI and I was wondering is FastAPI using cache when dealing with auth (example below)? Password can change, somebody can delete the user or change his privileges, I hope it does not use cache in my case. Where do I put use_cache=False if it does?

async def get_user(security_scopes: SecurityScopes, credentials: HTTPBasicCredentials = Depends(_security)) -> User:
    """
    Get user from DB and check if they are authorized to do what is in security_scopes.
    I implement my own caching logic here and check if user was changed in DB.
    """

# /token endpoint
async def token(user: User = Depends(get_user)) -> JSONResponse:
    """Use Basic Auth to get token."""

# /users/{user_id} endpoint
async def get_user_by_id(user_id: int, user: User = Security(get_user, scopes=["users:read"])):
    '''Get user by ID'''

Thanks a lot! :smile:

Environment

  • OS: Linux:
  • FastAPI Version: 0.58.0
  • Python version: 3.7
question

All 4 comments

The parameter use_cache defaults to True, as we can see from FastAPI's Security function:

def Security(  # noqa: N802
    dependency: Callable = None, *, scopes: Sequence[str] = None, use_cache: bool = True
) -> Any:
    return params.Security(dependency=dependency, scopes=scopes, use_cache=use_cache)

You can pass it directly to Security, such as:
```

/users/{user_id} endpoint

async def get_user_by_id(user_id: int, user: User = Security(get_user, scopes=["users:read"], use_cache=False)):
'''Get user by ID'''

Thanks, @mlaradji ! If I need to pass use_cache=False to every endpoint explicitly - it is better to create function that does that for me :thinking:

def BetterSecurity(dependency: Callable = None, *, scopes: Sequence[str] = None) -> Any:
    return params.Security(dependency=dependency, scopes=scopes, use_cache=False)

Solution that should work and a bit cleaner:

async def get_user(security_scopes: SecurityScopes, credentials: HTTPBasicCredentials = Depends(_security)) -> User:
    """
    Get user from DB and check if they are authorized to do what is in security_scopes.
    I implement my own caching logic here and check if user was changed in DB.
    """

def Auth(scopes: Sequence[str] = None) -> Any:
    return params.Security(dependency=get_user, scopes=scopes, use_cache=False)

# /users/{user_id} endpoint
async def get_user_by_id(user_id: int, user: User = Auth(scopes=["users:read"])):
    '''Get user by ID'''

Hey, you don't really need to disable the cache. That cache is only used per-request. It only avoids, for example, getting the user from DB several times in dependencies and sub-dependencies to handle a single request.

But all that will be executed again for the next request. So it's fine to leave it. You should set use_cache=False only when you have some specific reason to make a dependency function execute more than once in a single request.

In fact, I have never found a real use case for it. I thought there would be one at some point, but it hasn't happened so far. :shrug:

Was this page helpful?
0 / 5 - 0 ratings