Added more detailed transformations topics AND added local link checking on PRs#328
Added more detailed transformations topics AND added local link checking on PRs#328kristin-kronstain-brown wants to merge 37 commits intomainfrom
Conversation
Signed-off-by: Kristin Brown <[email protected]>
Deploying agentproxy with
|
| Latest commit: |
893766f
|
| Status: | ✅ Deploy successful! |
| Preview URL: | https://fdc0e034.agentproxy.pages.dev |
| Branch Preview URL: | https://kkb-transformations.agentproxy.pages.dev |
Signed-off-by: Kristin Brown <[email protected]>
Signed-off-by: Kristin Brown <[email protected]>
Signed-off-by: Kristin Brown <[email protected]>
Signed-off-by: Kristin Brown <[email protected]>
Signed-off-by: Kristin Brown <[email protected]>
Signed-off-by: Kristin Brown <[email protected]>
Signed-off-by: Kristin Brown <[email protected]>
Signed-off-by: Kristin Brown <[email protected]>
Signed-off-by: Kristin Brown <[email protected]>
Signed-off-by: Kristin Brown <[email protected]>
Signed-off-by: Kristin Brown <[email protected]>
Signed-off-by: Kristin Brown <[email protected]>
Signed-off-by: Kristin Brown <[email protected]>
Signed-off-by: Kristin Brown <[email protected]>
Signed-off-by: Kristin Brown <[email protected]>
Signed-off-by: Kristin Brown <[email protected]>
Signed-off-by: Kristin Brown <[email protected]>
Signed-off-by: Kristin Brown <[email protected]>
Signed-off-by: Kristin Brown <[email protected]>
Signed-off-by: Kristin Brown <[email protected]>
Signed-off-by: Kristin Brown <[email protected]>
Signed-off-by: Kristin Brown <[email protected]>
Signed-off-by: Kristin Brown <[email protected]>
Signed-off-by: Kristin Brown <[email protected]>
Signed-off-by: Kristin Brown <[email protected]>
Signed-off-by: Kristin Brown <[email protected]>
Signed-off-by: Kristin Brown <[email protected]>
|
|
||
|
|
||
|
|
||
| ## Context variables {#context-variables} |
There was a problem hiding this comment.
add a sentence about what context variables are
| {{% github-table url="https://raw.githubusercontent.com/agentgateway/agentgateway/refs/heads/main/schema/cel.md" section="CEL context Schema" %}} | ||
|
|
||
|
|
||
| ## Built-in functions {#cel-functions} |
There was a problem hiding this comment.
add a sentence what built-in functions are
|
|
||
| ### Function examples | ||
|
|
||
| These functions are used in the documentation examples in this section. |
There was a problem hiding this comment.
maybe a table with topic name and then used function?
| @@ -1,21 +1,20 @@ | |||
| Use an Inja template to extract a value from a request header and add it as a header to your responses. | |||
| Use [CEL expressions]({{< link-hextra path="/reference/cel/" >}}) to inject, modify, and remove headers in requests and responses. The example uses `request.headers[]` to extract a header value and combines `set`, `add`, and `remove` operations in a single transformation. | |||
There was a problem hiding this comment.
| Use [CEL expressions]({{< link-hextra path="/reference/cel/" >}}) to inject, modify, and remove headers in requests and responses. The example uses `request.headers[]` to extract a header value and combines `set`, `add`, and `remove` operations in a single transformation. | |
| Use [CEL expressions]({{< link-hextra path="/reference/cel/" >}}) to inject, modify, and remove response headers. The example uses the `request.headers[]` context variable to extract a request header value and injects the value into a response header. You also explore how to combine `set`, `add`, and `remove` operations in a single transformation. |
| {{% tab tabName="Envoy-based kgateway" %}} | ||
| ```yaml | ||
|
|
||
| The gateway intercepts the upstream response and modifies its headers before returning it to the client. You can combine `set`, `add`, and `remove` in a single policy so that the gateway applies all three operations in one pass. This configuration is useful when you need to enrich responses with values from the original request, enforce header policies like CORS, or strip internal headers that should not reach the client. |
There was a problem hiding this comment.
| The gateway intercepts the upstream response and modifies its headers before returning it to the client. You can combine `set`, `add`, and `remove` in a single policy so that the gateway applies all three operations in one pass. This configuration is useful when you need to enrich responses with values from the original request, enforce header policies like CORS, or strip internal headers that should not reach the client. | |
| The gateway intercepts the upstream response and modifies its headers before returning them to the client. You can combine `set`, `add`, and `remove` operations in a single policy so that the gateway applies all three operations in one pass. This configuration is useful when you need to enrich responses with values from the original request or strip internal headers that should not reach the client. |
| In this example, all three operations are applied together: | ||
|
|
||
| * `set`: Extracts the `x-gateway-request` request header value and sets it as the `x-gateway-response` response header. Also injects a static `x-response-raw` header with the value `hello`. Use `set` to create a header or overwrite it if it already exists. | ||
| * `add`: Appends `https://example.com` to the `access-control-allow-origin` header. Because httpbin already returns `access-control-allow-origin: *`, the response ends up with two entries for that header. Use `add` when you want to append a value without overwriting what is already present. |
There was a problem hiding this comment.
| * `add`: Appends `https://example.com` to the `access-control-allow-origin` header. Because httpbin already returns `access-control-allow-origin: *`, the response ends up with two entries for that header. Use `add` when you want to append a value without overwriting what is already present. | |
| * `add`: Appends `https://example.com` to the `access-control-allow-origin` header. Because httpbin already returns `access-control-allow-origin: *`, the response ends up with two entries for that header. Use `add` when you want to append or add a value without overwriting what is already present. |
There was a problem hiding this comment.
can you make this a list for each header and explain what happens for each? similar to what we did previously (removed lines).
| {{< /tabs >}} | ||
| {{< /doc-test >}} | ||
|
|
||
| 2. Send a request to the httpbin app and include the `x-gateway-request` request header. Verify that you get back a 200 HTTP response code and that the response includes the injected headers, contains two `access-control-allow-origin` values, and omits `access-control-allow-credentials`. |
There was a problem hiding this comment.
maybe list the expected outcome for each header in a bulleted list
There was a problem hiding this comment.
appending is weird, typically appending means I still have one header but with multiple values. The fact that you get back the same header with different values, smells like a bug to me. I don't think a system would be able to process that correctly
asked in slack, seems like this is the expectation, but in this case it is not appended, it is just added https://solo-io-corp.slack.com/archives/C08P050QFGF/p1774463768717419
There was a problem hiding this comment.
in order to show the removal, you would technically need to show an example without the policy to prove the header is actually there
| In this example, two headers are injected on every incoming request before it is forwarded upstream: | ||
|
|
||
| * `x-request-id`: A unique UUIDv4 generated by `uuid()`, used to correlate the request across services. | ||
| * `x-sampling-decision`: A random float from `random()`. A tracing backend configured to sample when the value is less than `0.1` records roughly 10% of all requests and ignores the rest. |
There was a problem hiding this comment.
| * `x-sampling-decision`: A random float from `random()`. A tracing backend configured to sample when the value is less than `0.1` records roughly 10% of all requests and ignores the rest. | |
| * `x-sampling-decision`: A random float from the `random()` function. For example, you might have a tracing backend that is configured to sample requests only if the `x-sampling-decision` header is set to `0.1` or less. |
| @@ -0,0 +1,189 @@ | |||
| Use [CEL expressions]({{< link-hextra path="/reference/cel/" >}}) to encode and decode base64 values in request headers and add the results as response headers. The examples use `base64.encode()`, `base64.decode()`, `bytes()`, `string()`, and `request.headers[]`. | |||
There was a problem hiding this comment.
| Use [CEL expressions]({{< link-hextra path="/reference/cel/" >}}) to encode and decode base64 values in request headers and add the results as response headers. The examples use `base64.encode()`, `base64.decode()`, `bytes()`, `string()`, and `request.headers[]`. | |
| Use [CEL expressions]({{< link-hextra path="/reference/cel/" >}}) to encode and decode base64 values in request headers and add the results as response headers. The examples use the `base64.encode()`, `base64.decode()`, `bytes()`, and `string()` CEL functions, and the `request.headers[]` context variables. |
| response: | ||
| set: | ||
| - name: x-user-id-encoded | ||
| value: 'base64.encode(bytes(request.headers["x-user-id"]))' |
There was a problem hiding this comment.
what does bytes do here? It looks like the transformation works without it
| @@ -0,0 +1,17 @@ | |||
| --- | |||
| title: Forward request URLs | |||
There was a problem hiding this comment.
| title: Forward request URLs | |
| title: Create redirect URLs |
| --- | ||
| title: Forward request URLs | ||
| weight: 40 | ||
| description: Use CEL expressions to construct a full request URL from context variables and forward it upstream as a request header. |
There was a problem hiding this comment.
| description: Use CEL expressions to construct a full request URL from context variables and forward it upstream as a request header. | |
| description: Use CEL expressions to construct a redirect URL from context variables and forward it upstream as a request header. |
| "curl/8.7.1" | ||
| ], | ||
| "X-Forwarded-Uri": [ | ||
| "http://www.example.com:80/get" |
There was a problem hiding this comment.
| "http://www.example.com:80/get" | |
| "http://www.example.com/get" |
| @@ -0,0 +1,167 @@ | |||
| Change the request path and HTTP method when a request header is present by using [CEL expressions]({{< link-hextra path="/reference/cel/" >}}). The example uses `request.headers[]`, `request.path`, and `request.method` with a ternary expression to conditionally set the `:path` and `:method` pseudo headers. | |||
There was a problem hiding this comment.
this example does not use query parameters. We should rename that to something like: Change request path and method
|
|
||
| ## Remove request headers | ||
|
|
||
| In this example, you remove the `x-internal-token` request header before the request is forwarded to the upstream. This configuration prevents internal credentials from being exposed to the backend service. |
There was a problem hiding this comment.
maybe show a request with that header so that people can see it is there.
There was a problem hiding this comment.
This configuration prevents internal credentials from being exposed to the backend service.
this is very specific to the name of the header that was chosen. I think in general you would use this to get rid of headers that you do not want to send to backend services
|
|
||
| ## Inject request header fields into a response body | ||
|
|
||
| In this example, you set the response body to a JSON string built from request context variables. The gateway intercepts the upstream response and replaces the body with the CEL expression result before returning it to the client. The upstream never sees the change — only the client receives the modified body. This is useful for tying responses back to request traces. |
There was a problem hiding this comment.
| In this example, you set the response body to a JSON string built from request context variables. The gateway intercepts the upstream response and replaces the body with the CEL expression result before returning it to the client. The upstream never sees the change — only the client receives the modified body. This is useful for tying responses back to request traces. | |
| In this example, you set the response body to a JSON string built from request context variables. The gateway intercepts the upstream response and replaces the body with the CEL expression result before returning it to the client. The upstream never sees the change — only the client receives the modified body. |
| ```sh | ||
| curl -vi http://$INGRESS_GW_ADDRESS:80/get \ | ||
| -H "host: www.example.com:80" \ | ||
| -H "x-request-id: alice" |
There was a problem hiding this comment.
maybe use an ID instead of the name
| {{< reuse "agw-docs/snippets/agentgateway/prereq.md" >}} | ||
|
|
||
|
|
||
| ## Inject request header fields into a response body |
There was a problem hiding this comment.
| ## Inject request header fields into a response body | |
| ## Inject request header fields into a request body |
|
|
||
| ## Inject request body fields into a response body | ||
|
|
||
| In this example, you parse a JSON request body using `json()` to extract a field and include it in the response body. Use `request.body` to access the raw incoming request body as a string. |
There was a problem hiding this comment.
| In this example, you parse a JSON request body using `json()` to extract a field and include it in the response body. Use `request.body` to access the raw incoming request body as a string. | |
| In this example, you parse a JSON request body by using the `json()` function to extract a field and include it in the response body. Use `request.body` to access the raw incoming request body as a string. |
| @@ -0,0 +1,26 @@ | |||
| --- | |||
| title: Inject response bodies | |||
There was a problem hiding this comment.
| title: Inject response bodies | |
| title: Inject response body fields |
| @@ -0,0 +1,17 @@ | |||
| --- | |||
| title: Change response bodies | |||
There was a problem hiding this comment.
| title: Change response bodies | |
| title: Update response status |
|
|
||
| ## Change the response status on a route | ||
|
|
||
| In this example, the transformation applies after routing and targets a specific HTTPRoute. You change the value of the `:status` response header to 401 if the request URI contains `foo=bar`. If the request URI does not contain `foo=bar`, you return a 403 HTTP response code. |
There was a problem hiding this comment.
| In this example, the transformation applies after routing and targets a specific HTTPRoute. You change the value of the `:status` response header to 401 if the request URI contains `foo=bar`. If the request URI does not contain `foo=bar`, you return a 403 HTTP response code. | |
| In this example, the transformation applies after routing and targets a specific HTTPRoute. You change the value of the `:status` response header to 401 if the request URI contains the `foo=bar` query parameter. If the request URI does not contain `foo=bar`, you return a 403 HTTP response code. |
| @@ -0,0 +1,105 @@ | |||
| Use the `filterKeys()` and `merge()` [CEL functions]({{< link-hextra path="/reference/cel/#functions-policy-all" >}}) 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 values overwriting any matching keys in the first. `toJson()` serializes the resulting map back to a JSON string. | |||
There was a problem hiding this comment.
| Use the `filterKeys()` and `merge()` [CEL functions]({{< link-hextra path="/reference/cel/#functions-policy-all" >}}) 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 values overwriting any matching keys in the first. `toJson()` serializes the resulting map back to a JSON string. | |
| Use the `filterKeys()` and `merge()` [CEL functions]({{< link-hextra path="/reference/cel/#functions-policy-all" >}}) 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. |
| {{< /doc-test >}} | ||
|
|
||
| The expression breaks down as follows: | ||
| * `json(request.body)`: Parses the raw request body string into a map. |
|
|
||
| ## Log specific variables | ||
|
|
||
| Map individual attribute names to CEL expressions. The attribute names on the left (`request_path`, `request_method`, `client_ip`) are arbitrary and become the keys in the structured log output. |
There was a problem hiding this comment.
not sure what we mean with on the left?
There was a problem hiding this comment.
maybe just say: Add access log attributes with CEL expressions.
|
|
||
| {{< reuse "agw-docs/snippets/agentgateway/prereq.md" >}} | ||
|
|
||
| ## Log specific variables |
There was a problem hiding this comment.
| ## Log specific variables | |
| ## Log specific request data |
|
|
||
| Add a `filter` CEL expression to log only requests that match a condition. This configuration is useful for reducing log volume by capturing only error responses or specific traffic patterns. | ||
|
|
||
| 1. Create an {{< reuse "agw-docs/snippets/trafficpolicy.md" >}} resource with a `filter` field set to a CEL expression. Logs are written only when the expression evaluates to `true`. |
There was a problem hiding this comment.
| 1. Create an {{< reuse "agw-docs/snippets/trafficpolicy.md" >}} resource with a `filter` field set to a CEL expression. Logs are written only when the expression evaluates to `true`. | |
| 1. Create an {{< reuse "agw-docs/snippets/trafficpolicy.md" >}} resource with a `filter` field that logs requests only if the response status code does not equal 400. |
Signed-off-by: Kristin Brown <[email protected]>
Added new transformation topics, updated from kgateway. Link checker changes also included to be able to check a subset of files effectively.
Link checker changes
Adds pull request support to the link checker workflow. Previously the workflow only ran on a schedule (Monday) and manual dispatch, checking all links across all files and reporting results via GitHub issues and Slack. PRs now trigger a faster, targeted check.
Trigger changes
On pull requests
On cron/dispatch
Other