-
Notifications
You must be signed in to change notification settings - Fork 6
Description
Hi,
I am using version 0.9.0. When configuring a default/catch-all route using PathPrefix: /, it always matches, even when a more specific RegularExpression rule should have matched first.
The Migrating from Ingress guide explicitly recommends this pattern for implementing a default backend:
The Ingress default backend configures a backend that will respond to all unmatched HTTP requests related to that Ingress resource. Gateway API does not have a direct equivalent: it is necessary to define such a routing rule explicitly. For example, define a rule to route requests with the path prefix / to a Service that corresponds to the default backend.
PathPrefix: / is evaluated before RegularExpression rules, so the catch-all backend always serves the request and the regex rule is never reached.
I am unsure if the behavior is strictly defined in Gateway API.
Note this is not about HAProxy's internal default_backend backend_not_found.
Reproduction
The following HTTPRoute:
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: helloworld
labels:
app: helloworld
service: helloworld
spec:
parentRefs:
- name: sample-gateway
hostnames: ["helloworld.sample.com"]
rules:
- matches:
- path:
type: RegularExpression
value: "/[Hh]ell[oO]"
backendRefs:
- name: helloworld
port: 5000
- matches:
- path:
type: PathPrefix
value: /
backendRefs:
- name: custom-error-pages
port: 8080generates this config:
http-request set-var(txn.route,ifnotexists) path,map_beg(/usr/local/hug/maps/hug_http_80/path_prefix.map) # {"hug":"any domain + path prefix"}
http-request set-var(txn.route,ifnotexists) var(txn.base),map_end(/usr/local/hug/maps/hug_http_80/domain_wildcard_path_exact.map) # {"hug":"domain wildcard + exact path"}
http-request set-var(txn.route,ifnotexists) path,map_reg(/usr/local/hug/maps/hug_http_80/path_regex.map) # {"hug":"any domain + path regex"}
http-request set-var(txn.route,ifnotexists) var(txn.base),map_reg(/usr/local/hug/maps/hug_http_80/path_regex.map) # {"hug":"domain wildcard + path prefix or regex, exact domain + path regex"}
with these map files:
==> hug_http_80/domain_wildcard_path_exact.map <==
==> hug_http_80/domain_wildcard_sni.map <==
==> hug_http_80/path_exact.map <==
==> hug_http_80/path_prefix.map <==
helloworld.sample.com/ hug_test-development_custom-error-pages_8080__
==> hug_http_80/path_regex.map <==
^helloworld\.sample\.com/[Hh]ell[oO] hug_test-development_helloworld_5000__
==> hug_http_80/sni.map <==
Because path_prefix.map is evaluated first and ifnotexists short-circuits further evaluation, path_regex.map is never consulted. The custom-error-pages backend always wins.