FastAPI Cache的@cache 装饰器会自动收集被装饰的函数参数,构建缓存key。不过在实际使用过程中,默认key builder会在有些场景下会不适用。

1、不包含self的key builder

主要用于装饰一个类中的方法,需要在构建key的时候去掉参数的类方法中的self参数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
def noself_key_builder(
func: Callable,
namespace: Optional[str] = "",
request: Optional[Request] = None,
response: Optional[Response] = None,
args: Optional[tuple] = None,
kwargs: Optional[dict] = None,
) -> str:
"""使用在类函数上的cache key builder.

本key builder在计算key的时候忽略self, 以免每次self不同导致key不同
"""
prefix = f"{FastAPICache.get_prefix()}:{namespace}:"
ordered_kwargs = sorted(kwargs.items())
noself_args = args[1:] if args else args
return (
prefix
+ hashlib.sha256( # nosec:B303
f"{func.__module__}:{func.__name__}:{noself_args}:{ordered_kwargs}".encode(),
).hexdigest()
)

2、将请求的header也纳入key计算

有的时候,会有些参数通过header进行传递,这个key builder将header跟query参数一同纳入key计算。注意这里没有纳入body内容,主要是因为需要使用body传递的请求基本都是POST请求,POST请求一般不需要缓存。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
def request_key_builder(
func: Callable,
namespace: Optional[str] = "",
request: Optional[Request] = None,
response: Optional[Response] = None,
args: Optional[tuple] = None,
kwargs: Optional[dict] = None,
) -> str:
"""API route上使用的key builder.

本key builder在计算key的时候使用Url参数与header参数, 没有采用body. 缓存建议使用在GET请求中,
有body的请求一般都是POST类请求, 不建议加缓存
"""
prefix = f"{FastAPICache.get_prefix()}:{namespace}:"
query_params = repr(sorted(request.query_params.items()))
header_params = repr(sorted(request.headers.items()))
return (
prefix
+ hashlib.sha256(
f"{request.method.lower()}:{request.url.path}:{query_params}:{header_params}".encode(),
).hexdigest()
)