# OpenConcho — nginx site config.
# Serves the React SPA and header-driven same-origin /api proxy to Honcho.
# The browser sends X-Honcho-Upstream per request; nginx forwards server-side (no browser CORS).

server {
    listen       8080;
    listen       [::]:8080;
    server_name  _;
    root         /usr/share/nginx/html;
    index        index.html;

    # Don't leak the nginx version.
    server_tokens off;

    # The resolver (required for per-request DNS with a runtime-variable proxy_pass)
    # is rendered by the entrypoint into conf.d from the container's own DNS, so it
    # works on both user-defined networks (127.0.0.11) and the default bridge.

    # Header-driven same-origin proxy: the browser names the Honcho upstream per
    # request via X-Honcho-Upstream, so the browser never makes a cross-origin call.
    # $allow_upstream is provided by the allowlist map in conf.d (entrypoint-rendered).
    location ^~ /api/ {
        set $upstream $http_x_honcho_upstream;
        if ($upstream = "") {
            add_header X-Honcho-Proxy-Reject "no-upstream" always;
            return 421;
        }
        if ($allow_upstream = 0) {
            add_header X-Honcho-Proxy-Reject "allowlist" always;
            return 403;
        }
        rewrite ^/api/(.*)$ /$1 break;
        proxy_pass               $upstream;
        proxy_ssl_server_name    on;
        proxy_set_header Host    $proxy_host;
        proxy_set_header X-Honcho-Upstream "";
    }

    # Runtime config — regenerated per container start, must never be cached.
    location = /config.js {
        add_header Cache-Control "no-cache, no-store, must-revalidate";
        try_files $uri =404;
    }

    # Long-cache static assets — Vite hashes filenames so they're immutable.
    location ~* \.(?:js|mjs|css|woff2?|ttf|otf|eot|svg|png|jpg|jpeg|gif|ico|webp|avif|wasm)$ {
        expires 1y;
        add_header Cache-Control "public, immutable";
        access_log off;
        try_files $uri =404;
    }

    # Container healthcheck (local; distinct from Honcho's /health).
    location = /healthz {
        access_log off;
        default_type text/plain;
        return 200 "ok\n";
    }

    # SPA fallback: unknown paths return index.html so the router resolves them.
    location / {
        try_files $uri $uri/ /index.html;
        add_header Cache-Control "no-cache, no-store, must-revalidate";
    }

    gzip on;
    gzip_types text/plain text/css application/javascript application/json image/svg+xml;
    gzip_min_length 1024;
}
