Skip to content

For the complete documentation index, see llms.txt. Markdown versions of all docs pages are available by appending .md to any docs URL.

Page as Markdown

Header and query match

Use header and query matchers in a route delegation setup.

Verified Code examples on this page have been automatically tested and verified.

Use header and query matchers in a route delegation setup.

Configuration overview

In this guide, you add headers and query parameters as matchers on a parent HTTPRoute. Parent matchers control which requests are delegated. Child matchers independently control which delegated requests are routed to a backend. A child can define additional matchers beyond what the parent specifies, or rely solely on path matching.

The following image illustrates the route delegation hierarchy:

parent HTTPRoute:

  • Delegates traffic as follows:
    • /anything/team1 is delegated to child-team1 in namespace team1 for requests that include the header1: val1 request header and the query1=val1 query parameter.
    • /anything/team2 is delegated to child-team2 in namespace team2 for requests that include the header2: val2 request header and the query2=val2 query parameter.

child-team1 HTTPRoute:

  • Matches incoming traffic for the /anything/team1/foo prefix path when the request includes the header1: val1 and headerX: valX headers and the query1=val1 and queryX=valX query parameters. Matching requests are forwarded to the httpbin app in the team1 namespace. The child defines additional header and query parameter matchers beyond what the parent specifies.

child-team2 HTTPRoute:

  • Matches incoming traffic for the /anything/team2/bar exact path and routes that traffic to the httpbin app in the team2 namespace. Unlike child-team1, this child does not define any header or query parameter matchers. It relies solely on path matching, while the parent’s matchers control which requests are delegated.

Before you begin

  1. Follow the Get started guide to install agentgateway.

  2. Follow the Sample app guide to create the agentgateway-proxy Gateway with an HTTP listener.

  3. Get the external address of the agentgateway proxy and save it in an environment variable.

    export INGRESS_GW_ADDRESS=$(kubectl get svc -n agentgateway-system agentgateway-proxy -o jsonpath="{.status.loadBalancer.ingress[0]['hostname','ip']}")
    echo $INGRESS_GW_ADDRESS

  4. Create the namespaces for team1 and team2.

    kubectl create namespace team1
    kubectl create namespace team2
  5. Deploy the httpbin app into both namespaces. The httpbin app exposes endpoints such as /anything/..., /headers, and /delay/N that are useful for verifying routing and policy behavior.

    curl -sL https://raw.githubusercontent.com/kgateway-dev/kgateway/main/examples/httpbin.yaml \
      | awk 'BEGIN{skip=0} /^kind: Namespace$/{skip=1} skip==0{print} /^---$/{skip=0}' \
      | sed 's/namespace: httpbin/namespace: team1/g' \
      | kubectl apply -f -
    
    curl -sL https://raw.githubusercontent.com/kgateway-dev/kgateway/main/examples/httpbin.yaml \
      | awk 'BEGIN{skip=0} /^kind: Namespace$/{skip=1} skip==0{print} /^---$/{skip=0}' \
      | sed 's/namespace: httpbin/namespace: team2/g' \
      | kubectl apply -f -
  6. Verify that the httpbin apps are up and running.

    kubectl get pods -n team1
    kubectl get pods -n team2

    Example output:

    NAME                       READY   STATUS    RESTARTS   AGE
    httpbin-6bc5b79755-xlvjf   3/3     Running   0          7s
    NAME                       READY   STATUS    RESTARTS   AGE
    httpbin-6bc5b79755-twxq9   3/3     Running   0          6s

Setup

  1. Create the parent HTTPRoute that matches incoming traffic on the delegation.example domain. The HTTPRoute specifies two routes:

    • Route 1 matches on the following conditions. If they are met, the routing decision is delegated to a child HTTPRoute in the team1 namespace.
      • path prefix match on /anything/team1
      • exact header match on header1=val1
      • exact query parameter match on query1=val1
    • Route 2 matches on the following conditions. If they are met, the routing decision is delegated to a child HTTPRoute in the team2 namespace.
      • path prefix match on /anything/team2
      • exact header match on header2=val2
      • exact query parameter match on query2=val2
    kubectl apply -f- <<EOF
    apiVersion: gateway.networking.k8s.io/v1
    kind: HTTPRoute
    metadata:
      name: parent
      namespace: agentgateway-system
    spec:
      hostnames:
      - delegation.example
      parentRefs:
      - name: agentgateway-proxy
      rules:
      - matches:
        - path:
            type: PathPrefix
            value: /anything/team1
          headers:
          - type: Exact
            name: header1
            value: val1
          queryParams:
          - type: Exact
            name: query1
            value: val1
        backendRefs:
        - group: gateway.networking.k8s.io
          kind: HTTPRoute
          name: child-team1
          namespace: team1
      - matches:
        - path:
            type: PathPrefix
            value: /anything/team2
          headers:
          - type: Exact
            name: header2
            value: val2
          queryParams:
          - type: Exact
            name: query2
            value: val2
        backendRefs:
        - group: gateway.networking.k8s.io
          kind: HTTPRoute
          name: child-team2
          namespace: team2
    EOF
  2. Create the child-team1 HTTPRoute in the team1 namespace that matches traffic on the /anything/team1/foo path prefix when the header1: val1 and headerX: valX request headers and the query1=val1 and queryX=valX query parameters are present. Requests that meet these conditions are forwarded to the httpbin app.

    kubectl apply -f- <<EOF
    apiVersion: gateway.networking.k8s.io/v1
    kind: HTTPRoute
    metadata:
      name: child-team1
      namespace: team1
    spec:
      rules:
      - matches:
        - path:
            type: PathPrefix
            value: /anything/team1/foo
          headers:
          - type: Exact
            name: header1
            value: val1
          - type: Exact
            name: headerX
            value: valX
          queryParams:
          - type: Exact
            name: query1
            value: val1
          - type: Exact
            name: queryX
            value: valX
        backendRefs:
        - name: httpbin
          port: 8000
    EOF
  3. Create the child-team2 HTTPRoute in the team2 namespace that matches traffic on the /anything/team2/bar exact path. Unlike child-team1, this child does not define any header or query parameter matchers. The parent’s matchers still control which requests are delegated to the team2 namespace.

    kubectl apply -f- <<EOF
    apiVersion: gateway.networking.k8s.io/v1
    kind: HTTPRoute
    metadata:
      name: child-team2
      namespace: team2
    spec:
      rules:
      - matches:
        - path:
            type: Exact
            value: /anything/team2/bar
        backendRefs:
        - name: httpbin
          port: 8000
    EOF
  4. Send a request to the delegation.example domain along the /anything/team1/foo path with the header1: val1 request header and the query1=val1 query parameter. Verify that you get a 404 HTTP response. Although you included the header and query parameter that are defined on the parent, the headers and query parameters that the child also matches on (headerX and queryX) are missing.

    curl -i "http://$INGRESS_GW_ADDRESS:8080/anything/team1/foo?query1=val1" \
      -H "host: delegation.example" -H "header1: val1"

    Example output:

    HTTP/1.1 404 Not Found
    content-type: text/plain
    server: agentgateway
  5. Send another request along the /anything/team1/foo path. This time, include all of the headers and query parameters that the parent and child define. Verify that you get a 200 HTTP response.

    curl -i "http://$INGRESS_GW_ADDRESS:8080/anything/team1/foo?query1=val1&queryX=valX" \
      -H "host: delegation.example" -H "header1: val1" -H "headerX: valX"

    Example output:

    HTTP/1.1 200 OK
    access-control-allow-credentials: true
    access-control-allow-origin: *
    content-type: application/json; encoding=utf-8
    server: agentgateway
  6. Send a request along the /anything/team2/bar path with the parent’s matchers (header2 and query2). Verify that you get a 200 HTTP response. The parent’s rule delegates the request to the team2 namespace, and child-team2 matches on path alone with no additional header or query parameter requirements.

    curl -i "http://$INGRESS_GW_ADDRESS:8080/anything/team2/bar?query2=val2" \
      -H "host: delegation.example" -H "header2: val2"

    Example output:

    HTTP/1.1 200 OK
    access-control-allow-credentials: true
    access-control-allow-origin: *
    content-type: application/json; encoding=utf-8
    server: agentgateway
  7. Send another request along the /anything/team2/bar path, but without the parent’s matchers. Verify that you get a 404 HTTP response. Even though child-team2 matches on path alone, the parent requires header2: val2 and query2=val2 to delegate the request to the team2 namespace.

    curl -i http://$INGRESS_GW_ADDRESS:8080/anything/team2/bar \
      -H "host: delegation.example"

    Example output:

    HTTP/1.1 404 Not Found
    content-type: text/plain
    server: agentgateway

Cleanup

You can remove the resources that you created in this guide.
kubectl delete httproute parent -n agentgateway-system
kubectl delete httproute child-team1 -n team1
kubectl delete httproute child-team2 -n team2
kubectl delete namespaces team1 team2
Was this page helpful?
Agentgateway assistant

Ask me anything about agentgateway configuration, features, or usage.

Note: AI-generated content might contain errors; please verify and test all returned information.

Tip: one topic per conversation gives the best results. Use the + button in the chat header to start a new conversation.

Switching topics? Starting a new conversation improves accuracy.
↑↓ navigate select esc dismiss

What could be improved?

Your feedback helps us improve assistant answers and identify docs gaps we should fix.

Need more help? Join us on Discord: https://discord.gg/y9efgEmppm

Want to use your own agent? Add the Solo MCP server to query our docs directly. Get started here: https://search.solo.io/.