From 60ce69e115c94c96bc178f8325e01d2fb527b8f9 Mon Sep 17 00:00:00 2001 From: Beda Schmid Date: Tue, 17 Mar 2026 17:27:22 -0300 Subject: [PATCH] Try a unified api endpoint --- .env.example | 5 ++++- doc/operations-and-configuration.md | 4 ++-- docker-compose.yml | 1 + frontend/nginx.conf | 10 ++++++++++ frontend/src/lib/api.ts | 6 +++--- frontend/vite.config.ts | 8 ++++++++ 6 files changed, 28 insertions(+), 6 deletions(-) diff --git a/.env.example b/.env.example index eb5eadd..5ea52ec 100644 --- a/.env.example +++ b/.env.example @@ -47,8 +47,11 @@ PROVIDER_BASE_URL_ALLOWLIST=[] PUBLIC_BASE_URL=http://localhost:8000 CORS_ORIGINS=["http://localhost:5173","http://localhost:3000"] -# Used at build time for production frontend image, and at runtime in development. +# Leave empty to use same-origin /api/v1 through the frontend proxy. +# Set an absolute URL only when you intentionally want split-origin frontend/API traffic. VITE_API_BASE= +# Development-only Vite proxy target. Docker compose sets this to http://api:8000 automatically. +VITE_API_PROXY_TARGET=http://localhost:8000 # Development-only Vite host allowlist override. VITE_ALLOWED_HOSTS= diff --git a/doc/operations-and-configuration.md b/doc/operations-and-configuration.md index 88ede1b..1858954 100644 --- a/doc/operations-and-configuration.md +++ b/doc/operations-and-configuration.md @@ -87,8 +87,8 @@ Use `.env.example` as baseline. The table below documents user-managed settings | --- | --- | --- | | `APP_ENV` | `development` | `production` | | `HOST_BIND_IP` | `127.0.0.1` or local LAN bind if needed | `127.0.0.1` (publish behind proxy only) | -| `PUBLIC_BASE_URL` | `http://localhost:8000` | `https://api.example.com` | -| `VITE_API_BASE` | empty for host-derived `http://:8000/api/v1`, or explicit local URL | `https://api.example.com/api/v1` (build-time value for production frontend image) | +| `PUBLIC_BASE_URL` | `http://localhost:8000` or same-origin frontend host when proxying API through frontend | `https://app.example.com` when frontend proxies `/api`, or dedicated API origin if you intentionally keep split-origin routing | +| `VITE_API_BASE` | empty to use same-origin `/api/v1` through frontend proxy, or explicit local URL when bypassing proxy | empty or `/api/v1` for same-origin production routing; only use `https://api.example.com/api/v1` when you intentionally keep split-origin frontend/API traffic | | `VITE_ALLOWED_HOSTS` | optional comma-separated hostnames, for example `localhost,docs.lan` | optional comma-separated public frontend hostnames, for example `app.example.com` | | `CORS_ORIGINS` | `["http://localhost:5173","http://localhost:3000"]` | exact frontend origins only, for example `["https://app.example.com"]` | | `REDIS_URL` | `redis://:@redis:6379/0` in isolated local network | `rediss://:@redis.internal:6379/0` | diff --git a/docker-compose.yml b/docker-compose.yml index 2606748..79677a0 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -167,6 +167,7 @@ services: VITE_API_BASE: ${VITE_API_BASE:-} environment: VITE_API_BASE: ${VITE_API_BASE:-} + VITE_API_PROXY_TARGET: ${VITE_API_PROXY_TARGET:-http://api:8000} CORS_ORIGINS: '${CORS_ORIGINS:-["http://localhost:5173","http://localhost:3000"]}' VITE_ALLOWED_HOSTS: ${VITE_ALLOWED_HOSTS:-} # ports: diff --git a/frontend/nginx.conf b/frontend/nginx.conf index ac3d618..ea829e9 100644 --- a/frontend/nginx.conf +++ b/frontend/nginx.conf @@ -2,10 +2,20 @@ server { listen 5173; listen [::]:5173; server_name _; + client_max_body_size 100m; root /usr/share/nginx/html; index index.html; + location /api/ { + proxy_pass http://api:8000; + proxy_http_version 1.1; + proxy_set_header Host $host; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_set_header X-Real-IP $remote_addr; + } + location / { try_files $uri $uri/ /index.html; } diff --git a/frontend/src/lib/api.ts b/frontend/src/lib/api.ts index 082178b..bda5bb7 100644 --- a/frontend/src/lib/api.ts +++ b/frontend/src/lib/api.ts @@ -16,7 +16,7 @@ import type { } from '../types'; /** - * Resolves backend base URL from environment with host-derived HTTP fallback. + * Resolves backend base URL from environment with same-origin proxy fallback. */ function resolveApiBase(): string { const envValue = import.meta.env?.VITE_API_BASE; @@ -27,8 +27,8 @@ function resolveApiBase(): string { } } - if (typeof window !== 'undefined' && window.location?.hostname) { - return `${window.location.protocol}//${window.location.hostname}:8000/api/v1`; + if (typeof window !== 'undefined' && window.location?.origin) { + return '/api/v1'; } return 'http://localhost:8000/api/v1'; } diff --git a/frontend/vite.config.ts b/frontend/vite.config.ts index 7f50d21..0e123f6 100644 --- a/frontend/vite.config.ts +++ b/frontend/vite.config.ts @@ -74,11 +74,19 @@ function buildAllowedHosts(env: Record): string[] | undefined { export default defineConfig(({ mode }) => { const env = loadEnv(mode, process.cwd(), ''); const allowedHosts = buildAllowedHosts(env); + const apiProxyTarget = env.VITE_API_PROXY_TARGET?.trim() || 'http://localhost:8000'; return { server: { host: '0.0.0.0', port: 5173, + proxy: { + '/api': { + target: apiProxyTarget, + changeOrigin: false, + secure: false, + }, + }, ...(allowedHosts ? { allowedHosts } : {}), }, };