Variables can be used to store intermediate results during flow execution. A valid variable name starts with $
followed by a letter a
…z
or A
…Z
or an underscore _
. More letters, underscores, the numbers 0
…9
or hyphens -
may follow.
The following predefined variables exist:
$body
: client request body
$env
: environment variables
$request
: client request information
$server
: server information
$upstream
: upstream response information
$error
: Contains information regarding the most recent error, but is initially empty.
Try the following flow with
$ curl --data hello localhost:8080 | jq
<flow><template>{"$request": {{{with $request }}{{: * }}{{end}}},"$body": {{ $body }},"$upstream": {{ $upstream }},"$server": {{{: $server/* }}},"$env": {{{: $env/* }}}}</template></flow>
The actions request
and requests
set the $upstream
variable, too:
<flow><requests>{"ok": {"url": "https://httpbin.org/status/200"},"failure": {"url": "https://httpbin.org/status/500"}}</requests><template>{"$upstream": {{{with $upstream }}{{: * }}{{end}}}}</template></flow>
{"$upstream": {"ok": {"url": "https://httpbin.org/status/200","status": 200,"cacheHit": false,"headers": { … }},"failure": {…}}}
Global variables are usually defined as the output of eval
actions. The variable name is defined in the out="…"
attribute. It must begin with $
followed by a letter and then more letters or numbers.
<flow><!-- $x = 1 --><eval out="$x">1</eval><!-- $x = $x + 5 --><eval out="$x">$x + 5</eval><!-- $answer = $x * 7 --><eval out="$answer">$x * 7</eval></flow>
For structured JSON variables, you can use the template
action:
<flow><template out="$cfg">{"stage": "prod","mock": {{ boolean($request/get/mock) }},"answer": {{ $answer }}}</template></flow>
Variables may be copied with eval, too:
<flow><eval out="$client_request">$request</eval>…</flow>
Templates may define local variables with {{$… := …}}
. Those variables are undefined outside the template they're defined in:
<flow><template>{{$answer:= 42 }}</template><!-- null --><template>{{ $answer }}</template></flow>
📎 If a variable containing binary content is processed in a
template
orxslt
action, its content will probably end up being truncated, garbled or both.
Attempting to access a variable that has not been set previously will yield an empty node-set. The empty node-set will be evaluated to false
in conditions and produces the string null
in placeholders:
<flow><template>{{if $undefined }}will never be reached{{else}}<!-- null -->{{ $undefined }}{{end}}</template></flow>
The $body
variable contains the request body.
If the request body is JSON (Content-Type: application/json
) $body
contains the parsed JSON. You can access its properties with XPath expressions with a json
segment before the top-level properties. E.g.
{"foo": 1,"bar": {"baz": true}}
The value for foo
can be accessed by $body/json/foo
, the value for baz
by $body/json/bar/baz
.
In other cases the content is stored in $body
as a string and cannot be accessed by XPath.
The $request
variable contains information about the incoming client request, such as the URL, the request header fields and possibly the query component or cookies, if any were sent.
Example:
<request><method>POST</method><purpose>main</purpose><debug/><host>localhost</host><port>12345</port><id>XeeSVJ5AFt8VyXYagp3lvgAAACc</id><url>http://localhost:12345/api/proxy/foo?a=b&c=d</url><path>/api/proxy/foo</path><query>a=b&c=d</query><headers><host>localhost:12345</host><user-agent>curl/7.64.0</user-agent><accept>*/*</accept><cookie>NAME1=VALUE1; NAME2=VALUE2</cookie><content-type>application/x-www-form-urlencoded</content-type><foo>asdf</foo><bar>qwer</bar><content-length>17</content-length></headers><get><a>b</a><c>d</c></get><cookies><NAME1>VALUE1</NAME1><NAME2>VALUE2</NAME2></cookies><endpoint>/api/proxy</endpoint></request>
As HTTP request headers are defined to be case-insensitive, their names are lower-cased for convenient access even if the client has sent the field name with upper-case letters, e.g.:
$request/headers/user-agent
If a client URL path is matched by a wildcard path, $request/endpoint
is the path part preceding the part matched by /**
. Otherwise, $request/endpoint
is the same as $request/path
.
…basePath: /api…paths:/**:…/foo/**:…/foo/qux:…/foo/{p1}:…
Client URL | matches |
|
|
/foo/qux | /api/foo/qux | /api/foo/qux | |
/foo/{p1} | /api/foo/quuux | /api/foo/quuux | |
/foo/** | /api/foo/bar/qux | /api/foo | |
/** | /api/bar | /api |
The $upstream
variable contains information about upstream responses. The properties for each upstream response are stored with the request ID (id
property or content
attribute).
url
- The request URL (string)
status
- The response status code (integer)
cacheHit
- true
if the response was served from a cache (see use-http-cache
or force-cache-ttl
request options), false
otherwise
headers
- The response headers, each with a lower-cased field name
Example:
<upstream><request1><url>https://httpbin.org/status/200</url><status number="">200</status><cacheHit>false</cacheHit><headers><date>Thu, 27 Aug 2020 14:12:33 GMT</date><content-type>text/html; charset=utf-8</content-type><connection>keep-alive</connection><server>gunicorn/19.9.0</server><access-control-allow-origin>*</access-control-allow-origin><access-control-allow-credentials>true</access-control-allow-credentials></headers></request1><request2><url>https://httpbin.org/status/500</url><status number="">500</status><cacheHit>false</cacheHit><headers><date>Thu, 27 Aug 2020 14:12:33 GMT</date><content-type>text/html; charset=utf-8</content-type><connection>keep-alive</connection><server>gunicorn/19.9.0</server><access-control-allow-origin>*</access-control-allow-origin><access-control-allow-credentials>true</access-control-allow-credentials></headers></request2></upstream>
To check, for example, if the status code of the response with the ID myRequest
is successful you can use the following XPath expression:
$upstream/myRequest/status = 200
Client request and response validation, upstream connection and request and response validation errors, and those triggered by the error
action will store information about the error in $error
. While initially empty, $error
will have the following properties containing information about the most recent error, unless it is triggered by the error
action:
status
- the HTTP status that is used by default for responses if the error was passed to the client (type: number
)
code
- an error code (type: number
)
message
- a single line of text describing the error (type: string
)
info
- detailed information about the error (type: array
of string
)
requestID
- the requestID as it should appear in the logs (type: string
)
Example:
{"status": 400,"code": 3204,"message": "Input Validation Failed","info": ["Path /api/empty-body/ not found."],"requestID": "[email protected]"}
If set by the error
action, $error
contains the JSON template result of the action's element body.
Using Env Vars (cookbook)