kubernetes-sigs / gateway-api

Repository for the next iteration of composite service (e.g. Ingress) and load balancing APIs.
https://gateway-api.sigs.k8s.io
Apache License 2.0
1.67k stars 437 forks source link

HttpRoute should be able to match path prefix with case-insensitive option #3123

Open gorban opened 4 weeks ago

gorban commented 4 weeks ago

What would you like to be added:

Support for case-insensitive path prefix matching, e.g. with caseSensitive: false (naming not important to me, that's how it's called in xDS if you're using Envoy).

apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: proxy-from-k8s-to-httpbin
spec:
  rules:
  - backendRefs:
    - ...
    matches:
    - path:
        type: PathPrefix
        value: /httpbin
        caseSensitive: false
    filters:
    - type: URLRewrite
      urlRewrite:
        path:
          type: ReplacePrefixMatch
          replacePrefixMatch: /

Why this is needed:

HttpRoute currently requires regular expressions to achieve case-insensitive path prefix matching.

  1. Existing code may expect URLs to be case-insensitive, since file systems can be case-insensitive. Windows Servers are a good example. Also, case-insensitivity helps users who might enter a URL manually in their address bar.
  2. We would also like to use replacePrefixMatch on a URLRewrite. This is explicitly disallowed for regular expressions, so we really need the case-insensitive support on prefix matches, specifically.
  3. Regular expressions are still a less optimal solution regardless:
    • The specific Gateway implementation may not guarantee reasonable ordering, and there is no flag to denote the priority of a regex match. We have to rely on a specific implementation like Envoy Gateway ordering the regular expression routes sensibly, which is not guaranteed by the Gateway API itself. If they are mis-ordered, a less specific path match could apply first. This is a problem if a more root path has an authentication requirement, but a nested, more specific path is intentionally public (like is common if you have a /prefix/authenticate path that accepts credentials to authenticate in the first place).
    • Regular expressions could be less performant.
  4. Feature parity with other API Gateway technologies (some required fields have be removed for brevity of examples):

    • Istio VirtualService, see ignoreUriCase:
      apiVersion: networking.istio.io/v1alpha3
      kind: VirtualService
      metadata:
      name: proxy-from-k8s-to-httpbin
      spec:
      http:
      - match:
       - uri:
           prefix: /httpbin
         ignoreUriCase: true
       rewrite:
         uri: /
    • Kong Gateway which uses Kubernetes Ingress API (doesn't have case-insensitive, but Kong has explicit regex priority for confidence the more nested, specific route is applied):

      apiVersion: networking.k8s.io/v1
      kind: Ingress
      metadata:
      name: proxy-from-k8s-to-httpbin
      annotations:
       kubernetes.io/ingress.class: kong
       konghq.com/strip-path: \"true\"
       konghq.com/regex-priority: \"1\"
      spec:
      rules:
      - http:
         paths:
         - path: /~/(?i)httpbin
           pathType: ImplementationSpecific
      
      ---
      apiVersion: networking.k8s.io/v1
      kind: Ingress
      metadata:
      name: proxy-from-k8s-to-httpbin-get
      annotations:
       kubernetes.io/ingress.class: kong
       konghq.com/strip-path: \"true\"
       konghq.com/regex-priority: \"2\"
      spec:
      rules:
      - http:
         paths:
         - path: /~/(?i)httpbin/get
           pathType: ImplementationSpecific

From documentation:

ReplacePrefixMatch is only compatible with a PathPrefix HTTPRouteMatch.

robscott commented 3 weeks ago

Thanks for filing this @gorban! If you have time to work on this in the next 2-3 months, do you mind proposing it in our v1.2 release scoping discussion?