Using templating in simulations

Templating in Hoverfly Cloud provides a powerful way to render just about anything you want into the response. It uses the well known {{ handlebars }} syntax where the handlebars surround functions which allow you to control information flow.

In order to enable templating you need to explicitly click the "Enable templating" checkbox when crafting your response.

Things you can do with templating include:

1. Render back any part of the Request

The most basic thing you might want to do is render back in the response some part of the original request. This can be easily achieved using any of the following functions:

{{ Request.Scheme }} 
{{ Request.QueryParam.myParam }} 
{{ Request.QueryParam.NameOfParameter.[0] }} 
{{ Request.Path.[0] }} 
{{ Request.Method }} 
{{ Request.Host }} 
{{ Request.Body 'jsonpath' '$.id' }} 
{{ Request.Body 'xpath' '/root/id' }} 
{{ Request.FormData.email }} 
{{ Request.Header.X-Header-Id }} 
{{ Request.Header.X-Header-Id.[0] }} 

Note that where the result is an array, you access it it using zero based indexes. Read more about these here

2. Render synthetic data

FAKER:

Hoverfly supports over 200 Faker functions. You can see the full list here

Hoverfly also supports a number of other simple random data generator functions:

A random string

{{ randomString }}

hGfclKjnmwcCds

A random string with a specified length

{{ randomStringLength 2 }}

KC

A random boolean

{{ randomBoolean }}

true

A random integer

{{ randomInteger }}

42

A random integer within a range

{{ randomIntegerRange 1 10 }}

7

A random float

{{ randomFloat }}

42

A random float within a range

{{ randomFloatRange 1.0 10.0 }}

7.4563213423

A random email address

{{ randomEmail }}

BenClark@photolist.com

A random IPv4 address

{{ randomIPv4 }}

224.36.27.8

A random IPv6 address

{{ randomIPv6 }}

41d7:daa0:6e97:6fce:411e:681:f86f:e557

A random UUID

{{ randomUuid }}

3. Render dates and times with offsets

The following date and time methods are supported:

Description

Example

Result

The current date time with offset, in the given format.

For example:

  • The current date time plus 1 day in unix timestamp

  • The current date time in ISO 8601 format

  • The current date time minus 1 day in custom format

  • {{ now '1d' 'unix' }}

  • {{ now '' '' }}

  • {{ now '-1d' '2006-Jan-02' }}

  • 1136300645

  • 2006-01-02T15:04:05Z

  • 2006-Jan-01

When using template helper method now, time offset must be formatted using the following syntax.

Shorthand

Type

ns

Nanosecond

us/µs

Microsecond

ms

Millisecond

s

Second

m

Minute

h

Hour

d

Day

y

Year

Prefix an offset with - to subtract the duration from the current date time.

Example time offset

5m

5 minutes

1h30m

1 hour 5 minutes

1y10d

1 year 10 days

Date time formats

When using template helper method now, date time formats must follow the Golang syntax. More can be found out here https://golang.org/pkg/time/#Parse

Example date time formats

2006-01-02T15:04:05Z07:00

Mon, 02 Jan 2006 15:04:05 MST

Jan _2 15:04:05

4. Render lookup data from a CSV (Enterprise customers only)

Hoverfly now support CSV data sources to be uploaded with the simulations, and these can be used in the templated responses to provide real data back based on a key and column combination.

Read more here

5. Conditional and Equality statements

You can control logic within your template using a number of conditional statements including:

  • {{#if } {{/else}} {{/if }} - this checks for the existence of something (this does not check equality)

  • {{#unless}} {{/else}} {{/unless}} - this checks for the non-existence of something (this does not check non-equality)

  • {{#equal}} {{/else}} {{/equal}} - this checks equality, i.e. if something equals something

Follow a tutorial here to learn more about conditionals and equality

6. Loops

The ability to loop over arrays of data can be very useful in constructing a response. Some of the arrays typically in a response are:

  • the elements of path

  • the headers in the request

  • an array of query parameters if there are more than one with the same name

  • a JSON array extracted from the body of a request

The following block is used to loop over an array:

  • {{#each}} {{else}} {{/each}}

Follow a tutorial here to learn more about looping

7. Variables and Arrays

To support more complex logical flows within template, as well as to make arithmetic operations within loops possible, we have introduced variables and arrays to the templating engine.

Variables:

You can create a variable and put a value into it using the following function:

{{ putValue 'variablename' value outputtotemplate? }}

example:

{{ putValue 'id' (Request.Body 'jsonpath' '$.id') true }}

(The outputtotemplate boolean will determine if the value is written out to the template as well as stored in memory, or just stored in memory.)

You can read a variable and use it in another function, or simply render it into the template using the following function:

{{ getValue 'variablename' }}

example: simply rendering out:

{{ getValue 'price' }}

example: using within another function:

{{ add (getValue 'price') this.tax '0.00' }}

Arrays:

You can append items to an array using the following function: (this is useful within a loop when you need to sum a list of numbers at the end)

{{ addToArray 'arrayname' value outputtotemplate?}}

example:

{{ addToArray 'totalweight' (multiply (this.quantity) (csv 'products' 'upc' 'this.upc' 'weight') '') false}}

(The outputtotemplate boolean will determine if the value is written out to the template as well as appended to the array, or just appended to the array.)

You would generally not render an array straight into the template - they would typically be used by another function or block statement that takes arrays, using the following function:

{{ getValue <variablename> }}

example: passing into another function:

{{ sum (getArray 'totalweight') '0.00' }}

8. Arithmetic operations

You can perform simple addition, subtraction, multiplication and division between any two numbers using the following functions. Note that these will return the result, either into the template, or if they are enclosed in another function, then into that function.

Addition

{{ add  <number1> <number2> <format>}}

example:

{{ add this.cost this.markup '0.00' }}

Subtraction

{{ subtract <number1> <number2> <format> }}

example:

{{ subtract this.fullprice this.discount '0.00' }}

Multiplication

{{ multiply <number1> <number2> <format> }}

example:

{{ multiply this.quantity this.price '0.00' }}

Division

{{ divide <number1> <number2> <format> }}

example:

{{ divide this.discount '10' '0.00'}}

Summing Arrays

You can also sum an array of numbers using the following function:

{{ sum <array> <format> }}

example 1:

{{ sum (split (Request.Body 'jsonpath' '$.price[*]') ' ') '0.00' }}

example 2:

{{ sum myArrayOfNumbers '0.00' }}

9. Render data from part of any previous Request or Response (Enterprise customers only)

Hoverfly Cloud has two separate mechanisms for creating API simulations that can mock a stateful service. The first uses a state machine with variables that you set and which control how the simulation flows through states. This is available to all customers.

You can read about this approach in the Hoverfly documentation here

The second approach provides the ability to retrieve from memory any past request or response that has been indexed with a key you provide, and then retrieve any part of that request or response for processing in your current response. This allows the mocking of a persistent back-end service. This is only available to enterprise customers.

You can read about this approach here

10. Combining and nesting functions

With all functions that take parameters the convention is as follows:

  • String literal parameters and number literal parameters are enclosed in single quotes.

  • Parameter values that are derived from nested functions are not enclosed in single quotes, they are enclosed with round brackets

  • When using variables and arrays, their names are string based parameters and are normally enclosed in single quotes, unless they are the result of a nested function (this can be useful)

  • Boolean flag parameters are not enclosed in single quotes.

  • Iterator instance parameters (this, or this.some-variable) are not enclosed in single quotes

  • Function names are not enclosed in single quotes.

Examples:

{{ putValue 'id' (Request.Body 'jsonpath' '$.id') true }}
{{ multiply '5' '2' '0.00' }}
{{ multiply this.quantity this.price '0.00' }}

Many functions can be nested inside other functions. In some cases it makes sense to nest multiple levels of functions. It is conventional to enclose the inner functions with round brackets.

Example 1:

Consider the following 3 functions:

{{ sum <array '<format>' }}
{{ split <delimited-string> '<delimiter>' }}
{{ Request.Body '<querylanguage>' '<query>' }}

As an example they can be combined together in the following way:

{{ sum(split (Request.Body 'jsonpath' '$.price[*]') ' ') '0.00' }}

Example 2:

Consider the following 3 functions:

{{ putValue '<variablename>' <value> <outputtotemplate?> }}
{{ multiply <number1> <number2> '<format>' }}
{{ csv '<data-source-name>' '<key-column>' '<key-value>' '<return-column>' }}

As an example they can be combined together in the following way:

{{ putValue 'linetotalsbeforediscounts' (multiply (this.quantity) (csv 'products' 'upc' 'this.upc' 'price') '') false}}

11. Useful functions to know

Concatenate two strings

{{ concat <string1> <string2> }}

Search and replace text in a string

{{ replace <string-to-search> <string-to-replace> <replacement-string> }}

Create an array from a delimited string

This can be particularly useful when dealing with the results of a JsonPath query that returns an array, as these are space delimited strings of values.

{{ split <delimited-string> '<delimiter>' }}

Last updated