Overview

Delegated routes inherit matchers from the parent route table. This way, you can route to specific subpaths that share a common element. Review the following examples of how matcher inheritance works.

Multiple matchers in the same table

Multiple matchers can lead to many matching routes, as shown in the following example.

Say that you have two matchers in a parent route table for the www.example.com host domain: /product-1 and /product-2.

The delegated child route table also has two matchers: /foo and /bar. The /foo matcher routes requests to the app-1 virtual destination. The /bar matcher routes requests to the app-2 virtual destination.

The resulting child routes inherit the parent matchers and can match on the following paths:

  • www.example.com/product-1/foo served by app-1
  • www.example.com/product-2/foo served by app-1
  • www.example.com/product-1/bar served by app-2
  • www.example.com/product-2/bar served by app-2

Example YAML configuration files

  # Example of matcher inheritance
# Parent table with two matchers
apiVersion: networking.gloo.solo.io/v2
kind: RouteTable
metadata:
  name: parent
  namespace: source-apps
spec:
  hosts:
    - www.example.com
  virtualGateways:
    - name: istio-ingressgateway
      namespace: gloo-mesh-gateways
  http:
    - name: product-1
      # Match requests along the path `www.example.com/product-1`
      matchers:
      - uri:
          prefix: /product-1
      # Delegate requests that match this path to child-a
      delegate:
        routeTables:
        - labels:
            table: child-a 
    - name: product-1
      # Match requests along the path `www.example.com/product-2`
      matchers:
      - uri:
          prefix: /product-2
      # Delegate requests that match this path to child-a
      delegate:
        routeTables:
        - labels:
            table: child-a 
---
# Child A route table
apiVersion: networking.gloo.solo.io/v2
kind: RouteTable
metadata:
  name: child-a
  namespace: target-apps
  labels:
    # Matches label in parent route table to for delegation
    table: child-a
spec:
  http:
  # Table routes matching requests to app-1
  - name: product-1
    matchers:
    - uri:
        prefix: /foo
        ignoreCase: true
    forwardTo:
      destinations:
      - ref:
          name: app-1
          namespace: target-apps
        port:
          number: 8080
        kind: VIRTUAL_DESTINATION
  # Table routes matching requests to app-2
  - name: product-1
    matchers:
    - uri:
        prefix: /bar
        ignoreCase: true
    forwardTo:
      destinations:
      - ref:
          name: app-2
          namespace: target-apps
        port:
          number: 8080
        kind: VIRTUAL_DESTINATION
  

Separate child tables without matchers

As you saw in the previous example, multiple matchers can lead to many matching routes. These resulting routes might not be what you intended.

Say that you wanted only two matching routes, /product-1 served by the app-1 virtual destination and /product-2 served by the app-2 virtual destination.

With matcher inheritance, you can configure your parent and child route tables to achieve this scenario. In the parent route table, specify the full matchers for the resulting routes that you want in the parent route table. Each matcher delegates to a seperate child route table. In the child route tables, do not add more matchers. Instead, the child route tables inherit the matchers from the parent. The child route tables specify the apps to route to.

The resulting child routes inherit the parent matchers and can match on the following paths:

  • www.example.com/product-1 served by app-1
  • www.example.com/product-2 served by app-2

Example YAML configuration files

  # Example of matcher inheritance
# Parent table with two matchers
apiVersion: networking.gloo.solo.io/v2
kind: RouteTable
metadata:
  name: parent
  namespace: source-apps
spec:
  hosts:
    - www.example.com
  virtualGateways:
    - name: istio-ingressgateway
      namespace: gloo-mesh-gateways
  http:
    - name: product-1
      # Match requests along the path `www.example.com/product-1`
      matchers:
      - uri:
          prefix: /product-1
          ignoreCase: true
      # Delegate requests that match this path to child-a
      delegate:
        routeTables:
        - labels:
            table: child-a 
    - name: product-1
      # Match requests along the path `www.example.com/product-2`
      matchers:
      - uri:
          prefix: /product-2
          ignoreCase: true
      # Delegate requests that match this path to child-b
      delegate:
        routeTables:
        - labels:
            table: child-b
---
# Child A route table
apiVersion: networking.gloo.solo.io/v2
kind: RouteTable
metadata:
  name: child-a
  namespace: target-apps
  labels:
    # Matches label in parent route table to for delegation
    table: child-a
spec:
  http:
  # Table routes matching requests to app-1
  - name: product-1
    forwardTo:
      destinations:
      - ref:
          name: app-1
          namespace: target-apps
        port:
          number: 8080
        kind: VIRTUAL_DESTINATION
---
# Child B route table
apiVersion: networking.gloo.solo.io/v2
kind: RouteTable
metadata:
  name: child-b
  namespace: target-apps
  labels:
    # Matches label in parent route table to for delegation
    table: child-b
spec:
  http:
  # Table routes matching requests to app-2
  - name: product-2
    forwardTo:
      destinations:
      - ref:
          name: app-2
          namespace: target-apps
        port:
          number: 8080
        kind: VIRTUAL_DESTINATION
  

More matcher inheritance rules

Matcher inheritance rules vary depending on the type of matcher that a delegated route inherits. Review the inheritance rules for the following use cases:

Header Matchers

Child routes inherit header matchers from the parent route. The child route can also set its own header matchers, which are merged with the parent’s header matchers. However, if a child route matches on the same header as the parent, the route is invalid until the conflict is resolved.

Parent example

The following parent route table matches traffic on the one.solo.io host with the X-delegated=true header, and delegates requests to child route tables with the table=child label.

  apiVersion: networking.gloo.solo.io/v2
kind: RouteTable
metadata:
  name: parent-rt
  namespace: global
spec:
  hosts:
    - 'one.solo.io'
  virtualGateways:
    - name: istio-ingressgateway
      namespace: bookinfo
      cluster: ${CLUSTER_NAME}
  http:
  - matchers:
    - headers:
      - name: X-delegated
        value: true
    delegate:
      routeTables:
      - labels:
          table: child
  
Child with more header matchers example

The following child route table has a matcher for the X-child header. It inherits the X-delegated header matcher from the parent. As such, it matches traffic with the the X-child=true and X-delegate=true headers.

  apiVersion: networking.gloo.solo.io/v2
kind: RouteTable
metadata:
  name: child-rt1
  namespace: global
  labels:
    table: child
spec:
  http:
  - matchers:
    - headers:
      - name: X-child
        value: true
    forwardTo:
      destinations:
      - ref:
          name: myapp
          namespace: global
          cluster: ${CLUSTER_NAME}
        port:
          number: 8090
        kind: SERVICE
  
Child conflict example

The following child route table also has a matcher for the X-delegated header. As such, the route is invalid and does not work until you resolve the conflict.

  apiVersion: networking.gloo.solo.io/v2
kind: RouteTable
metadata:
  name: child-rt2
  namespace: global
  labels:
    table: child
spec:
  http:
  - matchers:
    - headers:
      - name: X-delegated
        value: sometimes
    forwardTo:
      destinations:
      - ref:
          name: myapp
          namespace: global
          cluster: ${CLUSTER_NAME}
        port:
          number: 8090
        kind: SERVICE
  

Inverted header matchers

Child routes inherit inverted header matchers (invertMatch=true) from the parent route. The child route can also set its own inverted header matchers, which are merged with the parent’s header matchers. However, if a child route matches on the same inverted header as the parent, the route is invalid until the conflict is resolved.

Parent example

The following parent route table matches traffic on the one.solo.io host with an inverted header matcher for the X-version header. This inverted matcher means that traffic can only match without the X-version=v1 header. For example, traffic with X-version=v1 is not forwarded. However, traffic with X-version=v2 and so on is matched and delegated to child route tables with the table=child label.

  apiVersion: networking.gloo.solo.io/v2
kind: RouteTable
metadata:
  name: parent-rt
  namespace: global
spec:
  hosts:
    - 'one.solo.io'
  virtualGateways:
    - name: istio-ingressgateway
      namespace: bookinfo
      cluster: ${CLUSTER_NAME}
  http:
  - matchers:
    - headers:
      - name: X-version
        value: v1
        invertMatch: true
    delegate:
      routeTables:
      - labels:
          table: child
  
Child with more inverted matchers example

The following child route table has an inverted matcher for the X-env=prod header. It inherits the X-version=v1 inverted header matcher from the parent. As such, it does not match traffic with the the X-version=v1 or X-env=prod headers.

  apiVersion: networking.gloo.solo.io/v2
kind: RouteTable
metadata:
  name: child-rt1
  namespace: global
  labels:
    table: child
spec:
  http:
  - matchers:
    - headers:
      - name: X-env
        value: prod
        invertMatch: true
    forwardTo:
      destinations:
      - ref:
          name: myapp
          namespace: global
          cluster: ${CLUSTER_NAME}
        port:
          number: 8090
        kind: SERVICE
  
Child conflict example

The following child route table also has an inverted matcher for the X-version header, this time with v2. Note that the values are not merged together to block matches on both X-version=v1 and X-version=v2 headers. Instead, the route is invalid and does not work until you resolve the conflict.

  apiVersion: networking.gloo.solo.io/v2
kind: RouteTable
metadata:
  name: child-rt2
  namespace: global
  labels:
    table: child
spec:
  http:
  - matchers:
    - headers:
      - name: X-version
        value: v2
        invertMatch: true
    forwardTo:
      destinations:
      - ref:
          name: myapp
          namespace: global
          cluster: ${CLUSTER_NAME}
        port:
          number: 8090
        kind: SERVICE
  

Query parameter matchers

Child routes inherit query parameter matchers from the parent route. The child route can also set its own query parameter matchers, which are merged with the parent’s matchers. However, if a child route matches on the same query parameter as the parent, the route is invalid until the conflict is resolved.

Parent example

The following parent route table matches traffic on the one.solo.io host with the version=v1 query parameter, and delegates requests to child route tables with the table=child label.

  apiVersion: networking.gloo.solo.io/v2
kind: RouteTable
metadata:
  name: parent-rt
  namespace: global
spec:
  hosts:
    - 'one.solo.io'
  virtualGateways:
    - name: istio-ingressgateway
      namespace: bookinfo
      cluster: ${CLUSTER_NAME}
  http:
  - matchers:
    - queryParameters:
      - name: version
        value: v1
    delegate:
      routeTables:
      - labels:
          table: child
  
Child with more query matchers example

The following child route table has a matcher for the env query parameter. It inherits the version matcher from the parent. As such, it matches traffic with the the ?version=v1 and ?env=staging query parameters.

  apiVersion: networking.gloo.solo.io/v2
kind: RouteTable
metadata:
  name: child-rt1
  namespace: global
  labels:
    table: child
spec:
  http:
  - matchers:
    - queryParameters:
      - name: env
        value: staging
    forwardTo:
      destinations:
      - ref:
          name: myapp
          namespace: global
          cluster: ${CLUSTER_NAME}
        port:
          number: 8090
        kind: SERVICE
  
Child conflict example

The following child route table also has a matcher for the version query parameter, this time with v2. Note that the values are not merged together to match requests on both ?version=v1 and ?version=v2 queries. Instead, the route is invalid and does not work until you resolve the conflict.

  apiVersion: networking.gloo.solo.io/v2
kind: RouteTable
metadata:
  name: child-rt2
  namespace: global
  labels:
    table: child
spec:
  http:
  - matchers:
    - queryParameter:
      - name: version
        value: v2
    forwardTo:
      destinations:
      - ref:
          name: myapp
          namespace: global
          cluster: ${CLUSTER_NAME}
        port:
          number: 8090
        kind: SERVICE
  

HTTP method

Child routes inherit HTTP method matchers from the parent route. The child route cannot set a different HTTP method. If the child has a conflicting HTTP method matcher, the route is invalid until the conflict is resolved.

Parent example

The following parent route table matches PATCH methods on the one.solo.io host, and delegates requests to child route tables with the table=child label.

  apiVersion: networking.gloo.solo.io/v2
kind: RouteTable
metadata:
  name: parent-rt
  namespace: global
spec:
  hosts:
    - 'one.solo.io'
  virtualGateways:
    - name: istio-ingressgateway
      namespace: bookinfo
      cluster: ${CLUSTER_NAME}
  http:
  - matchers:
    - method: PATCH
    delegate:
      routeTables:
      - labels:
          table: child
  
Child inheritance example

The following child route table does not set a matcher. Instead, it inherits the PATCH method matcher from the parent route table. Requests with the PATCH method to one.solo.io are resolved to the myapp destination that the child route forwards to.

  apiVersion: networking.gloo.solo.io/v2
kind: RouteTable
metadata:
  name: child-rt1
  namespace: global
  labels:
    table: child
spec:
  http:
    forwardTo:
      destinations:
      - ref:
          name: myapp
          namespace: global
          cluster: ${CLUSTER_NAME}
        port:
          number: 8090
        kind: SERVICE
  
Child conflict example

The following child route table also matches on a method, PUT. Because this method conflicts with the parent method, the route is invalid and does not work until you resolve the conflict.

  apiVersion: networking.gloo.solo.io/v2
kind: RouteTable
metadata:
  name: child-rt2
  namespace: global
  labels:
    table: child
spec:
  http:
  - matchers:
    - method: PUT
    forwardTo:
      destinations:
      - ref:
          name: myapp
          namespace: global
          cluster: ${CLUSTER_NAME}
        port:
          number: 8090
        kind: SERVICE
  

Port matcher

Child routes inherit the HTTP port matcher from the parent route, even if the parent does not have a port matcher. The child route cannot have its own HTTP port matcher. If it does, the child route’s port matcher is ignored.

Parent example

The following parent route table matches the 8090 port on the one.solo.io host, and delegates requests to child route tables with the table=child label.

  apiVersion: networking.gloo.solo.io/v2
kind: RouteTable
metadata:
  name: parent-rt
  namespace: global
spec:
  hosts:
    - 'one.solo.io'
  virtualGateways:
    - name: istio-ingressgateway
      namespace: bookinfo
      cluster: ${CLUSTER_NAME}
  http:
  - matchers:
    - port: 8090
    delegate:
      routeTables:
      - labels:
          table: child
  
Child inheritance example

The following child route table does not set a port matcher. Instead, it inherits the 8090 port matcher from the parent route table. Requests to one.solo.io:8090 are resolved to the myapp destination that the child route forwards to.

  apiVersion: networking.gloo.solo.io/v2
kind: RouteTable
metadata:
  name: child-rt1
  namespace: global
  labels:
    table: child
spec:
  http:
    forwardTo:
      destinations:
      - ref:
          name: myapp
          namespace: global
          cluster: ${CLUSTER_NAME}
        port:
          number: 8090
        kind: SERVICE
  
Child ignored example

The following child route table also matches on a port, 8091. However, port matchers on a child route are ignored. Requests to one.solo.io:8091 are not resolved along this route. Instead, the child route inherits the parent’s port matcher of 8090. Requests to one.solo.io:8090 are resolved to the myapp destination that the child route forwards to.

  apiVersion: networking.gloo.solo.io/v2
kind: RouteTable
metadata:
  name: child-rt2
  namespace: global
  labels:
    table: child
spec:
  http:
  - matchers:
    - port: 8091
    forwardTo:
      destinations:
      - ref:
          name: myapp
          namespace: global
          cluster: ${CLUSTER_NAME}
        port:
          number: 8090
        kind: SERVICE