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:
@@ -14,11 +14,27 @@ trigger-caddy-vhosts-docker-args-process-deploy() {
|
||||
local proxy_container_https_port proxy_container_https_port_candidate proxy_host_https_port_candidate
|
||||
local STDIN=$(cat)
|
||||
|
||||
if [[ "$PROC_TYPE" != "web" ]]; then
|
||||
if [[ "$(plugn trigger proxy-type "$APP")" != "caddy" ]]; then
|
||||
return
|
||||
fi
|
||||
|
||||
if [[ "$(plugn trigger proxy-type "$APP")" != "caddy" ]]; then
|
||||
if [[ "$PROC_TYPE" != "web" ]]; then
|
||||
# Non-web processes are only labeled when at least one path-based route
|
||||
# targets the process. Otherwise caddy-docker-proxy should ignore the
|
||||
# container entirely.
|
||||
local route_proc
|
||||
local has_route=false
|
||||
while IFS='|' read -r route_proc _ _ _; do
|
||||
if [[ "$route_proc" == "$PROC_TYPE" ]]; then
|
||||
has_route=true
|
||||
break
|
||||
fi
|
||||
done < <(plugn trigger proxy-routes-list "$APP")
|
||||
if [[ "$has_route" != "true" ]]; then
|
||||
echo -n "$STDIN"
|
||||
return
|
||||
fi
|
||||
fn-caddy-route-labels "$APP" "$PROC_TYPE" "$STDIN"
|
||||
return
|
||||
fi
|
||||
|
||||
|
||||
@@ -4,6 +4,70 @@ source "$PLUGIN_CORE_AVAILABLE_PATH/common/property-functions"
|
||||
set -eo pipefail
|
||||
[[ $DOKKU_TRACE ]] && set -x
|
||||
|
||||
fn-caddy-route-labels() {
|
||||
declare desc="emits per-route caddy labels for a non-web container"
|
||||
declare APP="$1" PROC_TYPE="$2" STDIN="$3"
|
||||
local caddy_domains app_domains output route_proc route_port route_path route_strip
|
||||
local matcher_name route_index=0
|
||||
|
||||
app_domains="$(plugn trigger domains-list "$APP")"
|
||||
if [[ -n "$app_domains" ]]; then
|
||||
caddy_domains="$(echo "$app_domains" | xargs)"
|
||||
caddy_domains="${caddy_domains// /, }"
|
||||
fi
|
||||
|
||||
output=""
|
||||
if [[ -n "$caddy_domains" ]]; then
|
||||
# Joining the same site declared by the web container so this container's
|
||||
# handler directives are merged into the existing site block by
|
||||
# caddy-docker-proxy.
|
||||
output="--label 'caddy=${caddy_domains}'"
|
||||
fi
|
||||
|
||||
while IFS='|' read -r route_proc route_port route_path route_strip; do
|
||||
[[ -z "$route_proc" ]] && continue
|
||||
[[ "$route_proc" != "$PROC_TYPE" ]] && continue
|
||||
|
||||
local route_slug
|
||||
route_slug="$(fn-caddy-route-slug "$route_path")"
|
||||
matcher_name="@${route_slug}"
|
||||
# The named matcher accepts both the bare prefix and the prefix-glob form
|
||||
# so requests like /api/v0 and /api/v0/users/42 both match.
|
||||
output="$output --label 'caddy.${matcher_name}.path=${route_path} ${route_path}/*'"
|
||||
output="$output --label 'caddy.${route_index}_route=${matcher_name}'"
|
||||
local sub_index=0
|
||||
if [[ "$route_strip" == "1" ]]; then
|
||||
output="$output --label 'caddy.${route_index}_route.${sub_index}_uri=strip_prefix ${route_path}'"
|
||||
sub_index=$((sub_index + 1))
|
||||
fi
|
||||
output="$output --label \"caddy.${route_index}_route.${sub_index}_reverse_proxy={{upstreams ${route_port}}}\""
|
||||
route_index=$((route_index + 1))
|
||||
done < <(plugn trigger proxy-routes-list "$APP")
|
||||
|
||||
local proxy_labels_file_path=$(fn-proxy-get-labels-file-path "caddy" "$APP")
|
||||
if [[ -f "$proxy_labels_file_path" ]]; then
|
||||
while read -r line; do
|
||||
[[ -z "$line" ]] && continue
|
||||
output="$output --label '$line'"
|
||||
done <"$proxy_labels_file_path"
|
||||
fi
|
||||
|
||||
echo -n "$STDIN $output"
|
||||
}
|
||||
|
||||
fn-caddy-route-slug() {
|
||||
declare desc="returns a deterministic kebab-case slug for a route path"
|
||||
declare ROUTE_PATH="$1"
|
||||
local s="${ROUTE_PATH#/}"
|
||||
s="${s%/}"
|
||||
s="${s//\//-}"
|
||||
s="${s,,}"
|
||||
if [[ -z "$s" ]]; then
|
||||
s="root"
|
||||
fi
|
||||
echo "$s"
|
||||
}
|
||||
|
||||
fn-caddy-logs() {
|
||||
declare desc="shows the logs for the caddy container"
|
||||
declare TAIL="$1" NUM="$2"
|
||||
|
||||
18
plugins/caddy-vhosts/proxy-supports-routes
Executable file
18
plugins/caddy-vhosts/proxy-supports-routes
Executable file
@@ -0,0 +1,18 @@
|
||||
#!/usr/bin/env bash
|
||||
set -eo pipefail
|
||||
[[ $DOKKU_TRACE ]] && set -x
|
||||
source "$PLUGIN_CORE_AVAILABLE_PATH/common/functions"
|
||||
|
||||
trigger-caddy-vhosts-proxy-supports-routes() {
|
||||
declare desc="advertises path-based routing support for caddy"
|
||||
declare trigger="proxy-supports-routes"
|
||||
declare APP="$1"
|
||||
|
||||
if [[ "$(plugn trigger proxy-type "$APP")" != "caddy" ]]; then
|
||||
return
|
||||
fi
|
||||
|
||||
echo "true"
|
||||
}
|
||||
|
||||
trigger-caddy-vhosts-proxy-supports-routes "$@"
|
||||
Reference in New Issue
Block a user