From dd8ddb64e6134bc46374df9a9b4d2c75304dde92 Mon Sep 17 00:00:00 2001 From: Daniel Volz Date: Wed, 11 Mar 2026 10:03:34 +0100 Subject: [PATCH] feat: expose optional API docs through frontend ingress (#416) --- .env.example | 3 ++- README.md | 8 +++++--- frontend/nginx.conf | 43 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 50 insertions(+), 4 deletions(-) diff --git a/.env.example b/.env.example index f14d90f..ab19a01 100644 --- a/.env.example +++ b/.env.example @@ -31,9 +31,10 @@ LOG_LEVEL=warn # API documentation UI + OpenAPI JSON # Default behavior: enabled outside production, disabled in production +# When enabled, docs are available on /docs and /docs/json. # Recommended: # development/staging: OPENAPI_DOCS_ENABLED=true -# production: OPENAPI_DOCS_ENABLED=false +# production: leave unset, or set OPENAPI_DOCS_ENABLED=false # OPENAPI_DOCS_ENABLED=true # Timezone for scheduled reminders (e.g., Europe/Berlin, America/New_York) diff --git a/README.md b/README.md index 57a4786..42d2acb 100644 --- a/README.md +++ b/README.md @@ -204,12 +204,13 @@ Recommended values for API docs by environment: |-------------|----------------| | Development | `OPENAPI_DOCS_ENABLED=true` | | Staging/Test | `OPENAPI_DOCS_ENABLED=true` | -| Production | `OPENAPI_DOCS_ENABLED=false` (or keep `auto` with `NODE_ENV=production`) | +| Production | leave it unset, or set `OPENAPI_DOCS_ENABLED=false` | Notes: -- `auto` means: docs enabled when `NODE_ENV` is not `production`, disabled when `NODE_ENV=production`. -- Explicitly setting `OPENAPI_DOCS_ENABLED` always overrides `auto` behavior. +- If `OPENAPI_DOCS_ENABLED` is not set, docs are enabled outside production and disabled in production. +- If `OPENAPI_DOCS_ENABLED=true`, docs are available on `/docs` and `/docs/json`. +- If `OPENAPI_DOCS_ENABLED=false`, only the docs are disabled. The API still works normally. ### Authentication @@ -256,6 +257,7 @@ API reference: - Interactive docs: `/docs` - OpenAPI JSON: `/docs/json` +- With the bundled frontend ingress, these paths work on the normal app URL as well, for example `http://localhost:4174/docs` when docs are enabled. - Key management endpoints for authenticated users: - `GET /auth/api-keys` - `POST /auth/api-keys` diff --git a/frontend/nginx.conf b/frontend/nginx.conf index 4d0e9e3..f7c5c8f 100644 --- a/frontend/nginx.conf +++ b/frontend/nginx.conf @@ -23,6 +23,49 @@ server { # Allow larger file uploads (for medication images and data import/export) client_max_body_size 50M; + # ------------------------------------------------------------------------- + # Swagger/OpenAPI docs (optional) + # When backend docs are enabled, expose them through the frontend ingress so + # no separate backend port is required for /docs access. + # + # Important: do not inherit the app-shell CSP here. Swagger UI ships its own + # CSP headers from Fastify and would otherwise be blocked by the stricter + # frontend policy. + # ------------------------------------------------------------------------- + location = /docs { + resolver 127.0.0.11 valid=10s ipv6=off; + set $backend_upstream ${BACKEND_URL}; + + proxy_pass http://$backend_upstream; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_pass_header Set-Cookie; + proxy_cookie_path / /; + + # Defining a location-level header prevents inheritance of the stricter + # frontend app-shell headers while leaving backend Swagger headers intact. + add_header X-Docs-Proxy "1" always; + } + + location ^~ /docs/ { + resolver 127.0.0.11 valid=10s ipv6=off; + set $backend_upstream ${BACKEND_URL}; + + proxy_pass http://$backend_upstream; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_pass_header Set-Cookie; + proxy_cookie_path / /; + + # Defining a location-level header prevents inheritance of the stricter + # frontend app-shell headers while leaving backend Swagger headers intact. + add_header X-Docs-Proxy "1" always; + } + location / { try_files $uri /index.html; }