Skip to content

Commit 0c62149

Browse files
authored
docs(router): Add Expressions documentation (#7164)
1 parent 4b2a248 commit 0c62149

File tree

6 files changed

+168
-13
lines changed

6 files changed

+168
-13
lines changed
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
export default {
22
index: 'Overview',
33
'environment-variables': 'Environment Variables',
4+
expressions: 'Expressions',
45
};
Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
---
2+
title: Expressions
3+
---
4+
5+
import { Callout } from '@theguild/components'
6+
7+
# Expressions
8+
9+
The Hive Router uses **expressions** written in
10+
[VRL (Vector Remap Language)](https://vector.dev/docs/reference/vrl/) to make dynamic decisions at
11+
runtime. VRL is a small, declarative language originally created by DataDog for the
12+
[Vector observability pipeline](https://vector.dev/) and is well‑suited for parsing and transforming
13+
structured data. In Hive Router, expressions let you:
14+
15+
- [Route requests to different subgraph URLs](../guides/dynamic-subgraph-routing) based on HTTP
16+
headers, geographic region or other request metadata.
17+
- [Insert, modify or remove HTTP headers](../guides/header-manipulation) before forwarding a request
18+
to a subgraph or before sending a response back to the client.
19+
20+
Although the concept of "expressions" appears in several parts of the configuration, the syntax and
21+
available APIs are consistent. This page explains **what variables and functions are available, when
22+
different variables can be used**, and links you to the official VRL documentation for the full
23+
language reference.
24+
25+
## Syntax overview
26+
27+
Every expression evaluates to a value, and you can build more complex logic using functions and
28+
control‑flow. For example:
29+
30+
```
31+
if .request.headers."x-feature-toggle" == "beta" {
32+
"https://beta.example.com/graphql"
33+
} else {
34+
.original_url
35+
}
36+
```
37+
38+
<Callout type="info">
39+
You can break long expressions across multiple lines using the `|` indentation in YAML.
40+
</Callout>
41+
42+
VRL supports [variables](#available-variables) (prefixed with a dot), built‑in
43+
[functions](#available-functions), simple arithmetic and comparisons, and control structures such as
44+
`if … else`.
45+
46+
Multi‑line expressions are especially useful for readability and complex routing logic.
47+
48+
## Available values
49+
50+
Within an expression you interact with a few top‑level values. The most important ones are:
51+
52+
### `.request`
53+
54+
Represents the incoming HTTP request. It exposes nested fields such as:
55+
56+
- `.request.headers` - a case‑insensitive map of request headers. For example,
57+
`.request.headers.authorization` gives you the value of the `Authorization` header.
58+
- `.request.method` - the HTTP method as a lowercase string (e.g. `"post"`).
59+
- `.request.url.host` - the request host (e.g. `api.example.com`).
60+
- `.request.url.port` - the request port (e.g. `443`).
61+
- `.request.url.path` - the request path (e.g. `/graphql`).
62+
- `.request.operation.name` - the name of the GraphQL operation being executed, if provided.
63+
- `.request.operation.type` - the type of GraphQL operation being executed (e.g. `"query"`,
64+
`"mutation"`, or `"subscription"`).
65+
- `.request.operation.query` - the full GraphQL query string being executed.
66+
67+
These values allow you to branch logic based on who is calling your API and what data they send.
68+
69+
### `.response`
70+
71+
Available only in **response** header rules. It represents the HTTP response from a subgraph call.
72+
You can inspect `.response.url` or `.response.headers` and then set or override additional headers.
73+
For example, you could conditionally add a cache header based on the subgraph’s status code. This
74+
variable is not present when computing request headers or dynamic URLs, because the response does
75+
not yet exist.
76+
77+
- `.response.headers` - a case‑insensitive map of response headers.
78+
79+
### `.subgraph`
80+
81+
Available in both **request** and **response** header rules. It provides metadata about the subgraph
82+
handling the current request, including:
83+
84+
- `.subgraph.name` - the name of the subgraph as defined in your supergraph schema.
85+
86+
### `.timestamp`
87+
88+
While not a full object, the special variable `.timestamp` yields the current UNIX timestamp. The
89+
header manipulation guide demonstrates using `.timestamp` to add a `X‑Request‑Time` header. This is
90+
useful for debugging and tracing requests.
91+
92+
### `.original_url`
93+
94+
This variable is only available in [dynamic routing expressions](./override_subgraph_urls). It holds
95+
the default URL for the current subgraph, as declared in your supergraph schema. Because the
96+
expression must return a URL, you should always provide a fallback using `.original_url` so that
97+
requests are routed somewhere when no condition matches. The configuration reference emphasises this
98+
by showing a pattern where the expression returns `.original_url` in the `else` branch.
99+
100+
## Available functions
101+
102+
The Hive Router exposes the full set of
103+
[VRL built‑in functions](https://vector.dev/docs/reference/vrl/functions/). The configuration guides
104+
use a few of them in examples:
105+
106+
- `replace(value, pattern, replacement)` - returns a new string with all matches of pattern
107+
replaced. In the header manipulation guide it's used to normalise an `Authorization` header by
108+
stripping existing prefixes.
109+
- `contains(value, substring)` - tests whether a string contains a substring.
110+
- `random_int(min, max)` - produces a random integer in the inclusive range. Combined with `if` to
111+
create percentage‑based canary routing of subgraphs.
112+
- `lowercase(value)`, `uppercase(value)`, `split(value, delimiter)`, `to_int(value)` - helpful for
113+
normalising and parsing header values.
114+
115+
For a complete list of functions - including string manipulation, number conversion, JSON parsing,
116+
and more - see the [VRL function reference](https://vector.dev/docs/reference/vrl/functions/). When
117+
writing expressions, you can call any of these functions directly.
118+
119+
<Callout type="warning">
120+
Functions that could perform network I/O (e.g. HTTP requests) are intentionally not available, so
121+
expressions remain side‑effect‑free and deterministic.
122+
</Callout>
123+
124+
## Troubleshooting
125+
126+
When an expression doesn't work as expected, it can be due to a compilation error (syntax) or a
127+
runtime error (evaluation). The Hive Router provides detailed logs to help you diagnose the issue.
128+
129+
### Compilation Errors
130+
131+
Compilation errors occur if your expression has invalid VRL syntax. The router will fail to start
132+
and log an error message pointing to the problematic expression. Common syntax errors include
133+
mismatched parentheses, missing commas, or incorrect function names.
134+
135+
### Runtime Errors
136+
137+
Runtime errors happen when a syntactically correct expression fails during execution. These are
138+
logged by the router during a request. The router will also return an error response to the client.
139+
140+
Here are some frequent causes of runtime errors in expressions:
141+
142+
1. **Accessing an unavailable variable**: Expressions run in specific contexts. For example, trying
143+
to access `.response` in a request header rule will fail because the response from the subgraph
144+
doesn't exist yet.
145+
1. **Type Mismatches**: VRL is strongly typed. If you try to perform an operation on incompatible
146+
types, like comparing a string with an integer, you'll get a runtime error.
147+
1. **Handling `null` values**: Accessing a non-existent header or field returns `null`. Operations
148+
on `null` values can lead to errors. Always check for the existence of a value or provide a
149+
fallback. You can use the `||` operator to provide a default value (e.g.,
150+
`.request.headers."x-custom-header" || "default-value"`).
151+
152+
For a full list of error codes and their meanings, refer to the
153+
[VRL error reference](https://vector.dev/docs/reference/vrl/errors).

packages/web/docs/src/content/router/configuration/headers.mdx

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -63,11 +63,11 @@ values.
6363

6464
Adds a new header or overwrites an existing one.
6565

66-
| Key | Type | Description |
67-
| :----------- | :------- | :----------------------------------------------------------- |
68-
| `name` | `string` | **Required.** The name of the header to insert or overwrite. |
69-
| `value` | `string` | A static string value for the header. |
70-
| `expression` | `string` | A VRL expression that dynamically computes the header value. |
66+
| Key | Type | Description |
67+
| :----------- | :------- | :------------------------------------------------------------------------- |
68+
| `name` | `string` | **Required.** The name of the header to insert or overwrite. |
69+
| `value` | `string` | A static string value for the header. |
70+
| `expression` | `string` | An [expression](./expressions) that dynamically computes the header value. |
7171

7272
### 3. `remove`
7373

packages/web/docs/src/content/router/configuration/override_subgraph_urls.mdx

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,10 +50,11 @@ override_subgraph_urls:
5050

5151
#### Dynamic URL with `expression`
5252

53-
When an `object` is provided, it must contain a VRL `expression` that returns a URL string. The
54-
expression is evaluated for each request, allowing for request-time routing decisions.
53+
When an `object` is provided, it must contain an `expression` that returns a URL string. The
54+
[expression](./expressions) is evaluated for each request, allowing for request-time routing
55+
decisions.
5556

56-
- `expression`: **(string, required)** A VRL expression that computes the new URL.
57+
- `expression`: **(string, required)** An [expression](./expressions) that computes the new URL.
5758

5859
Within the `expression`, you have access to two key variables:
5960

packages/web/docs/src/content/router/guides/dynamic-subgraph-routing.mdx

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,8 @@ configuration reference, see
1616

1717
## How It Works
1818

19-
Dynamic routing uses [VRL (Vector Remap Language)](https://vrl.dev) expressions to decide where to
20-
send requests. For each request, the router evaluates your expression and routes to the URL it
21-
returns.
19+
Dynamic routing uses [expressions](../configuration/expressions) to decide where to send requests.
20+
For each request, the router evaluates your expression and routes to the URL it returns.
2221

2322
**What you have access to:**
2423

packages/web/docs/src/content/router/guides/header-manipulation.mdx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ headers:
9595

9696
## Modifying Header Values
9797

98-
You can also transform header values on the fly using expressions.
98+
You can also transform header values on the fly using [expressions](../configuration/expressions).
9999

100100
```yaml filename="router.config.yaml"
101101
headers:
@@ -144,7 +144,8 @@ router will use the value from the last subgraph that responded.
144144

145145
## Conditional Header Rules
146146

147-
Apply different rules based on request properties, using expressions.
147+
Apply different rules based on request properties, using
148+
[expressions](../configuration/expressions).
148149

149150
```yaml filename="router.config.yaml"
150151
headers:

0 commit comments

Comments
 (0)