old_issues_repo icon indicating copy to clipboard operation
old_issues_repo copied to clipboard

RouteRules with regex against uri don't work, but do work for other headers

Open andrewjjenkins opened this issue 7 years ago • 3 comments

Is this a BUG or FEATURE REQUEST?: Bug

Did you review istio.io/help and existing issues to identify if this is already solved or being worked on?: Y.

This is the closest issue but I don't think it is the same: https://github.com/istio/istio/issues/1375

Bug: Y

What Version of Istio and Kubernetes are you using, where did you get Istio from, Installation details istio 0.4.0, kubernetes 1.9.0

$ istioctl version
Version: 0.4.0
GitRevision: 24089ea97c8d244493c93b499a666ddf4010b547-dirty
GitBranch: 6401744b90b43901b2aa4a8bced33c7bd54ffc13
User: root@cc5c34bbd1ee
GolangVersion: go1.8
$ kubectl version
Client Version: version.Info{Major:"1", Minor:"8", GitVersion:"v1.8.1", GitCommit:"f38e43b221d08850172a9a4ea785a86a3ffa3b3a", GitTreeState:"clean", BuildDate:"2017-10-12T00:45:05Z", GoVersion:"go1.9.1", Compiler:"gc", Platform:"darwin/amd64"}
Server Version: version.Info{Major:"", Minor:"", GitVersion:"v1.9.0", GitCommit:"925c127ec6b946659ad0fd596fa959be43f0cc05", GitTreeState:"clean", BuildDate:"2018-01-26T19:04:38Z", GoVersion:"go1.9.1", Compiler:"gc", Platform:"linux/amd64"}

Is Istio Auth enabled or not ? No Auth. kubectl apply -f istio-0.4.0/install/kubernetes/istio.yaml; kubectl apply -f istio-0.4.0/install/kubernetes/istio-initializer.yaml

What happened: When I define a RouteRule to apply a regex match to a URI, it does not match - I go to the "foo" service.

$ cat rr-uri-regex.yaml
---
apiVersion: config.istio.io/v1alpha1
kind: RouteRule
metadata:
  name: rr-uri-regex
  namespace: my-app
spec:
  destination:
    name: foo
    namespace: my-app
  match:
    request:
      headers:
        uri:
          regex: "^/(?:.*?)/?bar-please(?:/.*)?$"
  route:
  - destination:
      name: bar
      namespace: my-app
---
$ istioctl replace -f rr-uri-regex.yaml
Updated config route-rule/my-app/rr-uri-regex to revision 37386
$ curl http://$ING/i/would/like/bar-please/
...
  "os": {
    "hostname": "foo-76d4b96bdd-r587l"
  }

When I modify that same rule to apply a regex match to another header (x-header-test), it does match:

$ cat rr-xheader-regex.yaml
---
apiVersion: config.istio.io/v1alpha1
kind: RouteRule
metadata:
  name: rr-xheader-regex
  namespace: my-app
spec:
  destination:
    name: foo
    namespace: my-app
  match:
    request:
      headers:
        x-header-test:
          regex: "^/(?:.*?)/?bar-please(?:/.*)?$"
  route:
  - destination:
      name: bar
      namespace: my-app
---
$ istioctl replace -f rr-xheader-regex.yaml
Updated config route-rule/my-app/rr-xheader-regex to revision 36656
$ curl -H 'x-header-test: /i/would/like/bar-please/' http://$ING/
...
  "os": {
    "hostname": "bar-5d458ff878-8ztf8"
  }

The only diff between the two rules is whether the regex is applied to the URI or to another header:

$ diff -u rr-uri-regex.yaml rr-xheader-regex.yaml
--- rr-uri-regex.yaml   2018-02-06 11:04:14.000000000 -0700
+++ rr-xheader-regex.yaml       2018-02-06 10:48:52.000000000 -0700
@@ -2,7 +2,7 @@
 apiVersion: config.istio.io/v1alpha1
 kind: RouteRule
 metadata:
-  name: rr-uri-regex
+  name: rr-xheader-regex
   namespace: my-app
 spec:
   destination:
@@ -11,7 +11,7 @@
   match:
     request:
       headers:
-        uri:
+        x-header-test:
           regex: "^/(?:.*?)/?bar-please(?:/.*)?$"
   route:
   - destination:

(I'll append my deployments and ingresses and such in a comment below to try to reduce noise here)

What you expected to happen: I expect URI to support regex based on this:

  // *Note 2:* _uri_ can be used to perform URL matches. 
  // For all HTTP headers including _uri_, exact, prefix and ECMA style
  // regular expression matches are supported.

(appears in the docs here )

I would expect one of these two things:

  1. Matching on URI works (preferred)
  2. Docs are updated to not say that matching on URI works.

(The docs used to have a caveat that regex did not work for URI but it was removed here ):

  // *Note 2:* _uri_ can be used to perform URL matches. For URL matches
  // (_uri_), only prefix and exact matches are
  // supported. For other HTTP headers, exact, prefix and ECMA style
  // regular expression matches are supported.

How to reproduce it:

kubectl apply -f istio-0.4.0/install/kubernetes/istio.yaml
kubectl apply -f istio-0.4.0/install/kubernetes/istio-initializer.yaml
kubectl apply -f myapp-foo-bar.yaml
istioctl create -f rr-uri-regex.yaml
istioctl create -f rr-xheader-regex.yaml
curl http://$ING/i/would/like/bar-please/   # (goes to foo)
curl -H 'x-header-test: /i/would/like/bar-please/' http://$ING  # (goes to bar)

andrewjjenkins avatar Feb 06 '18 18:02 andrewjjenkins

Here are files that can be used to repro:

myapp-foo-bar.yaml.txt rr-uri-regex.yaml.txt rr-xheader-regex.yaml.txt

andrewjjenkins avatar Feb 06 '18 18:02 andrewjjenkins

I also experienced this. I can't believe there aren't more complaints than this.

mattwilliamson avatar Jan 28 '19 22:01 mattwilliamson

@mattwilliamson HttpMatchRequest lets you specify a uri regex directly, rather than as a header (https://istio.io/docs/reference/config/istio.networking.v1alpha3/#HTTPMatchRequest) does this not do what you want for some reason?

edit for clarity:

you can do this

  match:
    request:
      uri:
        regex: "^/(?:.*?)/?bar-please(?:/.*)?$"

rather than

  match:
    request:
      headers:
        uri:
          regex: "^/(?:.*?)/?bar-please(?:/.*)?$"

ediphy-azorab avatar Jan 29 '19 13:01 ediphy-azorab