From 9ab4b7b3fec5a329d98b6707a3c382ef9b6464c9 Mon Sep 17 00:00:00 2001 From: giles Date: Tue, 24 Feb 2026 18:17:47 +0000 Subject: [PATCH] Prevent circular fragment fetching between apps fetch_fragment() auto-returns "" when called inside a fragment request (detected via X-Fragment-Request header). This prevents deadlocks when e.g. blog fetches cart-mini from cart, and cart's context processor fetches nav-tree from blog. Co-Authored-By: Claude Opus 4.6 --- infrastructure/fragments.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/infrastructure/fragments.py b/infrastructure/fragments.py index 2c287c2..699a539 100644 --- a/infrastructure/fragments.py +++ b/infrastructure/fragments.py @@ -59,6 +59,15 @@ def _internal_url(app_name: str) -> str: # Public API # ------------------------------------------------------------------ +def _is_fragment_request() -> bool: + """True when the current request is itself a fragment fetch.""" + try: + from quart import request as _req + return bool(_req.headers.get(FRAGMENT_HEADER)) + except Exception: + return False + + async def fetch_fragment( app_name: str, fragment_type: str, @@ -72,7 +81,13 @@ async def fetch_fragment( Returns the raw HTML string. When *required* is True (default), raises ``FragmentError`` on network errors or non-200 responses. When *required* is False, returns ``""`` on failure. + + Automatically returns ``""`` when called inside a fragment request + to prevent circular dependencies between apps. """ + if _is_fragment_request(): + return "" + base = _internal_url(app_name) url = f"{base}/internal/fragments/{fragment_type}" try: