From a8fbf2b340de73f9c50da01001e0d41db5904cee Mon Sep 17 00:00:00 2001 From: vvanglro <947001731@qq.com> Date: Fri, 4 Nov 2022 16:56:43 +0800 Subject: [PATCH 1/5] fix: request / router KeyError --- fastapi_cache/decorator.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fastapi_cache/decorator.py b/fastapi_cache/decorator.py index 0aea981..fb08e00 100644 --- a/fastapi_cache/decorator.py +++ b/fastapi_cache/decorator.py @@ -78,9 +78,9 @@ def cache( # if the wrapped function does NOT have request or response in its function signature, # make sure we don't pass them in as keyword arguments if not request_param: - kwargs.pop("request") + kwargs.pop("request", None) if not response_param: - kwargs.pop("response") + kwargs.pop("response", None) if inspect.iscoroutinefunction(func): # async, return as is. From 4cb4afeff052064b282b4596e6ef8aee4acf45bf Mon Sep 17 00:00:00 2001 From: vvanglro <947001731@qq.com> Date: Fri, 4 Nov 2022 17:31:37 +0800 Subject: [PATCH 2/5] feat: support cache JSONResponse --- fastapi_cache/coder.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/fastapi_cache/coder.py b/fastapi_cache/coder.py index b6cd683..7dd5dfe 100644 --- a/fastapi_cache/coder.py +++ b/fastapi_cache/coder.py @@ -6,6 +6,7 @@ from typing import Any, Dict, Union import pendulum from fastapi.encoders import jsonable_encoder +from starlette.responses import JSONResponse from starlette.templating import _TemplateResponse as TemplateResponse CONVERTERS = { @@ -51,6 +52,8 @@ class Coder: class JsonCoder(Coder): @classmethod def encode(cls, value: Any) -> str: + if isinstance(value, JSONResponse): + return value.body return json.dumps(value, cls=JsonEncoder) @classmethod From 2710129c4e85dfd2770108aef6d3cdd11bfa8c5f Mon Sep 17 00:00:00 2001 From: vvanglro <947001731@qq.com> Date: Fri, 4 Nov 2022 17:34:20 +0800 Subject: [PATCH 3/5] feat: cache response obj add test case --- examples/in_memory/main.py | 9 ++++++++- examples/redis/main.py | 8 +++++++- tests/test_decorator.py | 10 ++++++++++ 3 files changed, 25 insertions(+), 2 deletions(-) diff --git a/examples/in_memory/main.py b/examples/in_memory/main.py index 1df6bc2..471899e 100644 --- a/examples/in_memory/main.py +++ b/examples/in_memory/main.py @@ -2,7 +2,7 @@ import pendulum import uvicorn from fastapi import FastAPI from starlette.requests import Request -from starlette.responses import Response +from starlette.responses import Response, JSONResponse from fastapi_cache import FastAPICache from fastapi_cache.backends.inmemory import InMemoryBackend @@ -42,6 +42,7 @@ async def get_date(): async def get_datetime(request: Request, response: Response): return {"now": pendulum.now()} + @app.get("/sync-me") @cache(namespace="test") def sync_me(): @@ -50,6 +51,12 @@ def sync_me(): return 42 +@app.get("/cache_response_obj") +@cache(namespace="test", expire=5) +async def cache_response_obj(): + return JSONResponse({"a": 1}) + + @app.on_event("startup") async def startup(): FastAPICache.init(InMemoryBackend()) diff --git a/examples/redis/main.py b/examples/redis/main.py index 773416e..98d1401 100644 --- a/examples/redis/main.py +++ b/examples/redis/main.py @@ -6,7 +6,7 @@ import uvicorn from fastapi import FastAPI from redis.asyncio.connection import ConnectionPool from starlette.requests import Request -from starlette.responses import Response +from starlette.responses import Response, JSONResponse from fastapi.responses import HTMLResponse from fastapi.staticfiles import StaticFiles from fastapi.templating import Jinja2Templates @@ -73,6 +73,12 @@ async def cache_html(request: Request): }) +@app.get("/cache_response_obj") +@cache(namespace="test", expire=5) +async def cache_response_obj(): + return JSONResponse({"a": 1}) + + @app.on_event("startup") async def startup(): pool = ConnectionPool.from_url(url="redis://redis") diff --git a/tests/test_decorator.py b/tests/test_decorator.py index 6d54aef..9ebb1ac 100644 --- a/tests/test_decorator.py +++ b/tests/test_decorator.py @@ -58,3 +58,13 @@ def test_sync() -> None: with TestClient(app) as client: response = client.get("/sync-me") assert response.json() == 42 + + +def test_cache_response_obj() -> None: + with TestClient(app) as client: + cache_response = client.get("cache_response_obj") + assert cache_response.json() == {"a": 1} + get_cache_response = client.get("cache_response_obj") + assert get_cache_response.json() == {"a": 1} + assert get_cache_response.headers.get("cache-control") + assert get_cache_response.headers.get("etag") From c1484a46fd80ece74d4635493405ddb6c43c893d Mon Sep 17 00:00:00 2001 From: vvanglro <947001731@qq.com> Date: Fri, 4 Nov 2022 17:44:41 +0800 Subject: [PATCH 4/5] feat: CHANGELOG.md --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index a136d3b..c7ab938 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,10 @@ ### 0.2.1 - Support cache jinja2 template response. +- Support cache `JSONResponse` +- Add `py.typed` file and type hints +- Add TestCase +- Fix cache decorate sync function ### 0.2.0 From 0d964fcf9f6cec23facc6ce0022d98475dfa4703 Mon Sep 17 00:00:00 2001 From: vvanglro <947001731@qq.com> Date: Sat, 7 Jan 2023 13:55:41 +0800 Subject: [PATCH 5/5] fix: remove unused --- examples/redis/main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/redis/main.py b/examples/redis/main.py index e4c0ceb..19a272a 100644 --- a/examples/redis/main.py +++ b/examples/redis/main.py @@ -4,7 +4,7 @@ import pendulum import redis.asyncio as redis import uvicorn from fastapi import FastAPI -from starlette.responses import Response, JSONResponse +from starlette.responses import JSONResponse from fastapi.responses import HTMLResponse from fastapi.staticfiles import StaticFiles from fastapi.templating import Jinja2Templates