Skip to content
If you are interested in trying out Gloo Gateway with the Kubernetes Gateway API, check out Solo Enterprise for kgateway. This version adds enterprise functionality on top of the kgateway open source project.

Update request paths and methods

Page as Markdown

Use the :path and :method pseudo headers to change the request path and HTTP method when a request header is present.

In this example, you use an if else function to determine the value of the :path and :method pseudo headers. If the bar request header is provided, you change the path and method. In all other cases, you preserve the value of both pseudo headers.

About pseudo headers

Pseudo headers are special headers that are used in HTTP/2 to provide metadata about the request or response in a structured way. Although they look like traditional HTTP/1.x headers, they come with specific characteristics:

  • Pseudo headers must always start with a colon (:).
  • They must appear before regular headers in the HTTP/2 frame.
  • Pseudo headers contain details about the request or response.

Common pseudo headers include:

  • :method: The HTTP method that is used, such as GET or POST.
  • :scheme: The protocol that is used, such as http or https.
  • :authority: The hostname and port number that the request is sent to.
  • :path: The path of the request.

Before you begin

  1. Follow the Get started guide to install Gloo Gateway, set up a gateway resource, and deploy the httpbin sample app.

  2. Get the external address of the gateway and save it in an environment variable.

    export INGRESS_GW_ADDRESS=$(kubectl get svc -n gloo-system gloo-proxy-http -o jsonpath="{.status.loadBalancer.ingress[0]['hostname','ip']}")
    echo $INGRESS_GW_ADDRESS  
    kubectl port-forward deployment/gloo-proxy-http -n gloo-system 8080:8080

Update request paths and HTTP methods

  1. Create a RouteOption or VirtualHostOption resource with the following transformation rules:

    • :path: If the request header foo equals the value bar, set the request path in the :path pseudo header to /post. In all other cases, set the request path to value of the :path pseudo header and return that value in the :path pseudo header.
    • :method: If the request header foo equals the value bar, set the HTTP method in the :method pseudo header to POST. In all other cases, set the method to the value of the :method pseudo header and return that value in the :method pseudo header.
      kubectl apply -f- <<EOF
      apiVersion: gateway.solo.io/v1
      kind: RouteOption
      metadata:
        name: transformation
        namespace: httpbin
      spec:
        targetRefs:
        - group: gateway.networking.k8s.io
          kind: HTTPRoute
          name: httpbin
        options:
          transformations:
            requestTransformation:
              transformationTemplate:
                headers:
                  # If the foo: bar header is present, update the request path to /post. 
                  # Otherwise, do not update the request path. 
                  # Note that you must use the :path pseudo-header to update the request path.
                  ":path":
                     text: '{% if header("foo") == "bar" %}/post{% else %}{{ header(":path") }}{% endif %}'
                  # If the foo: bar header is present, update the HTTP method to POST. 
                  # Otherwise, do not update the HTTP method. 
                  # Note that you must the :method pseudo-header to update the HTTP method of the request. 
                  ":method":
                     text: '{% if header("foo") == "bar" %}POST{% else %}{{ header(":method") }}{% endif %}'
      EOF
      kubectl apply -n gloo-system -f- <<EOF
      apiVersion: gateway.solo.io/v1
      kind: VirtualHostOption
      metadata:
        name: transformation
        namespace: gloo-system
      spec:
        options:
          transformations:
            requestTransformation:
              transformationTemplate:
                headers:
                  # If the foo: bar header is present, update the request path to /post. 
                  # Otherwise, do not update the request path. 
                  # Note that you must use the :path pseudo-header to update the request path.
                  ":path":
                     text: '{% if header("foo") == "bar" %}/post{% else %}{{ header(":path") }}{% endif %}'
                  # If the foo: bar header is present, update the HTTP method to POST. 
                  # Otherwise, do not update the HTTP method. 
                  # Note that you must the :method pseudo-header to update the HTTP method of the request. 
                  ":method":
                     text: '{% if header("foo") == "bar" %}POST{% else %}{{ header(":method") }}{% endif %}'
        targetRefs:
        - group: gateway.networking.k8s.io
          kind: Gateway
          name: http
          namespace: gloo-system
      EOF
  2. Send a request to the /get endpoint of the httpbin app. Include the foo: bar request header to trigger the request transformation. Verify that you get back a 200 HTTP response code and that your request path is rewritten to the /post endpoint. The /post endpoint accepts requests only if the HTTP POST method is used. The 200 HTTP response code therefore also indicates that the HTTP method was successfully changed from GET to POST.

    curl -vik http://$INGRESS_GW_ADDRESS:8080/get \
     -H "foo: bar" \
     -H "host: www.example.com:8080" 
    curl -vik localhost:8080/get \
    -H "foo: bar" \
    -H "host: www.example.com" \

    Example output:

    < HTTP/1.1 200 OK
    HTTP/1.1 200 OK
    ...  
    {
      "args": {},
      "headers": {
         "Accept": [
           "*/*"
         ],
         "Content-Length": [
         "0"
         ],
         "Foo": [
         "bar"
         ],
         "Host": [
         "www.example.com:8080"
         ],
         "User-Agent": [
         "curl/7.77.0"
         ],
         "X-Forwarded-Proto": [
         "http"
         ],
         "X-Request-Id": [
         "6b7debde-6a8a-4d9e-90a4-33a9a35937d3"
         ]
     },
     "origin": "127.0.0.6:48539",
     "url": "http://www.example.com:8080/post",
     "data": "",
     "files": null,
     "form": null,
     "json": null
    }  

  3. Send another request to the /get endpoint of the httpbin app. This time, you omit the foo: bar header. Verify that you get back a 200 HTTP response code and that the request path is not rewritten to the /post endpoint. The /get endpoint accepts requests only if the HTTP GET method is used. A 200 HTTP response code therefore also verifies that the HTTP method was not changed.

    curl -vik http://$INGRESS_GW_ADDRESS:8080/get \
     -H "host: www.example.com:8080" 
    curl -vik localhost:8080/get \
    -H "host: www.example.com" \

    Example output:

    < HTTP/1.1 200 OK
    HTTP/1.1 200 OK
    ...
    
    {
     "args": {},
     "headers": {
         "Accept": [
         "*/*"
         ],
         "Host": [
         "www.example.com:8080"
         ],
         "User-Agent": [
         "curl/7.77.0"
         ],
         "X-Forwarded-Proto": [
         "http"
         ],
         "X-Request-Id": [
         "b91ecfcf-4f79-4b65-9727-09aafcaeb40e"
         ]
     },
     "origin": "127.0.0.6:46209",
     "url": "http://www.example.com:8080/get"
    }

Cleanup

You can remove the resources that you created in this guide.

kubectl delete virtualhostoption transformation -n gloo-system
kubectl delete routeoption transformation -n httpbin