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.

Change response status

Page as Markdown

Update the response status based on fields that are present in the request body.

In this guide, you learn how to use an if else function to change the HTTP status that is returned in your response. To determine the response status, you use a JSON string that is provided in the request. If the JSON includes an error, you return a 400 HTTP response code. In all other cases, you return the response code of the :status pseudo header.

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

Change the response status

  1. Create a payload that you later send as your request body.

    cat << EOF > data.json
    {
      "error": {
       "message": "This is an error"
      }
    }
    EOF
  2. Create a RouteOption or VirtualHostOption resource with the following transformation rules:

    • Extract the message field from the data.json file that is sent in the request.
    • If the error message is not empty, return a 400 HTTP response code in the :status pseudo header.
    • In all other cases, do not change the :status 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:
            responseTransformation:
              transformationTemplate:
                extractors: 
                  message:
                    body: {}
                    mode: EXTRACT
                    regex: '[\s\S]*(message)[\s\S]*'
                    subgroup: 1
                headers:
                 # We set the response status via the :status pseudo-header based on the response code
                  :status:
                    text: '{% if ( message ) != "" %}400{% else %}{{ header(":status") }}{% 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:
            responseTransformation:
              transformationTemplate:
                parseBodyBehavior: ParseAsJson
                headers:
                 # We set the response status via the :status pseudo-header based on the response code
                  ":status":
                    text: '{% if {{ error }} != "" %}400{% else %}{{ header(":status") }}{% endif %}'
        targetRefs:
        - group: gateway.networking.k8s.io
          kind: Gateway
          name: http
          namespace: gloo-system
      EOF
  3. Send a request to the httpbin app and include data.json file as your payload. Because the error.message field is not empty, a 400 HTTP response code is returned.

    curl -X POST -H "host: www.example.com:8080" -w "%{http_code}" \
     -H "Content-Type: application/json" \
     http://$INGRESS_GW_ADDRESS:8080/post -d @data.json | jq
    curl -vik localhost:8080/get -w "%{http_code}" \
    -H "foo: bar" \
    -H "host: www.example.com" \

    Example output:

    {
      "args": {},
      "headers": {
        "Accept": [
          "*/*"
        ],
         "Content-Length": [
          "49"
        ],
        "Content-Type": [
          "application/json"
        ],
        "Host": [
          "www.example.com:8080"
        ],
        "User-Agent": [
          "curl/8.7.1"
        ],
        "X-Envoy-Expected-Rq-Timeout-Ms": [
          "15000"
        ],
        "X-Forwarded-Proto": [
          "http"
        ],
        "X-Request-Id": [
          "e462eb36-0a36-4ffd-b37d-316737819532"
        ]
      },
      "origin": "10.0.2.124:53583",
      "url": "http://www.example.com:8080/post",
      "data": "{  \"error\": {   \"message\": \"This is an error\"  }}",
      "files": null,
     "form": null,
      "json": {
        "error": {
          "message": "This is an error"
        }
      }
    }
    400

  4. Update your payload file and remove the message so that the error field is empty.

    cat << EOF > data.json
    {
      "error": {
      }
    }
    EOF
  5. Send another request to the httpbin app. Verify that this time a 200 HTTP response code is returned.

    curl -X POST -H "host: www.example.com:8080" -w "%{http_code}" \
     -H "Content-Type: application/json" \
     http://$INGRESS_GW_ADDRESS:8080/post -d @data.json | jq
    curl -vik localhost:8080/get -w "%{http_code}" \
    -H "foo: bar" \
    -H "host: www.example.com" \

    Example output:

    {
      "args": {},
      "headers": {
        "Accept": [
          "*/*"
        ],
         "Content-Length": [
          "49"
        ],
        "Content-Type": [
          "application/json"
        ],
        "Host": [
          "www.example.com:8080"
        ],
        "User-Agent": [
          "curl/8.7.1"
        ],
        "X-Envoy-Expected-Rq-Timeout-Ms": [
          "15000"
        ],
        "X-Forwarded-Proto": [
          "http"
        ],
        "X-Request-Id": [
          "e462eb36-0a36-4ffd-b37d-316737819532"
        ]
      },
      "origin": "10.0.2.124:53583",
      "url": "http://www.example.com:8080/post",
      "data": "{  \"error\": {   \"message\": \"This is an error\"  }}",
      "files": null,
     "form": null,
      "json": {
        "error": {
        }
      }
    }
    200

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