Cache Control
By defaults httpx-cache caches every response that:
- has a cacheable status_code in
(200, 203, 300, 301, 308)(can be modified) - corresponding request has a cacheable method in
('GET',)(can be modified) - corresponding request has an absolute url
Enabling/Disabling cache can also be configured at the operation level using cache-control headers directives (https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control)
Disable Checking Cache
Disabling cache on a particular request can be achieved by setting either the cache-control: no-cache or cache-control: max-age=0 headers.
The
no-cacherequest directive asks caches to validate the response with the origin server before reuse.no-cacheallows clients to request the most up-to-date response even if the cache has a fresh response. Browsers usually add no-cache to requests when users are force reloading a page.
import httpx_cache
with httpx_cache.Client() as client:
response1 = client.get("https://httpbin.org/get") # will be cached
response2 = client.get("https://httpbin.org/get", headers={"cache-control": "no-cache"})
# will NOT get it from cache, but it will make a new request that then will be re-cached again (refreched in the cache)
Disable Storing in Cache
Sometimes we want to make a request but not store a response in cache, so that we always get the freshest response. This can be achieved with cache-control: no-store header.
The no-store response/request directive indicates that any caches of any kind (private or shared) should not store this response.
NOTE: a no-store cache-control directive can also be set on the response headers by the server, in that case it will not be cached too.
import httpx_cache
with httpx_cache.Client() as client:
response1 = client.get("https://httpbin.org/get", headers={"cache-control": "no-cache"}) # will not be stored in cache
response2 = client.get("https://httpbin.org/get")
# cache is empty since previous request was not stored, will make a new request.
Always Cache
In the case where we want to ignore the no-store directive in the response headers, we can set the parameter always_cache=True. This parameter can be set on the client or on the transport.
Note: Event when
always_cache=True is set, the cache controller will still does the basic checks to make sure the response is cacheable, namely: status_code is cacheable, request method is cacheable, and request url is absolute.
Usage with client:
import httpx_cache
with httpx_cache.Client(always_cache=True) as client:
response1 = client.get("https://httpbin.org/get", headers={"cache-control": "no-store"}) # will be stored in cache
response2 = client.get("https://httpbin.org/get")
# cache is not empty since previous request was stored, will NOT make a new request.
Usage with transport:
import httpx_cache
with httpx_cache.Client(transport=httpx_cache.CachedTransport(always_cache=True)) as client:
response1 = client.get("https://httpbin.org/get", headers={"cache-control": "no-store"}) # will be stored in cache
response2 = client.get("https://httpbin.org/get")
# cache is not empty since previous request was stored, will NOT make a new request.
Cache Expiration
Max-Age Directive
Cache expiration can be controlled with the request (or response) max-age direvtive (directives found in a request take precedence over those in a response.)
The
max-age=Nrequest or response directive indicates that the client allows a stored response that is generated on the origin server within N seconds. Ff the response withcache-control: max-age=604800was stored in caches 3 hours ago,httpx-cachecouldn't reuse that response.
import httpx_cache
import time
with httpx_cache.Client() as client:
response1 = client.get("https://httpbin.org/get") # store in cache at time T
time.sleep(10) # sleep for 10s (T+10)
response2 = client.get("https://httpbin.org/get", headers={"cache-control": "max-age=5"}) # response in cache has expried since T+5 < T+10
# cached response will be deleted
Expires Header
In addition to the max-age directive, we can achieve the same effect with the expires header.
Use your own CacheController
To use your own cache controller with custom logic for when to cache a response, you can directly subclass httpx_cache.CacheController and httpx_cache.CacheControlTransport (or httpx_cache.AsyncCacheControlTransport):
import httpx
import httpx_cache
class MyCacheController(httpx_cache.CacheController):
def is_response_cacheable(self, response: httpx.Response) -> bool:
# always cache responses
return True
class MyCacheControlTransport(httpx_cache.CacheControlTransport):
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.cache_controller = MyCacheController()