Filter and merge request body fields

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

Use the filterKeys() and merge() CEL functions together with json() and toJson() to sanitize a JSON request body before it reaches the upstream. filterKeys() removes unwanted fields by testing each key against a predicate. merge() combines two maps, with the second map’s value overwriting any matching keys in the first. toJson() serializes the resulting map back to a JSON string.

Before you begin

  1. Set up an agentgateway proxy.
  2. Install the httpbin sample app.

Filter and merge request body fields

In this example, an incoming request body contains internal metadata fields prefixed with x_ that should not be forwarded to the upstream. After stripping those fields, default values for model and max_tokens are merged in.

For example, a request body of {"messages": [...], "model": "gpt-3.5-turbo", "x_trace_id": "abc", "x_user_session": "xyz"} is forwarded upstream as {"messages": [...], "model": "gpt-4o", "max_tokens": 2048}.

  1. Create an AgentgatewayPolicy resource with your transformation rules.

    kubectl apply -f- <<EOF
    apiVersion: agentgateway.dev/v1alpha1
    kind: AgentgatewayPolicy
    metadata:
      name: transformation
      namespace: httpbin
    spec:
      targetRefs:
      - group: gateway.networking.k8s.io
        kind: HTTPRoute
        name: httpbin
      traffic:
        transformation:
          request:
            body: 'toJson(json(request.body).filterKeys(k, !k.startsWith("x_")).merge({"model": "gpt-4o", "max_tokens": 2048}))'
    EOF

    The expression breaks down as follows:

    • json(request.body): Parses the raw request body string into a map.
    • .filterKeys(k, !k.startsWith("x_")): Keeps only the keys that do not start with x_, stripping internal metadata fields.
    • .merge({"model": "gpt-4o", "max_tokens": 2048}): Merges in the default values, overwriting any existing model value and adding max_tokens.
    • toJson(...): Serializes the resulting map back to a JSON string for the request body.
  2. Send a POST request to the httpbin app with a JSON body that includes internal metadata fields. Verify that you get back a 200 HTTP response code and that the x_ fields are absent from the forwarded body.

    curl -vi http://$INGRESS_GW_ADDRESS:80/post \
     -H "host: www.example.com:80" \
     -H "content-type: application/json" \
     -d '{"messages": [{"role": "user", "content": "hello"}], "model": "gpt-3.5-turbo", "x_trace_id": "abc123", "x_user_session": "xyz789"}'
    curl -vi localhost:8080/post \
    -H "host: www.example.com" \
    -H "content-type: application/json" \
    -d '{"messages": [{"role": "user", "content": "hello"}], "model": "gpt-3.5-turbo", "x_trace_id": "abc123", "x_user_session": "xyz789"}'

    Example output:

    < HTTP/1.1 200 OK
    HTTP/1.1 200 OK
    < content-type: application/json
    content-type: application/json
    ...
    
    {
      "data": "{\"messages\":[{\"role\":\"user\",\"content\":\"hello\"}],\"model\":\"gpt-4o\",\"max_tokens\":2048}",
      ...
    }
    

    The x_trace_id and x_user_session fields are absent. The model value is overwritten to gpt-4o and max_tokens is added.

Cleanup

You can remove the resources that you created in this guide.
kubectl delete AgentgatewayPolicy transformation -n httpbin
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/.