feat: add response cache middleware with poisoning-safe keys
This commit is contained in:
@@ -0,0 +1,44 @@
|
||||
"""Redis 缓存后端: 笨 KV(CacheBackend 契约);redis 是 optional extra。
|
||||
|
||||
降级不在这里做——本类忠实上抛异常,静默降级是 CacheMW 的职责(算法一份)。
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any
|
||||
|
||||
try:
|
||||
import redis.asyncio as aioredis
|
||||
except ImportError as _exc: # pragma: no cover - 依赖缺失路径
|
||||
aioredis = None
|
||||
_IMPORT_ERROR = _exc
|
||||
else:
|
||||
_IMPORT_ERROR = None
|
||||
|
||||
|
||||
class RedisCache:
|
||||
"""基于 redis.asyncio 的 KV;value 为 JSON 字符串,TTL 由调用方传入。"""
|
||||
|
||||
def __init__(self, client: Any) -> None:
|
||||
if aioredis is None:
|
||||
raise ImportError(
|
||||
"Redis 缓存后端需要 redis 包: pip install 'polygateway[redis]'"
|
||||
) from _IMPORT_ERROR
|
||||
self._client = client
|
||||
|
||||
@classmethod
|
||||
def from_url(cls, url: str) -> RedisCache:
|
||||
if aioredis is None:
|
||||
raise ImportError(
|
||||
"Redis 缓存后端需要 redis 包: pip install 'polygateway[redis]'"
|
||||
) from _IMPORT_ERROR
|
||||
return cls(aioredis.from_url(url, decode_responses=True))
|
||||
|
||||
async def get(self, key: str) -> str | None:
|
||||
return await self._client.get(key)
|
||||
|
||||
async def set(self, key: str, value: str, ttl_s: int) -> None:
|
||||
await self._client.set(key, value, ex=ttl_s)
|
||||
|
||||
async def aclose(self) -> None:
|
||||
await self._client.aclose()
|
||||
Reference in New Issue
Block a user