From a4d40becd88a070df764932d86fc597edffa3807 Mon Sep 17 00:00:00 2001 From: Jose Diaz-Gonzalez Date: Mon, 1 Jun 2026 14:34:15 -0400 Subject: [PATCH] refactor: drop proxy-supports-routes capability trigger The trigger was added to refuse proxy:route:set under openresty and haproxy, but the hard refusal created an ordering dependency for declarative tools and blocked users from staging routes ahead of a backend switch. Routes are now stored regardless of the active backend and silently ignored by backends that do not render them; the docs call out the inert behavior under openresty and haproxy. --- docs/development/plugin-triggers.md | 21 ------------------- docs/networking/proxy-management.md | 3 ++- plugins/caddy-vhosts/proxy-supports-routes | 18 ---------------- plugins/haproxy-vhosts/proxy-supports-routes | 21 ------------------- plugins/nginx-vhosts/proxy-supports-routes | 18 ---------------- .../openresty-vhosts/proxy-supports-routes | 20 ------------------ plugins/proxy/route_subcommands.go | 9 -------- plugins/proxy/routes.go | 15 ------------- plugins/scheduler-k3s/proxy-supports-routes | 18 ---------------- plugins/traefik-vhosts/proxy-supports-routes | 18 ---------------- tests/unit/proxy-route.bats | 14 ++++++------- 11 files changed, 8 insertions(+), 167 deletions(-) delete mode 100755 plugins/caddy-vhosts/proxy-supports-routes delete mode 100755 plugins/haproxy-vhosts/proxy-supports-routes delete mode 100755 plugins/nginx-vhosts/proxy-supports-routes delete mode 100755 plugins/openresty-vhosts/proxy-supports-routes delete mode 100755 plugins/scheduler-k3s/proxy-supports-routes delete mode 100755 plugins/traefik-vhosts/proxy-supports-routes diff --git a/docs/development/plugin-triggers.md b/docs/development/plugin-triggers.md index 933b05d64..5501b996b 100644 --- a/docs/development/plugin-triggers.md +++ b/docs/development/plugin-triggers.md @@ -2390,27 +2390,6 @@ while IFS='|' read -r proc port path strip; do done < <(plugn trigger proxy-routes-list "$APP") ``` -### `proxy-supports-routes` - -- Description: Returns `true` if the proxy backend currently selected for the app supports path-based routes (`proxy:route:set`), `false` otherwise. Implemented by each in-tree proxy plugin (nginx, traefik, caddy, and k3s return `true`; openresty and haproxy return `false`). The `proxy:route:set` command calls this trigger and refuses with a "not supported" message when the result is `false`. -- Invoked by: `proxy:route:set` in the `proxy` plugin -- Arguments: `$APP` -- Example: - -```shell -#!/usr/bin/env bash - -set -eo pipefail; [[ $DOKKU_TRACE ]] && set -x - -APP="$1" - -if [[ "$(plugn trigger proxy-type "$APP")" != "my-proxy" ]]; then - return -fi - -echo "true" -``` - ### `proxy-type` - Description: Returns the proxy type for an app diff --git a/docs/networking/proxy-management.md b/docs/networking/proxy-management.md index fe919e867..f5bb0a279 100644 --- a/docs/networking/proxy-management.md +++ b/docs/networking/proxy-management.md @@ -196,7 +196,7 @@ See the [port management documentation](/docs/networking/port-management.md) for By default, every HTTP/HTTPS request is routed to the `web` process declared in the app's `Procfile`. Use `proxy:route:*` to route specific path prefixes to a different process within the same app - for example, sending `/api/v0/*` to an `api` process or `/ws` to a `websocket` process. The `web` process always handles every other path as an implicit catch-all. > [!NOTE] -> Path-based routing is supported by the `nginx`, `traefik`, `caddy`, and `k3s` proxy backends. The `openresty` and `haproxy` backends do not currently support it; `proxy:route:set` exits with a "not supported" message under those backends. Support is tracked in [dokku/openresty-docker-proxy#137](https://github.com/dokku/openresty-docker-proxy/issues/137) and the `haproxy-vhosts` sidecar. +> Path-based routing is rendered by the `nginx`, `traefik`, `caddy`, and `k3s` proxy backends. The `openresty` and `haproxy` backends accept and store route declarations, but the routes are inert (no labels are emitted) because the sidecar images do not yet support path-prefix vocabulary. Routes stored ahead of a backend switch will activate automatically once the proxy is changed to a rendering backend. Tracked at [dokku/openresty-docker-proxy#137](https://github.com/dokku/openresty-docker-proxy/issues/137) and the `haproxy-vhosts` sidecar. #### Adding a route @@ -273,6 +273,7 @@ dokku proxy:route:set node-js-app api /api/v0/admin - **nginx**: route changes take effect immediately on the next `proxy-build-config` reload (which `proxy:route:*` invokes automatically). - **traefik** and **caddy**: routes are applied via Docker labels on the target containers. Containers must be recreated for new or removed labels to take effect. The command prints a notice instructing you to run `dokku ps:rebuild ` to recreate containers. - **k3s**: route changes take effect on the next deploy when the chart is re-rendered. +- **openresty** and **haproxy**: routes are stored but inert under these backends. They activate automatically if you switch to a rendering backend (`nginx`, `traefik`, `caddy`, or `k3s`). - **WebSocket** traffic is forwarded transparently on `nginx`, `traefik`, `caddy`, and `k3s` backends - no additional configuration is required. - A route to a process that is scaled to `0` will resolve to no upstream until the process is scaled up (`dokku ps:scale =1`). `proxy:route:set` warns when this is the case. diff --git a/plugins/caddy-vhosts/proxy-supports-routes b/plugins/caddy-vhosts/proxy-supports-routes deleted file mode 100755 index eb096b310..000000000 --- a/plugins/caddy-vhosts/proxy-supports-routes +++ /dev/null @@ -1,18 +0,0 @@ -#!/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 "$@" diff --git a/plugins/haproxy-vhosts/proxy-supports-routes b/plugins/haproxy-vhosts/proxy-supports-routes deleted file mode 100755 index 58aaebae5..000000000 --- a/plugins/haproxy-vhosts/proxy-supports-routes +++ /dev/null @@ -1,21 +0,0 @@ -#!/usr/bin/env bash -set -eo pipefail -[[ $DOKKU_TRACE ]] && set -x -source "$PLUGIN_CORE_AVAILABLE_PATH/common/functions" - -trigger-haproxy-vhosts-proxy-supports-routes() { - declare desc="advertises path-based routing support for haproxy (currently false)" - declare trigger="proxy-supports-routes" - declare APP="$1" - - if [[ "$(plugn trigger proxy-type "$APP")" != "haproxy" ]]; then - return - fi - - # The byjg/easy-haproxy sidecar image only supports host-based routing. - # Path-prefix routing requires either an upstream change to that sidecar - # or a different config-generation strategy. - echo "false" -} - -trigger-haproxy-vhosts-proxy-supports-routes "$@" diff --git a/plugins/nginx-vhosts/proxy-supports-routes b/plugins/nginx-vhosts/proxy-supports-routes deleted file mode 100755 index 25674a8aa..000000000 --- a/plugins/nginx-vhosts/proxy-supports-routes +++ /dev/null @@ -1,18 +0,0 @@ -#!/usr/bin/env bash -set -eo pipefail -[[ $DOKKU_TRACE ]] && set -x -source "$PLUGIN_CORE_AVAILABLE_PATH/common/functions" - -trigger-nginx-vhosts-proxy-supports-routes() { - declare desc="advertises path-based routing support for nginx" - declare trigger="proxy-supports-routes" - declare APP="$1" - - if [[ "$(plugn trigger proxy-type "$APP")" != "nginx" ]]; then - return - fi - - echo "true" -} - -trigger-nginx-vhosts-proxy-supports-routes "$@" diff --git a/plugins/openresty-vhosts/proxy-supports-routes b/plugins/openresty-vhosts/proxy-supports-routes deleted file mode 100755 index 7caefa662..000000000 --- a/plugins/openresty-vhosts/proxy-supports-routes +++ /dev/null @@ -1,20 +0,0 @@ -#!/usr/bin/env bash -set -eo pipefail -[[ $DOKKU_TRACE ]] && set -x -source "$PLUGIN_CORE_AVAILABLE_PATH/common/functions" - -trigger-openresty-vhosts-proxy-supports-routes() { - declare desc="advertises path-based routing support for openresty (currently false)" - declare trigger="proxy-supports-routes" - declare APP="$1" - - if [[ "$(plugn trigger proxy-type "$APP")" != "openresty" ]]; then - return - fi - - # The openresty sidecar image does not yet accept path-prefix routing labels. - # Tracked upstream at dokku/openresty-docker-proxy#137. - echo "false" -} - -trigger-openresty-vhosts-proxy-supports-routes "$@" diff --git a/plugins/proxy/route_subcommands.go b/plugins/proxy/route_subcommands.go index f5e687707..ee98e8c5e 100644 --- a/plugins/proxy/route_subcommands.go +++ b/plugins/proxy/route_subcommands.go @@ -23,15 +23,6 @@ func CommandRouteSet(appName string, processName string, path string, port int, return errors.New("Usage: dokku proxy:route:set [--port ] [--strip-prefix]") } - supported, err := SupportsRoutes(appName) - if err != nil { - return err - } - if !supported { - proxyType := getComputedProxyType(appName) - return fmt.Errorf("path-based routing is not yet supported with the %s proxy backend", proxyType) - } - if port == 0 { port = DefaultRoutePort } diff --git a/plugins/proxy/routes.go b/plugins/proxy/routes.go index b8bc80d7e..571b0f5b4 100644 --- a/plugins/proxy/routes.go +++ b/plugins/proxy/routes.go @@ -171,21 +171,6 @@ func RoutedProcessTypes(appName string) ([]string, error) { return out, nil } -// SupportsRoutes returns true if the proxy backend selected for the app -// supports path-based routing, as declared by the proxy-supports-routes -// trigger. Backends that do not implement the trigger are treated as not -// supporting routes (conservative default). -func SupportsRoutes(appName string) (bool, error) { - result, err := common.CallPlugnTrigger(common.PlugnTriggerInput{ - Trigger: "proxy-supports-routes", - Args: []string{appName}, - }) - if err != nil { - return false, err - } - return result.StdoutContents() == "true", nil -} - // AddRoute upserts a route. Returns whether the stored state changed. func AddRoute(appName string, route Route) (bool, error) { if err := ValidatePath(route.Path); err != nil { diff --git a/plugins/scheduler-k3s/proxy-supports-routes b/plugins/scheduler-k3s/proxy-supports-routes deleted file mode 100755 index e91e8b7f8..000000000 --- a/plugins/scheduler-k3s/proxy-supports-routes +++ /dev/null @@ -1,18 +0,0 @@ -#!/usr/bin/env bash -set -eo pipefail -[[ $DOKKU_TRACE ]] && set -x -source "$PLUGIN_CORE_AVAILABLE_PATH/common/functions" - -trigger-scheduler-k3s-proxy-supports-routes() { - declare desc="advertises path-based routing support for k3s" - declare trigger="proxy-supports-routes" - declare APP="$1" - - if [[ "$(plugn trigger proxy-type "$APP")" != "k3s" ]]; then - return - fi - - echo "true" -} - -trigger-scheduler-k3s-proxy-supports-routes "$@" diff --git a/plugins/traefik-vhosts/proxy-supports-routes b/plugins/traefik-vhosts/proxy-supports-routes deleted file mode 100755 index d9084a5cc..000000000 --- a/plugins/traefik-vhosts/proxy-supports-routes +++ /dev/null @@ -1,18 +0,0 @@ -#!/usr/bin/env bash -set -eo pipefail -[[ $DOKKU_TRACE ]] && set -x -source "$PLUGIN_CORE_AVAILABLE_PATH/common/functions" - -trigger-traefik-vhosts-proxy-supports-routes() { - declare desc="advertises path-based routing support for traefik" - declare trigger="proxy-supports-routes" - declare APP="$1" - - if [[ "$(plugn trigger proxy-type "$APP")" != "traefik" ]]; then - return - fi - - echo "true" -} - -trigger-traefik-vhosts-proxy-supports-routes "$@" diff --git a/tests/unit/proxy-route.bats b/tests/unit/proxy-route.bats index ced904671..0f8c73619 100644 --- a/tests/unit/proxy-route.bats +++ b/tests/unit/proxy-route.bats @@ -218,32 +218,30 @@ teardown() { assert_output "true" } -@test "(proxy:route:set) refuses under openresty backend" { +@test "(proxy:route:set) stores routes under openresty backend even though they are inert" { dokku proxy:set "$TEST_APP" openresty >/dev/null 2>&1 || skip "openresty proxy not available" run /bin/bash -c "dokku proxy:route:set $TEST_APP api /api/v0" echo "output: $output" echo "status: $status" - assert_failure - assert_output_contains "not yet supported" + assert_success run /bin/bash -c "dokku proxy:route:report $TEST_APP" echo "output: $output" echo "status: $status" - assert_output_contains "(none)" + assert_output_contains "/api/v0 -> api:5000" } -@test "(proxy:route:set) refuses under haproxy backend" { +@test "(proxy:route:set) stores routes under haproxy backend even though they are inert" { dokku proxy:set "$TEST_APP" haproxy >/dev/null 2>&1 || skip "haproxy proxy not available" run /bin/bash -c "dokku proxy:route:set $TEST_APP api /api/v0" echo "output: $output" echo "status: $status" - assert_failure - assert_output_contains "not yet supported" + assert_success run /bin/bash -c "dokku proxy:route:report $TEST_APP" echo "output: $output" echo "status: $status" - assert_output_contains "(none)" + assert_output_contains "/api/v0 -> api:5000" }