proxy: fix double-prefix when outer proxy mounts a tool at the same name

The 0.1.24 nesting blindly appended the bundled sub-app name to the incoming
X-Forwarded-Prefix, which double-counted it when the outer proxy mounts the app
under the SAME name and proxies to our /<app>/ path (topology B): outer sends
"/township" -> container emitted "/township/township", so every township
fetch() 404'd ("Not found" -> JSON parse error in the UI).

Per-app maps now only append our name when the incoming prefix doesn't already
end in it, so both topologies work: outer-wraps-everything ("/ai" -> "/ai/town
ship") and outer-mounts-same-name ("/township" -> "/township"). Direct (no outer
proxy) still yields "/township".
Co-Authored-By: 's avatarClaude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RdMufYvtTbtGDWsiZVoXce
parent f177d01d
......@@ -16,7 +16,7 @@
# Canonical product version for CoderAI — single source of truth. Both the API
# metadata and the admin web UI read from here.
__version__ = "0.1.24"
__version__ = "0.1.25"
# Configure the CUDA caching allocator BEFORE torch is imported anywhere.
# expandable_segments lets the allocator return freed pages to the driver even
......
......@@ -58,13 +58,35 @@ http {
default $host;
"~." $http_x_forwarded_host;
}
# Incoming sub-path prefix from the outer proxy (trailing slash stripped),
# so we can NEST our own mount prefixes under it (e.g. outer "/ai" + our
# "/township" -> "/ai/township"). Empty when there is no outer prefix.
# Incoming sub-path prefix from the outer proxy (trailing slash stripped).
# Empty when there is no outer prefix.
map $http_x_forwarded_prefix $fwd_prefix {
"~^(?<p>.*?)/?$" $p;
}
# Per-app public prefix. Two valid outer-proxy topologies must both work:
# (A) outer wraps the WHOLE container under one prefix and proxies to our
# root: outer sends e.g. "/ai" -> the app's public prefix is
# "/ai/<app>", so we APPEND.
# (B) outer mounts the app at the SAME name and proxies to our "/<app>/"
# path: outer sends e.g. "/township" (or "/ai/township") that ALREADY
# ends in our app name -> use it AS-IS, never append (appending would
# emit "/township/township" and every fetch() would 404).
# Rule: if the incoming prefix already ends in "/<app>", pass it through;
# otherwise append. Empty incoming -> just "/<app>" (direct, no outer proxy).
map $fwd_prefix $xfp_editor {
"~/editor$" $fwd_prefix;
default $fwd_prefix/editor;
}
map $fwd_prefix $xfp_videogen {
"~/videogen$" $fwd_prefix;
default $fwd_prefix/videogen;
}
map $fwd_prefix $xfp_township {
"~/township$" $fwd_prefix;
default $fwd_prefix/township;
}
# Shared proxy headers. CoderAI builds public URLs from these
# (codai/api/urlutils.py); the tools honour X-Forwarded-Prefix for sub-paths.
proxy_http_version 1.1;
......@@ -73,9 +95,9 @@ http {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $fwd_proto;
proxy_set_header X-Forwarded-Host $fwd_host;
# Pass the outer prefix through unchanged at the root; sub-apps override this
# with their own nested value below.
proxy_set_header X-Forwarded-Prefix $http_x_forwarded_prefix;
# Pass the outer prefix through unchanged at the root (trailing slash
# stripped); sub-apps override this with their own value below.
proxy_set_header X-Forwarded-Prefix $fwd_prefix;
upstream coderai { server 127.0.0.1:18776; }
upstream editor { server 127.0.0.1:8420; }
......@@ -90,7 +112,7 @@ http {
# --- Video editor: https://host:8776/editor/ -------------------------
location /editor/ {
proxy_pass http://editor/; # trailing slash strips the prefix
proxy_set_header X-Forwarded-Prefix "${fwd_prefix}/editor"; # nest under outer prefix
proxy_set_header X-Forwarded-Prefix $xfp_editor; # smart nest (see map above)
proxy_request_buffering off; # stream large uploads through
proxy_buffering off; # SSE progress
}
......@@ -98,7 +120,7 @@ http {
# --- Videogen studio: https://host:8776/videogen/ -------------------
location /videogen/ {
proxy_pass http://videogen/;
proxy_set_header X-Forwarded-Prefix "${fwd_prefix}/videogen"; # nest under outer prefix
proxy_set_header X-Forwarded-Prefix $xfp_videogen; # smart nest (see map above)
proxy_request_buffering off;
proxy_buffering off;
}
......@@ -106,7 +128,7 @@ http {
# --- Township fighters: https://host:8776/township/ ----------------
location /township/ {
proxy_pass http://township/;
proxy_set_header X-Forwarded-Prefix "${fwd_prefix}/township"; # nest under outer prefix
proxy_set_header X-Forwarded-Prefix $xfp_township; # smart nest (see map above)
proxy_request_buffering off;
proxy_buffering off;
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment