From 4490a2ed705573b889e820e9013c3db6e5ee6992 Mon Sep 17 00:00:00 2001 From: bruno Date: Wed, 28 Oct 2026 16:49:45 -0400 Subject: [PATCH] fix(cors): /api/search remplace les en-tetes CORS au lieu de les empiler (defaut 3b) --- app/middleware/recherche_cors.py | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/app/middleware/recherche_cors.py b/app/middleware/recherche_cors.py index 8f99954..2488c73 100644 --- a/app/middleware/recherche_cors.py +++ b/app/middleware/recherche_cors.py @@ -193,7 +193,32 @@ class RechercheCorsMiddleware: if message["type"] == "http.response.start": cors = cors_headers_for(origin, request_host=request_host) if cors is not None: - message["headers"] = list(message.get("headers", [])) + [ + # Remplacer, pas empiler (défaut 3b, 2026-10-28) : + # le CORSMiddleware global de l'application pose + # déjà Access-Control-Allow-Credentials: true sur + # TOUTES les réponses (comportement Starlette avec + # allow_credentials=True, même pour une origine + # hors allowlist et hors /api/search) ; empiler les + # en-têtes de recherche donnait, sur /api/search + # depuis agent-dev, Allow-Credentials en double + # (« true, true » ≠ « true » pour le contrôle CORS + # du navigateur → fetch rejeté → « injoignable + # (CORS ou réseau) ») et, depuis une sœur + # (origine déjà dans la allowlist globale), + # Allow-Origin en double (rejet certain). Les + # hôtes TikTak/Kanbante, sans ce cumul, répondent + # avec des en-têtes uniques — d'où l'échec + # Flowdeck seul. Une origine non autorisée + # traverse sans modification (comportement + # antérieur préservé : le seul en-tête global + # reste, sans Allow-Origin, donc bloqué). + restants = [ + (k, v) for k, v in message.get("headers", []) + if k.decode("latin-1").lower() not in ( + "access-control-allow-origin", + "access-control-allow-credentials", + "vary")] + message["headers"] = restants + [ (k.lower().encode("latin-1"), v.encode("latin-1")) for k, v in cors.items() ]