Template Expressions - WunderGraph
Template Expressions Overview
Template Expressions are a robust mechanism for accessing information related to requests, responses, and other key aspects of the router’s operation. They enable conditional feature activation and allow for extracting and configuring values dynamically. An example use case involves conditionally blocking mutations:
security:
block_mutations:
enabled: true
condition: "request.header.Get('x-block-mutation') == 'yes'"
In this example, the condition is evaluated each time a request is made. Template Expressions provide access to request details, including headers, URLs, and query parameters. However, not all fields are consistently available throughout the request lifecycle. For instance, authentication data becomes accessible only after successful authentication. During the build process, the router validates expressions. If an expression is invalid or does not return the expected type (such as a boolean or string), an error message is generated to ensure clarity and correctness.
Template Language
The expressions are based on the expr-lang template language. This language is characterized by its:
- Safety – Expressions are evaluated securely.
- Speed – The language is optimized for performance.
- Side-effect-free operation – Expressions are read-only and do not alter state.
To modify configurations or manipulate requests and responses, implementing a custom module is recommended.
Naming Conventions
- Fields: Use camelCase (e.g.,
request.auth.claims). - Methods: Use PascalCase (e.g.,
request.header.Get("Content-Type")). - Utility Functions: camelCase (e.g. trim) for the full list see here.
Expression Context
Request Object
The request object is a read-only entity that provides details about the incoming client request. It is accessible at all times during the lifecycle of the request.
Available Fields:
request.methodrequest.url.hostrequest.url.pathrequest.url.portrequest.trace.sampledrequest.error
Operation Object
request.operationrequest.operation.namerequest.operation.type(possible values:mutationorquery)request.operation.hash- Hash of the normalized operation.request.operation.queryPlanHash- The Hash used as the query plan cache key.request.operation.sha256Hash- SHA-256 hash of the original operation query string sent by the client.request.operation.parsingTime(time.Duration)request.operation.persistedIdrequest.operation.normalizationTime(time.Duration)request.operation.validationTime(time.Duration)request.operation.planningTime(time.Duration)request.operation.resolverAcquireDuration(time.Duration)request.operation.normalizationCacheHit(bool)request.operation.variablesNormalizationCacheHit(bool)request.operation.variablesRemappingCacheHit(bool)request.operation.persistedOperationCacheHit(bool)request.operation.planCacheHit(bool)request.operation.variables- The operation variables sent with the request, as a JSON string.
request.operation.* fields are populated during HTTP request handling. They are not available for WebSocket subscription access logs, which reuse the expression context from the initial HTTP upgrade request.
Example expressions
hasPrefix(request.operation.name, 'Delete') == true
request.operation.sha256Hash != ''
request.operation.persistedId != ''
request.operation.planCacheHit == true
# Log the variables only when the variable remapping cache missed.
request.operation.variablesRemappingCacheHit ? '' : request.operation.variables
Client Object
request.clientrequest.client.namerequest.client.version
Example expressions
request.client.name == 'CoolGraphQLClient'
Header Access:
request.header.Get('Content-Type')– Header retrieval is case-insensitive.
Example expressions
request.url.query.foo == 'bar' && request.method == 'POST'
request.header.Get('x-block-mutation') == 'yes'
Request Body Object
The body object holds information related to the request body. Available Fields:
request.body.raw
Example expressions
request.error != nil ? request.body.raw : ''
Authentication Object
The auth object contains authentication-related information for the request.
Available Fields:
request.authrequest.auth.isAuthenticatedrequest.auth.typerequest.auth.claimsrequest.auth.scopes
Example expressions
'read:miscellaneous' in request.auth.scopes
request.auth.isAuthenticated
Subgraph Object
The Subgraph object provides information about the current subgraph being accessed in the request.
Properties
subgraph.id(string)subgraph.name(string)subgraph.request(SubgraphRequest)
SubgraphRequest Properties
subgraph.request.error(error)subgraph.request.clientTrace(ClientTrace)subgraph.request.startTime(int)
Example expressions
subgraph.name == 'products'
subgraph.request.error != nil
subgraph.request.clientTrace.connAcquireDuration > 1.0
Response Object
The response object provides details about the outgoing response.
Available Fields:
response.body(ResponseBody)
ResponseBody Object
The body object holds information related to the response body.
Available Fields:
response.body.raw(string)
Example expressions
request.error != nil ? response.body.raw : ''
Subgraph Retry Expressions
You can use expressions to specify the conditions for retries upon subgraph request failures.
Functions
You can use all the built-in functions of the Expr language.
Additional Notes
- A Request for Comments (RFC) is open for feedback on the complete API specification. Future implementations will be driven by customer requirements.