diff --git a/Docs/Architekture.md b/Docs/Architekture.md index 9ef3286..6614032 100644 --- a/Docs/Architekture.md +++ b/Docs/Architekture.md @@ -768,7 +768,67 @@ APScheduler 4.x (async mode) manages recurring background tasks. --- -## 9.2 Deployment Constraints +## 9.2 nginx Routing Rules + +The reverse proxy (nginx) must route requests correctly to prevent frontend SPA fallback rules from hiding backend 404 errors. The following location blocks ensure proper behavior: + +### Location Block Priority + +nginx uses **longest-prefix matching** to determine which location block handles a request: +1. Exact matches (`location =`) — highest priority +2. Regular expression matches (`location ~`) — second priority +3. Prefix matches (`location /prefix`) — matched in order of specificity (longest first) +4. Catch-all (`location /`) — lowest priority + +### Routing Configuration + +| Location Block | Rule | Purpose | +|---|---|---| +| `location /api/` | `proxy_pass http://backend:8000;` — **no `try_files`** | Proxy all API requests to FastAPI backend. Any unmatched API route (typos, invalid paths) returns 404 from the backend. | +| `location /assets/` | `try_files $uri =404;` | Serve static assets with long-term caching. Return 404 if file doesn't exist. | +| `location /` | `try_files $uri $uri/ /index.html;` | SPA fallback: serve `index.html` for all unmatched routes (client-side routing). | + +### Routing Behavior + +``` +Request → /api/some-endpoint + ↓ + nginx matches location /api/ (longest prefix) + ↓ + proxy_pass → backend:8000 + ↓ + Backend returns 404 if endpoint doesn't exist (✓ correct) + Client sees 404, not SPA HTML + +Request → /some-page + ↓ + nginx matches location / (catch-all) + ↓ + try_files looks for file, then directory, then /index.html + ↓ + Serves /index.html (React Router handles client-side routing) + ↓ + Client sees 200 with HTML (✓ correct for SPA) + +Request → /api/typos + ↓ + nginx matches location /api/ (longest prefix, NOT catch-all) + ↓ + proxy_pass → backend:8000 + ↓ + FastAPI returns 404 (✓ correct, not caught by SPA fallback) +``` + +### Critical Implementation Notes + +- **Never add `try_files` to the `/api/` location block** — this would hide backend 404s. +- **The `/api/` location must come before the `/` catch-all** in the config (this is automatically respected via longest-prefix matching). +- **No inherited `try_files` rules** — the `/api/` location has no global `try_files` that could affect it. +- **Backend 404 responses pass through nginx unchanged** — nginx does not rewrite 404 responses from the backend. + +--- + +## 9.3 Deployment Constraints ### Single-Worker Requirement