feat: route paths to non-web processes via proxy:route

Adds proxy:route:set/remove/clear/report so users can declare path-prefix routes to non-web Procfile processes without hand-writing nginx.conf.sigil. Routes are stored on the proxy plugin as a PropertyMap of path to process:port:strip, with set semantics so each invocation produces a fully-determined state and re-application is idempotent. A proxy-supports-routes capability trigger gates the command per backend - nginx-vhosts, traefik-vhosts, caddy-vhosts, and scheduler-k3s render routes today; openresty-vhosts and haproxy-vhosts refuse until their sidecar images learn a path-prefix vocabulary (tracked in dokku/openresty-docker-proxy#137 and the haproxy sidecar). Closes #8725.
This commit is contained in:
Jose Diaz-Gonzalez
2026-06-01 13:48:17 -04:00
parent 2cd558e102
commit ffd5248cc3
29 changed files with 1539 additions and 7 deletions

View File

@@ -236,6 +236,33 @@ fn-nginx-vhosts-render-template() {
PROXY_PORT_MAP="$(echo "$proxy_port_map" | xargs)" # trailing spaces mess up default template
PROXY_UPSTREAM_PORTS="$(echo "$PROXY_UPSTREAM_PORTS" | xargs)"
# Path-based routes (proxy:route:set). Format the storage representation
# into space-separated sigil variables: PROXY_ROUTES holds the route triples
# (process|port|path|strip), PROXY_ROUTE_LISTENERS holds one
# (process|port|listener-ip,listener-ip,...) entry per unique process+port
# pair so the template can render per-route upstream blocks.
local PROXY_ROUTES="" PROXY_ROUTE_LISTENERS=""
local route_pair_seen=" "
while IFS='|' read -r route_proc route_port route_path route_strip; do
[[ -z "$route_proc" ]] && continue
PROXY_ROUTES="${PROXY_ROUTES} ${route_proc}|${route_port}|${route_path}|${route_strip}"
local route_pair="${route_proc}|${route_port}"
if [[ "$route_pair_seen" != *" ${route_pair} "* ]]; then
route_pair_seen="${route_pair_seen}${route_pair} "
local route_listeners="$(plugn trigger network-get-listeners "$APP" "$route_proc" | xargs)"
if [[ -z "$route_listeners" ]]; then
# No live containers for this process yet; emit a stub so nginx -t
# still passes during pre-validate and the upstream block renders
# without a host-not-found error at reload time.
route_listeners="127.0.0.1:${route_port}"
fi
local route_listener_csv="${route_listeners// /,}"
PROXY_ROUTE_LISTENERS="${PROXY_ROUTE_LISTENERS} ${route_proc}|${route_port}|${route_listener_csv}"
fi
done < <(plugn trigger proxy-routes-list "$APP")
PROXY_ROUTES="$(echo "$PROXY_ROUTES" | xargs)"
PROXY_ROUTE_LISTENERS="$(echo "$PROXY_ROUTE_LISTENERS" | xargs)"
local SSL_INUSE=
local NONSSL_VHOSTS=$(plugn trigger domains-list "$APP")
local NOSSL_SERVER_NAME=$(echo "$NONSSL_VHOSTS" | xargs)
@@ -352,6 +379,7 @@ fn-nginx-vhosts-render-template() {
NGINX_PORT="$PROXY_PORT" NGINX_SSL_PORT="$PROXY_SSL_PORT"
PROXY_PORT="$PROXY_PORT" PROXY_SSL_PORT="$PROXY_SSL_PORT"
PROXY_PORT_MAP="$PROXY_PORT_MAP" PROXY_UPSTREAM_PORTS="$PROXY_UPSTREAM_PORTS"
PROXY_ROUTES="$PROXY_ROUTES" PROXY_ROUTE_LISTENERS="$PROXY_ROUTE_LISTENERS"
PROXY_X_FORWARDED_FOR="$PROXY_X_FORWARDED_FOR"
PROXY_X_FORWARDED_PORT="$PROXY_X_FORWARDED_PORT"
PROXY_X_FORWARDED_PROTO="$PROXY_X_FORWARDED_PROTO"