Go Templates

Last updated: 5 minutes read.

Tyk’s request and response body transform middleware use the Go template language to parse and modify the provided input.

Go templates are also used by Tyk’s webhook event handler to produce the payload for the HTTP request sent to the target system.

In this section of the documentation, we provide some guidance and a few examples on the use of Go templating with Tyk.

Data format conversion using helper functions

Tyk provides two helper functions to assist with data format translation between JSON and XML:

  • jsonMarshal performs JSON style character escaping on an XML field and, for complex objects, serialises them to a JSON string (example)
  • xmlMarshal performs the equivalent conversion from JSON to XML (example)

When creating these functions within your Go templates, please note:

  • the use of . in the template refers to the entire input, whereas something like .myField refers to just the myField field of the input
  • the pipe | joins together the things either side of it, which is typically input data on the left and a receiving command to process the data on the right, such as jsonMarshal

Hence {{ . | jsonMarshal }} will pass the entire input to the jsonMarshal helper function.

Using functions within Go templates

You can define and use functions in the Go templates that are used for body transforms in Tyk. Functions allow you to abstract common template logic for cleaner code and to aid reusability. Breaking the template into functions improves readability of more complex tenplates.

Here is an example where we define a function called myFunction that accepts one parameter:

{{- define "myFunction" }}
  Hello {{.}}!
{{- end}}

We can call that function and pass “world” as the parameter:

{
  "message": {{ call . "myFunction" "world"}}
}

The output would be:

{
  "message": "Hello world!" 
}

We have bundled the Sprig Library (v3) which provides over 70 pre-written functions for transformations to assist the creation of powerful Go templates to transform your API requests.

Additional resources

Here’s a useful blogpost and YouTube tutorial that can help you to learn about using Go templates.

Go templating examples

Here we provide worked examples for both JSON and XML formatted inputs. We also explain examples using the jsonMarshal and xmlMarshal helper functions.

Example JSON transformation template

Imagine you have a published API that accepts the request listed below, but your upstream service requires a few alterations, namely:

  • swapping the values of parameters value1 and value2
  • renaming the value_list to transformed_list
  • adding a user-id extracted from the session metadata
  • adding a client-ip logging the client IP
  • adding a req-type that logs the value provided in query parameter type

Input

  • Session metadata uid = user123
  • IP address of calling client = 192.0.0.1
  • Query parameter type = strict
{
  "value1": "value-1",
  "value2": "value-2",
  "value_list": [
    "one",
    "two",
    "three"
  ]
}

Template

{
  "value1": "{{.value2}}",
  "value2": "{{.value1}}",
  "transformed_list": [
    {{range $index, $element := index . "value_list"}}
    {{if $index}}, {{end}}
    "{{$element}}"
    {{end}}
  ],
  "user-id": "{{._tyk_meta.uid}}",
  "user-ip": "{{._tyk_context.remote_addr}}",
  "req-type": "{{ ._tyk_context.request_data.param.type }}" 
}

In this template:

  • .value1 accesses the “value1” field of the input JSON
  • we swap value1 and value2
  • we use the range function to loop through the “value_list” array
  • ._tyk_meta.uid injects the “uid” session metadata value
  • ._tyk_context.remote_addr injects the client IP address from the context
  • ._tyk_context.request_data.param.type injects query parameter “type”

Output

{
  "value1": "value-2",
  "value2": "value-1",
  "transformed_list": [
    "one",
    "two",
    "three"
  ],
  "user-id": "user123"
  "user-ip": "192.0.0.1"
  "req-type": "strict"
}

Example XML transformation template

XML cannot be as easily decoded into strict structures as JSON, so the syntax is a little different when working with an XML document. Here we are performing the reverse translation, starting with XML and converting to JSON.

Input

  • Session metadata uid = user123
  • IP address of calling client = 192.0.0.1
  • Query parameter type = strict
<?xml version="1.0" encoding="UTF-8"?>
<data>
  <body>
    <value1>value-1</value1>
    <value2>value-2</value2>
    <valueList>
      <item>one</item>
      <item>two</item>
      <item>three</item>
    </valueList>
  </body>
</data>

Template

<?xml version="1.0" encoding="UTF-8"?>
<data>
  <body>
    <value1>{{ .data.body.value2 }}</value1>
    <value2>{{ .data.body.value1 }}</value2>
    <transformedList>
      {{range $index, $element := .data.body.valueList.item }}
      <item>{{$element}}</item>
      {{end}}
    </transformedList>
    <userId>{{ ._tyk_meta.uid }}</userId>
    <userIp>{{ ._tyk_context.remote_addr }}</userIp>
    <reqType>{{ ._tyk_context.request_data.param.type }}</reqType>
  </body>
</data>

In this template:

  • .data.body.value1 accesses the “value1” field of the input XML
  • we swap value1 and value2
  • we use the range function to loop through the “value_list” array
  • ._tyk_meta.uid injects the “uid” session metadata value
  • ._tyk_context.remote_addr injects the client IP address from the context
  • ._tyk_context.request_data.param.type injects query parameter “type”

Output

<?xml version="1.0" encoding="UTF-8"?>
<data>
  <body>
    <value1>value-2</value1>
    <value2>value-1</value2>
    <transformedList>
      <item>one</item>
      <item>two</item>
      <item>three</item>
    </transformedList>
    <userId>user123</userId>
    <userIp>192.0.0.1</userIp>
    <reqType>strict</reqType>
  </body>
</data>

XML to JSON conversion using jsonMarshal

The jsonMarshal function converts XML formatted input into JSON, for example:

Input

<hello>world</hello>

Template

{{ . | jsonMarshal }}

Output

{"hello":"world"}

Note that in this example, Go will step through the entire data structure provided to the template. When used in the Request or Response Body Transform middleware, this would include Context Variables and Session Metadata if provided to the middleware.

JSON to XML conversion using xmlMarshal

The xmlMarshal function converts JSON formatted input into XML, for example:

Input

{"hello":"world"}

Template

{{ . | xmlMarshal }}

Output

<hello>world</hello>

Note that in this example, Go will step through the entire data structure provided to the template. When used in the Request or Response Body Transform middleware, this would include Context Variables and Session Metadata if provided to the middleware.