Package: fastapi-cache2-fork
fastapi-cacheIntroductionfastapi-cacheis a tool to cache FastAPI endpoint and function results, with
backends supporting Redis, Memcached, and Amazon DynamoDB.FeaturesSupportsredis,memcache,dynamodb, andin-memorybackends.Easy integration withFastAPI.Support for HTTP cache headers likeETagandCache-Control, as well as conditionalIf-Match-Nonerequests.RequirementsFastAPIrediswhen usingRedisBackend.memcachewhen usingMemcacheBackend.aiobotocorewhen usingDynamoBackend.Install>pipinstallfastapi-cache2or>pipinstall"fastapi-cache2[redis]"or>pipinstall"fastapi-cache2[memcache]"or>pipinstall"fastapi-cache2[dynamodb]"UsageQuick Startfromcollections.abcimportAsyncGeneratorfromcontextlibimportasynccontextmanagerfromfastapiimportFastAPIfromstarlette.requestsimportRequestfromstarlette.responsesimportResponsefromfastapi_cacheimportFastAPICachefromfastapi_cache.backends.redisimportRedisBackendfromfastapi_cache.decoratorimportcacheimportredis.asyncioasredisfromredis.asyncio.connectionimportConnectionPool@asynccontextmanagerasyncdeflifespan(_app:FastAPI)->AsyncGenerator[None,None]:pool=ConnectionPool.from_url(url="redis://localhost")r=redis.Redis(connection_pool=pool)FastAPICache.init(RedisBackend(r),prefix="fastapi-cache")yieldapp=FastAPI(lifespan=lifespan)@cache()asyncdefget_cache():return1@app.get("/")@cache(expire=60)asyncdefindex():returndict(hello="world")InitializationFirst you must callFastAPICache.initduring startup FastAPI startup; this is where you set global configuration.Use the@cachedecoratorIf you want cache a FastAPI response transparently, you can use the@cachedecorator between the router decorator and the view function.Parametertypedefaultdescriptionexpireintsets the caching time in secondsnamespacestr""namespace to use to store certain cache itemscoderCoderJsonCoderwhich coder to use, e.g.JsonCoderkey_builderKeyBuildercallabledefault_key_builderwhich key builder to useinjected_dependency_namespacestr__fastapi_cacheprefix for injected dependency keywords.cache_status_headerstrX-FastAPI-CacheName for the header on the response indicating if the request was served from cache; eitherHITorMISS.You can also use the@cachedecorator on regular functions to cache their result.Injected Request and Response dependenciesThecachedecorator injects dependencies for theRequestandResponseobjects, so that it can add cache control headers to the outgoing response, and
return a 304 Not Modified response when the incoming request has a matchingIf-Non-Matchheader. This only happens if the decorated endpoint doesn't already
list these dependencies already.The keyword arguments for these extra dependencies are named__fastapi_cache_requestand__fastapi_cache_responseto minimize collisions.
Use theinjected_dependency_namespaceargument to@cacheto change the
prefix used if those names would clash anyway.Supported data typesWhen using the (default)JsonCoder, the cache can store any data type that FastAPI can convert to JSON, including Pydantic models and dataclasses,providedthat your endpoint has a correct return type annotation. An
annotation is not needed if the return type is a standard JSON-supported Python
type such as a dictionary or a list.E.g. for an endpoint that returns a Pydantic model namedSomeModel, the return annotation is used to ensure that the cached result is converted back to the correct class:from.modelsimportSomeModel,create_some_model@app.get("/foo")@cache(expire=60)asyncdeffoo()->SomeModel:returncreate_some_model()It is not sufficient to configure a response model in the route decorator; the cache needs to know what the method itself returns. If no return type decorator is given, the primitive JSON type is returned instead.For broader type support, use thefastapi_cache.coder.PickleCoderor implement a custom coder (see below).Custom coderBy default useJsonCoder, you can write custom coder to encode and decode cache result, just need
inheritfastapi_cache.coder.Coder.fromtypingimportAnyimportorjsonfromfastapi.encodersimportjsonable_encoderfromfastapi_cacheimportCoderclassORJsonCoder(Coder):@classmethoddefencode(cls,value:Any)->bytes:returnorjson.dumps(value,default=jsonable_encoder,option=orjson.OPT_NON_STR_KEYS|orjson.OPT_SERIALIZE_NUMPY,)@classmethoddefdecode(cls,value:bytes)->Any:returnorjson.loads(value)@app.get("/")@cache(expire=60,coder=ORJsonCoder)asyncdefindex():returndict(hello="world")Custom key builderBy default thedefault_key_builderbuiltin key builder is used; this creates a
cache key from the function module and name, and the positional and keyword
arguments converted to theirrepr()representations, encoded as a MD5 hash.
You can provide your own by passing a key builder in to@cache(), or toFastAPICache.init()to apply globally.For example, if you wanted to use the request method, URL and query string as a cache key instead of the function identifier you could use:defrequest_key_builder(func,namespace:str="",*,request:Request=None,response:Response=None,*args,**kwargs,):return":".join([namespace,request.method.lower(),request.url.path,repr(sorted(request.query_params.items()))])@app.get("/")@cache(expire=60,key_builder=request_key_builder)asyncdefindex():returndict(hello="world")Backend notesInMemoryBackendTheInMemoryBackendstores cache data in memory and only deletes when an
expired key is accessed. This means that if you don't access a function after
data has been cached, the data will not be removed automatically.RedisBackendWhen using the Redis backend, please make sure you pass in a redis client that doesnotdecode responses(decode_responsesmustbeFalse, which is the default). Cached data is stored asbytes(binary), decoding these in the Redis client would break caching.Tests and coveragecoveragerun-mpytest
coveragehtml
xdg-openhtmlcov/index.htmlLicenseThis project is licensed under theApache-2.0License.