From 988c1bbbdda934ee12ed762dcbe526c6f6e26f77 Mon Sep 17 00:00:00 2001 From: Imugiii Date: Fri, 19 Jun 2026 14:11:43 +0000 Subject: [PATCH] fix(borne): passerelle /api same-origin sur le vhost kiosk La borne consommait /api en chemin relatif sur sa propre origine (APP_HOST_KIOSK), ou aucune API n'est routee : le fallback SPA du vhost kiosk renvoyait index.html (HTML) -> data.js plantait sur res.json() -> catalogue vide ("pas cable"). Le middleware CORS livre en #61 n'etait donc jamais sollicite (la borne ne sortait pas vers l'origine API). Fix : le vhost kiosk relaie /api/* au front controller admin via PHP-FPM. ProxyFCGISetEnvIf force SCRIPT_FILENAME sur public/admin/index.php (sinon FPM rejette en "Access denied" : l'extension != .php). REQUEST_URI est preserve, le Router route correctement. data.js inchange (URLs relatives desormais correctes en same-origin). Seul /api est relaye : le back-office (/login, /admin/*) reste hors de l'origine borne. CORS conserve en defense en profondeur (doc conventions section 10). Verifie sur la vraie stack : /api/categories|products|menus|products/{id}| menus/{id} depuis l'origine borne -> 200 application/json ; /login et /admin/dashboard cote borne -> SPA borne (pas le back-office) ; admin direct + home borne sans regression. --- docker/apache/vhost.conf | 25 +++++++++++++++++++++++++ docs/api/conventions.md | 11 ++++++++--- 2 files changed, 33 insertions(+), 3 deletions(-) diff --git a/docker/apache/vhost.conf b/docker/apache/vhost.conf index 141483e..05e18f6 100644 --- a/docker/apache/vhost.conf +++ b/docker/apache/vhost.conf @@ -55,7 +55,10 @@ # SPA-like fallback : toute URL non-fichier -> index.html # (pour permettre de bookmarker un chemin profond dans la borne). + # Exclusion /api/ : ces requetes sont relayees a l'API (cf. + # plus bas) et ne doivent JAMAIS retomber sur index.html. RewriteEngine On + RewriteCond %{REQUEST_URI} !^/api/ RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule ^ index.html [L] @@ -66,6 +69,28 @@ Require all denied + # === API en MEME origine (P4 - passerelle same-origin) === + # La borne consomme l'API publique (/api/*) sur SA PROPRE origine : ce vhost + # relaie ces requetes au front controller admin via PHP-FPM. data.js garde + # donc ses URLs relatives (/api/categories...) -> aucune requete cross-origin + # cote borne -> CORS inutile pour ce parcours (le middleware reste en place + # cote API comme defense en profondeur). SEUL /api est relaye : le back-office + # (/login, /admin/*) n'est PAS joignable depuis l'origine borne. + # + # Le chemin apres host:port dans l'URL fcgi EST le SCRIPT_FILENAME envoye a + # FPM : on le force sur le front controller admin (un .php REEL). Sans ca, FPM + # recevrait un chemin sous le docroot borne sans extension .php et rejetterait + # (security.limit_extensions par defaut = .php -> reponse "Access denied"). + # ProxyPassMatch intercepte des la phase translate -> le faux chemin + # /.../borne/api/... n'est jamais calcule. REQUEST_URI (=/api/categories) et la + # query string sont preserves -> le Router (qui lit REQUEST_URI) route correctement. + ProxyPassMatch "^/api(/.*)?$" "fcgi://wakdo-app:9000/var/www/html/public/admin/index.php" + # mod_proxy_fcgi derive un SCRIPT_FILENAME corrompu (prefixe proxy: + chemin + # original colle apres index.php) -> FPM rejette (extension != .php). On force + # la valeur sur le front controller admin (un .php REEL) ; REQUEST_URI reste + # intact, donc le Router route correctement. + ProxyFCGISetEnvIf "true" SCRIPT_FILENAME "/var/www/html/public/admin/index.php" + # Compression text/html, css, js, json (Cr 1.e.8 temps de chargement). AddOutputFilterByType DEFLATE text/html text/css text/javascript \ diff --git a/docs/api/conventions.md b/docs/api/conventions.md index 395012d..e7c1210 100644 --- a/docs/api/conventions.md +++ b/docs/api/conventions.md @@ -307,9 +307,14 @@ ici. ## 10. CORS -L'API admin sous `/api/*` autorise l'origine du kiosk via `CORS_ALLOWED_ORIGIN` (valeur exacte, -sans joker), configuree dans `docker/apache/vhost.conf`. L'origine doit correspondre a -`APP_URL_KIOSK`. +La borne consomme `/api/*` en **meme origine** : le vhost kiosk (`docker/apache/vhost.conf`) +relaie `/api/*` au front controller admin via PHP-FPM (`ProxyPassMatch` + `ProxyFCGISetEnvIf` +qui force `SCRIPT_FILENAME` sur `public/admin/index.php`). `data.js` garde donc des URLs +relatives et le navigateur n'emet pas de requete cross-origin pour ce parcours. + +Le middleware `App\Core\Cors` reste en place comme defense en profondeur : il lit +`CORS_ALLOWED_ORIGIN` (valeur exacte, sans joker, = `APP_URL_KIOSK`) et autorise un eventuel +consommateur cross-origin de l'API. Il n'est pas sur le chemin de la borne. ---