Skip to content

Add methods for set cache_age in openapi schema#6

Merged
Nottezz merged 18 commits into
mainfrom
feature/add_cache-age-for-openapi
Jun 26, 2025
Merged

Add methods for set cache_age in openapi schema#6
Nottezz merged 18 commits into
mainfrom
feature/add_cache-age-for-openapi

Conversation

@Nottezz
Copy link
Copy Markdown
Collaborator

@Nottezz Nottezz commented Jun 22, 2025

Автоматическое проставления cache-age в OpenAPI схему.

@Nottezz Nottezz self-assigned this Jun 22, 2025
@Nottezz Nottezz linked an issue Jun 22, 2025 that may be closed by this pull request
@Nottezz Nottezz requested a review from chud0 June 23, 2025 10:16
Comment thread fast_cache_middleware/middleware.py Outdated
@chud0
Copy link
Copy Markdown
Owner

chud0 commented Jun 24, 2025

bugbot run

cursor[bot]

This comment was marked as outdated.

Comment thread fast_cache_middleware/middleware.py Outdated
@Nottezz Nottezz requested a review from chud0 June 24, 2025 08:00
except KeyError:
continue

app.openapi_schema = openapi_schema
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

а как она обычно подставляется? мы не ломаем какие то едж кейсы про генерацию схемы?

Copy link
Copy Markdown
Collaborator Author

@Nottezz Nottezz Jun 25, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Скорее всего ещё надо в начале прокинуть проверку схему. Доке ФастАПИ есть пример кастомной схемы - https://fastapi.tiangolo.com/how-to/extending-openapi/#normal-fastapi

Там прям так и идёт:

app.openapi_schema = openapi_schema
return app.openapi_schema

Единственное я ничего не возвращаю.

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

а в app.openapi_schema когда метод выполняется ничего нет? может схема уже готова

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

бездушная машина тоже говорит ... by always calling get_openapi(), which bypasses any custom OpenAPI schema generation logic

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Там логика такая: мы запрашиваем уже готовую схему от app, её редактируем, добавляем новые поля в ручки и передаём обновлённую схему. В прошлом варианте мы получали эту схему и целиком перезаписывали её, тем самым все пользовательские схемы перетирали.

@chud0
Copy link
Copy Markdown
Owner

chud0 commented Jun 25, 2025

bugbot run

Copy link
Copy Markdown

@cursor cursor Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: Lifespan Event Missing Type Check

The on_lifespan method calls set_cache_age_in_openapi_schema with scope["app"] without a FastAPI type check, unlike the on_http method, which can lead to runtime errors if scope["app"] is not a FastAPI instance. Furthermore, the _openapi_initialized flag is not set to True in on_lifespan after this call, causing duplicate OpenAPI schema processing on the first HTTP request.

fast_cache_middleware/middleware.py#L231-L245

async def on_lifespan(self, scope: Scope, _: Receive, __: Send) -> bool | None:
app_routes = get_app_routes(scope["app"])
set_cache_age_in_openapi_schema(scope["app"])
self._routes_info = self._extract_routes_info(app_routes)
return None
async def on_http(self, scope: Scope, receive: Receive, send: Send) -> bool | None:
request = Request(scope, receive)
if not self._openapi_initialized:
fastapi_app = scope["app"]
if isinstance(fastapi_app, FastAPI):
set_cache_age_in_openapi_schema(fastapi_app)
self._openapi_initialized = True

Fix in Cursor


Bug: Cache Age Setting and Schema Overwrite Issues

The set_cache_age_in_openapi_schema function has two issues: it incorrectly accesses route dependencies via route.dependant.dependencies instead of route.dependencies, preventing x-cache-age from being set for CacheConfig dependencies in the OpenAPI schema. Additionally, it unconditionally overwrites app.openapi_schema by always calling get_openapi(), which bypasses any custom OpenAPI schema generation logic.

fast_cache_middleware/_helpers.py#L6-L33

def set_cache_age_in_openapi_schema(app: FastAPI) -> None:
openapi_schema = get_openapi(
title=app.title,
version=app.version,
description=app.description,
routes=app.routes,
)
for route in app.routes:
if isinstance(route, routing.APIRoute):
path = route.path
methods = route.methods
for dependency in route.dependant.dependencies:
dep = dependency.call
if isinstance(dep, CacheConfig):
max_age = dep.max_age
for method in methods:
method = method.lower()
try:
operation = openapi_schema["paths"][path][method]
operation.setdefault("x-cache-age", max_age)
except KeyError:
continue
app.openapi_schema = openapi_schema

Fix in Cursor


Was this report helpful? Give feedback by reacting with 👍 or 👎

@Nottezz
Copy link
Copy Markdown
Collaborator Author

Nottezz commented Jun 25, 2025

bugbot run

Comment thread tests/conftest.py
@@ -0,0 +1,141 @@
import time
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Создал conftest, надеюсь не против. А то фикстуры разрастаются, становится тяжко. И свои тесты по схеме запихнул в отдельный модуль.

Comment thread tests/conftest.py
app.openapi_schema = openapi_schema
return app.openapi_schema

app.openapi = custom_openapi # type: ignore
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Мне никак не победить mypy с его ошибкой Mypy: Cannot assign to a method [method-assign].



def set_cache_age_in_openapi_schema(app: FastAPI) -> None:
openapi_schema = app.openapi()
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Добавил тест, который проверяет схему на "добавленные пользователем поля", работаю с функцией из utils, всё перезаписывалось. Переделал что б мы работали чисто со схемой приложения и всё нормально, перезаписей нету.

except KeyError:
continue

app.openapi_schema = openapi_schema
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

а в app.openapi_schema когда метод выполняется ничего нет? может схема уже готова

except KeyError:
continue

app.openapi_schema = openapi_schema
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

бездушная машина тоже говорит ... by always calling get_openapi(), which bypasses any custom OpenAPI schema generation logic

@Nottezz Nottezz merged commit 8a165e3 into main Jun 26, 2025
3 checks passed
@Nottezz Nottezz deleted the feature/add_cache-age-for-openapi branch July 7, 2025 09:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add x-cache-age to the OpenAPI schema

2 participants