fastapi-cache is a tool to cache fastapi response and function result, with backends support redis and memcached.

Overview

fastapi-cache

pypi license workflows workflows

Introduction

fastapi-cache is a tool to cache fastapi response and function result, with backends support redis, memcache, and dynamodb.

Features

  • Support redis, memcache, dynamodb, and in-memory backends.
  • Easily integration with fastapi.
  • Support http cache like ETag and Cache-Control.

Requirements

  • asyncio environment.
  • redis if use RedisBackend.
  • memcache if use MemcacheBackend.
  • aiobotocore if use DynamoBackend.

Install

> pip install fastapi-cache2

or

> pip install "fastapi-cache2[redis]"

or

> pip install "fastapi-cache2[memcache]"

or

> pip install "fastapi-cache2[dynamodb]"

Usage

Quick Start

import aioredis
from fastapi import FastAPI
from starlette.requests import Request
from starlette.responses import Response

from fastapi_cache import FastAPICache
from fastapi_cache.backends.redis import RedisBackend
from fastapi_cache.decorator import cache

app = FastAPI()


@cache()
async def get_cache():
    return 1


@app.get("/")
@cache(expire=60)
async def index(request: Request, response: Response):
    return dict(hello="world")


@app.on_event("startup")
async def startup():
    redis =  aioredis.from_url("redis://localhost", encoding="utf8", decode_responses=True)
    FastAPICache.init(RedisBackend(redis), prefix="fastapi-cache")

Initialization

Firstly you must call FastAPICache.init on startup event of fastapi, there are some global config you can pass in.

Use cache decorator

If you want cache fastapi response transparently, you can use cache as decorator between router decorator and view function and must pass request as param of view function.

Parameter type, description
expire int, states a caching time in seconds
namespace str, namespace to use to store certain cache items
coder which coder to use, e.g. JsonCoder
key_builder which key builder to use, default to builtin

And if you want use ETag and Cache-Control features, you must pass response param also.

You can also use cache as decorator like other cache tools to cache common function result.

Custom coder

By default use JsonCoder, you can write custom coder to encode and decode cache result, just need inherit fastapi_cache.coder.Coder.

@app.get("/")
@cache(expire=60,coder=JsonCoder)
async def index(request: Request, response: Response):
    return dict(hello="world")

Custom key builder

By default use builtin key builder, if you need, you can override this and pass in cache or FastAPICache.init to take effect globally.

def my_key_builder(
    func,
    namespace: Optional[str] = "",
    request: Request = None,
    response: Response = None,
    *args,
    **kwargs,
):
    prefix = FastAPICache.get_prefix()
    cache_key = f"{prefix}:{namespace}:{func.__module__}:{func.__name__}:{args}:{kwargs}"
    return cache_key

@app.get("/")
@cache(expire=60,coder=JsonCoder,key_builder=my_key_builder)
async def index(request: Request, response: Response):
    return dict(hello="world")

InMemoryBackend

InMemoryBackend store cache data in memory and use lazy delete, which mean if you don't access it after cached, it will not delete automatically.

License

This project is licensed under the Apache-2.0 License.

Comments
  • Make request parameter optional in user code

    Make request parameter optional in user code

    Hello, this PR makes request: Request parameter optional in user code by forcibly adding it to wrapped function signature I'd like to know if that change would be welcomed or not since it seems a bit hacky and it adds more complexity to the code

    opened by ThirVondukr 7
  • how to check if the data in cache is empty and then load data into the indicated cache?

    how to check if the data in cache is empty and then load data into the indicated cache?

    for example, how to check if there is None data in the cache "test" of the following function section_data? and how to load new data into it if it is empty.

    def my_key_builder(   func,  namespace: Optional[str] = "",  request: Request = None, response: Response = None, *args,  **kwargs,):
        prefix = FastAPICache.get_prefix()
        cache_key = f"{prefix}:{namespace}:{func.__module__}:{func.__name__}:{args}:{kwargs}"
        return cache_key
    
    @app.get('/data',response_model=List[Dict])
    @cache(namespace="test", expire=60,key_builder=my_key_builder)
    async def section_data( ):
        data= func('section')
        return data
    

    Thanks a lot

    opened by marcusau 6
  • [question] how to cache 200 http responses only?

    [question] how to cache 200 http responses only?

    I'm not sure how to discard 500 and 400 errors from cache using InMemoryBackend. My usecase depends on an external provider, but I want to cache only success responses. If the provider fails I want to keep asking for the data. I tried to inject 'no-cache' header but request headers are inmutable.

    opened by PieroValdebenito 5
  • Add dynamodb backend support

    Add dynamodb backend support

    Add support for Amazon DynamoDB backends using aiobotocore.

    Usage: >> dynamodb = DynamoBackend(table_name="your-cache", region="eu-west-1") >> await dynamodb.init() >> FastAPICache.init(dynamodb)

    opened by geo-mathijs 4
  • Error thrown : TypeError: object list can't be used in 'await' expression

    Error thrown : TypeError: object list can't be used in 'await' expression

    File "/usr/local/lib/python3.8/site-packages/uvicorn/protocols/http/httptools_impl.py", line 398, in run_asgi result = await app(self.scope, self.receive, self.send) File "/usr/local/lib/python3.8/site-packages/uvicorn/middleware/proxy_headers.py", line 45, in call return await self.app(scope, receive, send) File "/usr/local/lib/python3.8/site-packages/fastapi/applications.py", line 208, in call await super().call(scope, receive, send) File "/usr/local/lib/python3.8/site-packages/starlette/applications.py", line 112, in call await self.middleware_stack(scope, receive, send) File "/usr/local/lib/python3.8/site-packages/starlette/middleware/errors.py", line 181, in call raise exc from None File "/usr/local/lib/python3.8/site-packages/starlette/middleware/errors.py", line 159, in call await self.app(scope, receive, _send) File "/usr/local/lib/python3.8/site-packages/timing_asgi/middleware.py", line 68, in call await self.app(scope, receive, send_wrapper) File "/usr/local/lib/python3.8/site-packages/starlette/middleware/cors.py", line 86, in call await self.simple_response(scope, receive, send, request_headers=headers) File "/usr/local/lib/python3.8/site-packages/starlette/middleware/cors.py", line 142, in simple_response await self.app(scope, receive, send) File "/usr/local/lib/python3.8/site-packages/starlette/exceptions.py", line 82, in call raise exc from None File "/usr/local/lib/python3.8/site-packages/starlette/exceptions.py", line 71, in call await self.app(scope, receive, sender) File "/usr/local/lib/python3.8/site-packages/starlette/routing.py", line 580, in call await route.handle(scope, receive, send) File "/usr/local/lib/python3.8/site-packages/starlette/routing.py", line 241, in handle await self.app(scope, receive, send) File "/usr/local/lib/python3.8/site-packages/starlette/routing.py", line 52, in app response = await func(request) File "/usr/local/lib/python3.8/site-packages/fastapi/routing.py", line 226, in app raw_response = await run_endpoint_function( File "/usr/local/lib/python3.8/site-packages/fastapi/routing.py", line 159, in run_endpoint_function return await dependant.call(**values) File "/usr/local/lib/python3.8/site-packages/fastapi_cache/decorator.py", line 47, in inner ret = await func(*args, **kwargs) TypeError: object list can't be used in 'await' expression

    opened by omshankar1 4
  • Add minimum dependencies version

    Add minimum dependencies version

    At the current moment, it's impossible to install this package via poetry because of a min version conflict with the extras specified in pyproject.toml. It's probably best to set a minimum/explicit version and then have Dependabot tests against new updates instead of having *

    opened by rushilsrivastava 4
  • fix bug by adding utf-8

    fix bug by adding utf-8

    fix File "c:\Users\jackm\GitHub\pool-api\wvenv\lib\site-packages\fastapi_cache\key_builder.py", line 21, in default_key_builder + hashlib.md5( # nosec:B303 TypeError: Unicode-objects must be encoded before hashing #19

    opened by jack60612 3
  • [Errno 111] Connection refused

    [Errno 111] Connection refused

    My application is fully dockerized, it was working fine with fastapi. Im trying to add cache but It seems to have an error.

    Im getting an error trying to create_redis_pool. I tried using localhost, also other ports without any luck.

    @app.on_event("startup")
    async def startup():
        redis = await aioredis.create_redis_pool("redis://127.0.0.1", encoding="utf8")
        FastAPICache.init(RedisBackend(redis), prefix="fastapi-cache")
    

    Also ports are mapped on the docker-compose.yml

    opened by ollita7 3
  • fastapi-cache 0.1.4: TypeError: Unicode-objects must be encoded before hashing

    fastapi-cache 0.1.4: TypeError: Unicode-objects must be encoded before hashing

    Hi,

    I updated fastapi-cache using Github to solve the problem of "not JSON serializable", but now I have a new error:

      File "/lib/python3.9/site-packages/fastapi_cache/decorator.py", line 40, in inner
        cache_key = key_builder(
      File "/lib/python3.9/site-packages/fastapi_cache/key_builder.py", line 21, in default_key_builder
        + hashlib.md5(  # nosec:B303
    TypeError: Unicode-objects must be encoded before hashing
    

    Before (with version 1.3.4) I was using something like this bellow, but with the two lines commented and returning the json_updated_user:

    @router.get("/me/items/", response_model=List[schemas.User_Pydantic])
    @cache(namespace="test", expire=60, coder=JsonCoder)
    async def read_current_user_items(user: UserDB = Depends(fastapi_users.get_current_active_user)):
        user_cards = await schemas.Card_Pydantic.from_queryset(
            Card.filter(owner_id=user.id).all())
        for city in user_cards:
            await weather_api.get_api_info_by_id(city.id)
        # user_with_items = await schemas.User_Pydantic.from_queryset(UserModel.filter(id=user.id).all())
        # json_updated_user = jsonable_encoder(user_with_items)
        return await schemas.User_Pydantic.from_queryset(UserModel.filter(id=user.id).all())
    

    Without jsonable_encoder I get the error "not JSON serializable", but now I have the hash error. If I comment the @cache decorator, it works fine (and I don't need the jsonable_encoder).

    Thanks in advance!

    opened by diegocgaona 3
  • Default key builder does not work with memcached

    Default key builder does not work with memcached

    Memcached does not allow spaces in keys. Thus when using the default key builder with endpoint that has dependencies, a space can be introduced when object is being represented as string. Problem example:

    @router.get("/",
                 status_code=200,
                 response_model=list)
    async def distinct_values(field: str,
                                  es: Elasticsearch = Depends(ElasticConnector)):
    

    This result in ValidationError

    Proposed solution:

    def mcache_key_builder(
        func,
        namespace: Optional[str] = "",
        request: Request = None,
        response: Response = None,
        *args,
        **kwargs,
    ):
        prefix = FastAPICache.get_prefix()
        cache_key = f"{prefix}:{namespace}:{func.__module__}:{func.__name__}:{args}:{kwargs}".replace(" ","")
        return cache_key
            ```
    opened by MrAngry 3
  • Encode args and kwargs

    Encode args and kwargs

    The args and kwargs from the decorated are imported as a string directly which causes issues when using ORMs like SQLAlchemy that use instances of Sessions are have a different string representation. These values should be encoded via the coder.

    opened by rushilsrivastava 3
  • Transparent passthrough in the event of cache backend connection issues

    Transparent passthrough in the event of cache backend connection issues

    Currently if using the cache decorator on a function with a FastAPI path operation decorator, if there are any connection issues to a backend (e.g. Redis) an unhandled exception from the backend will cause a HTTP 500 - meaning cache backend uptime becomes a requirement for API functionality. This PR sets a better default - if cache backend connectivity fails, pass the request through as you would if the decorator isn't there (reimplementation of #14)

    @long2ice @mkdir700 could you have a look please? Hopefully a quick merge for you but this failure mode is a big blocker for me to use and evangelise this library more widely. As per #99 a new release would be awesome too!

    opened by hackjammer 1
  • when request is present, cache is disabled

    when request is present, cache is disabled

    Due to this line: https://github.com/long2ice/fastapi-cache/blob/8f0920d0d7f0a34bfb8987736cf794be5e3cc33f/fastapi_cache/decorator.py#L128

    When request is present, cache is disabled. Why do we do so? Isn't it quite normal if user want to customize key builder that takes in request object?

    I can create a pr to fix this but just wondering why the design is so in the first place.

    opened by schwannden 1
  • Feat/add@cacheable

    Feat/[email protected]

    #96

    add @cacheable

    example:

    from fastapi_cache.decorator import cacheable
    
    @cacheable(key="xxx:{0}:{b}", expire=60)
    async def test_func(a: int, b: int) -> int:
        return a + b
    
    async def main():
        await test_func(1, 2)
        # cache_key -> 'xxx:1:2'
    
    opened by mkdir700 0
  • How to cache `StreamingResponse`?

    How to cache `StreamingResponse`?

    Hi, is there a way to cache StreamingResponse?

    Currently i get:

    ValueError: [TypeError("'async_generator' object is not iterable"), TypeError('vars() argument must have __dict__ attribute')]
    
    opened by mglowinski93 5
Releases(v0.1.9)
Keepalive - Discord Bot to keep threads from expiring

keepalive Discord Bot to keep threads from expiring Installation Create a new Di

Francesco Pierfederici 5 Mar 14, 2022
Fast, simple API for Apple firmwares.

Loyal Fast, Simple API for fetching Apple Firmwares. The API server is closed due to some reasons. Wait for v2 releases. Features Fetching Signed IPSW

11 Oct 28, 2022
Starlette middleware for Prerender

Prerender Python Starlette Starlette middleware for Prerender Documentation: https://BeeMyDesk.github.io/prerender-python-starlette/ Source Code: http

BeeMyDesk 14 May 02, 2021
flask extension for integration with the awesome pydantic package

flask extension for integration with the awesome pydantic package

249 Jan 06, 2023
Prometheus exporter for Starlette and FastAPI

starlette_exporter Prometheus exporter for Starlette and FastAPI. The middleware collects basic metrics: Counter: starlette_requests_total Histogram:

Steve Hillier 225 Jan 05, 2023
FastAPI IPyKernel Sandbox

FastAPI IPyKernel Sandbox This repository is a light-weight FastAPI project that is meant to provide a wrapper around IPyKernel interactions. It is in

Nick Wold 2 Oct 25, 2021
FastAPI with async for generating QR codes and bolt11 for Lightning Addresses

sendsats An API for getting QR codes and Bolt11 Invoices from Lightning Addresses. Share anywhere; as a link for tips on a twitter profile, or via mes

Bitkarrot 12 Jan 07, 2023
Cbpa - Coinbase Pro Automation for buying your favourite cryptocurrencies

cbpa Coinbase Pro Automation for making buy orders from a default bank account.

Anthony Corletti 3 Nov 27, 2022
FastAPI + PeeWee = <3

FastAPIwee FastAPI + PeeWee = 3 Using Python = 3.6 🐍 Installation pip install FastAPIwee 🎉 Documentation Documentation can be found here: https://

16 Aug 30, 2022
A simple example of deploying FastAPI as a Zeit Serverless Function

FastAPI Zeit Now Deploy a FastAPI app as a Zeit Serverless Function. This repo deploys the FastAPI SQL Databases Tutorial to demonstrate how a FastAPI

Paul Weidner 26 Dec 21, 2022
Code for my FastAPI tutorial

FastAPI tutorial Code for my video tutorial FastAPI tutorial What is FastAPI? FastAPI is a high-performant REST API framework for Python. It's built o

José Haro Peralta 9 Nov 15, 2022
A Python framework to build Slack apps in a flash with the latest platform features.

Bolt for Python A Python framework to build Slack apps in a flash with the latest platform features. Read the getting started guide and look at our co

SlackAPI 684 Jan 09, 2023
Adds integration of the Chameleon template language to FastAPI.

fastapi-chameleon Adds integration of the Chameleon template language to FastAPI. If you are interested in Jinja instead, see the sister project: gith

Michael Kennedy 124 Nov 26, 2022
This is an API developed in python with the FastApi framework and putting into practice the recommendations of the book Clean Architecture in Python by Leonardo Giordani,

This is an API developed in python with the FastApi framework and putting into practice the recommendations of the book Clean Architecture in Python by Leonardo Giordani,

0 Sep 24, 2022
FastAPI Project Template

The base to start an openapi project featuring: SQLModel, Typer, FastAPI, JWT Token Auth, Interactive Shell, Management Commands.

A.Freud 4 Dec 05, 2022
An alternative implement of Imjad API | Imjad API 的开源替代

HibiAPI An alternative implement of Imjad API. Imjad API 的开源替代. 前言 由于Imjad API这是什么?使用人数过多, 致使调用超出限制, 所以本人希望提供一个开源替代来供社区进行自由的部署和使用, 从而减轻一部分该API的使用压力 优势

Mix Technology 450 Dec 29, 2022
FastAPI-Amis-Admin is a high-performance, efficient and easily extensible FastAPI admin framework. Inspired by django-admin, and has as many powerful functions as django-admin.

简体中文 | English 项目介绍 FastAPI-Amis-Admin fastapi-amis-admin是一个拥有高性能,高效率,易拓展的fastapi管理后台框架. 启发自Django-Admin,并且拥有不逊色于Django-Admin的强大功能. 源码 · 在线演示 · 文档 · 文

AmisAdmin 318 Dec 31, 2022
A kedro-plugin to serve Kedro Pipelines as API

General informations Software repository Latest release Total downloads Pypi Code health Branch Tests Coverage Links Documentation Deployment Activity

Yolan Honoré-Rougé 12 Jul 15, 2022
Opentracing support for Starlette and FastApi

Starlette-OpenTracing OpenTracing support for Starlette and FastApi. Inspired by: Flask-OpenTracing OpenTracing implementations exist for major distri

Rene Dohmen 63 Dec 30, 2022
Fastapi-ml-template - Fastapi ml template with python

FastAPI ML Template Run Web API Local $ sh run.sh # poetry run uvicorn app.mai

Yuki Okuda 29 Nov 20, 2022