Response Templating

Response headers and bodies, as well as proxy URLs, can optionally be rendered using Handlebars templates. This enables attributes of the request to be used in generating the response e.g. to pass the value of a request ID header as a response header or render an identifier from part of the URL in the response body.

Enabling response templating

When starting WireMock programmatically, response templating can be enabled by adding ResponseTemplateTransformer as an extension e.g.

@Rule
public WireMockRule wm = new WireMockRule(options()
    .extensions(new ResponseTemplateTransformer(false))
);

The boolean constructor parameter indicates whether the extension should be applied globally. If true, all stub mapping responses will be rendered as templates prior to being served.

Otherwise the transformer will need to be specified on each stub mapping by its name response-template:

Java

wm.stubFor(get(urlPathEqualTo("/templated"))
  .willReturn(aResponse()
      .withBody("{{request.path.[0]}}")
      .withTransformers("response-template")));

JSON

{
    "request": {
        "urlPath": "/templated"
    },
    "response": {
        "body": "{{request.path.[0]}}",
        "transformers": ["response-template"]
    }
}

Command line parameters can be used to enable templating when running WireMock standalone.

Template caching

By default, all templated fragments (headers, bodies and proxy URLs) are cached in their compiled form for performance, since compilation can be expensive for larger templates.

The size of the cache is not limited by default, but can be a construction time:

@Rule
public WireMockRule wm = new WireMockRule(options()
    .extensions(ResponseTemplateTransformer.builder()
                                .global(false)
                                .maxCacheEntries(3L)
                                .build())
);

Setting the limit to 0 will disable caching completely.

Proxying

Templating also works when defining proxy URLs, e.g.

Java

wm.stubFor(get(urlPathEqualTo("/templated"))
  .willReturn(aResponse()
      .proxiedFrom("{{request.headers.X-WM-Proxy-Url}}")
      .withTransformers("response-template")));

JSON

{
    "request": {
        "urlPath": "/templated"
    },
    "response": {
        "proxyBaseUrl": "{{request.headers.X-WM-Proxy-Url}}",
        "transformers": ["response-template"]
    }
}

Templated body file

The body file for a response can be selected dynamically by templating the file path:

Java

wm.stubFor(get(urlPathMatching("/static/.*"))
  .willReturn(ok()
    .withBodyFile("files/{{request.pathSegments.[1]}}")));

JSON

{
  "request" : {
    "urlPathPattern" : "/static/.*",
    "method" : "GET"
  },
  "response" : {
    "status" : 200,
    "bodyFileName" : "files/{{request.pathSegments.[1]}}"
  }
}

The request model

The model of the request is supplied to the header and body templates. The following request attributes are available:

request.url - URL path and query

request.requestLine.path - URL path

request.requestLine.pathSegments.[<n>]- URL path segment (zero indexed) e.g. request.pathSegments.[2]

request.requestLine.query.<key>- First value of a query parameter e.g. request.query.search

request.requestLine.query.<key>.[<n>]- nth value of a query parameter (zero indexed) e.g. request.query.search.[5]

request.requestLine.method- request method e.g. POST

request.requestLine.host- hostname part of the URL e.g. my.example.com

request.requestLine.port- port number e.g. 8080

request.requestLine.scheme- protocol part of the URL e.g. https

request.requestLine.baseUrl- URL up to the start of the path e.g. https://my.example.com:8080

request.headers.<key>- First value of a request header e.g. request.headers.X-Request-Id

request.headers.[<key>]- Header with awkward characters e.g. request.headers.[$?blah]

request.headers.<key>.[<n>]- nth value of a header (zero indexed) e.g. request.headers.ManyThings.[1]

request.cookies.<key> - First value of a request cookie e.g. request.cookies.JSESSIONID

request.cookies.<key>.[<n>] - nth value of a request cookie e.g. request.cookies.JSESSIONID.[2]

request.body - Request body text (avoid for non-text bodies)

Values that can be one or many

A number of HTTP elements (query parameters, form fields, headers) can be single or multiple valued. The template request model and built-in helpers attempt to make this easy to work with by wrapping these in a “list or single” type that returns the first (and often only) value when no index is specified, but also support index access.

For instance, given a request URL like /multi-query?things=1&things=2&things=3 I can extract the query data in the following ways:

{{request.query.things}} // Will return 1
{{request.query.things.0}} // Will return 1
{{request.query.things.first}} // Will return 1
{{request.query.things.1}} // Will return 2
{{request.query.things.[-1]}} // Will return 2
{{request.query.things.last}} // Will return 3

Note

When using the eq helper with one-or-many values, it is necessary to use the indexed form, even if only one value is present. The reason for this is that the non-indexed form returns the wrapper type and not a String, and will therefore fail any comparison with another String value.

Handlebars helpers

All of the standard helpers (template functions) provided by the Java Handlebars implementation by jknack plus all of the string helpers and the conditional helpers are available e.g.

{{capitalize request.query.search}}

Number and assignment helpers

Variable assignment and number helpers are available:

{{#assign 'myCapitalisedQuery'}}{{capitalize request.query.search}}{{/assign}}

{{isOdd 3}}
{{isOdd 3 'rightBox'}}

{{isEven 2}}
{{isEven 4 'leftBox'}}

{{stripes 3 'row-even' 'row-odd'}}

XPath helpers

Addiionally some helpers are available for working with JSON and XML.

When the incoming request contains XML, the xPath helper can be used to extract values or sub documents via an XPath 1.0 expression. For instance, given the XML

<outer>
    <inner>Stuff</inner>
</outer>

The following will render “Stuff” into the output:

{{xPath request.body '/outer/inner/text()'}}

And given the same XML the following will render <inner>Stuff</inner>:

{{xPath request.body '/outer/inner'}}

As a convenience the soapXPath helper also exists for extracting values from SOAP bodies e.g. for the SOAP document:

<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope/">
    <soap:Body>
        <m:a>
            <m:test>success</m:test>
        </m:a>
    </soap:Body>
</soap:Envelope>

The following will render “success” in the output:

{{soapXPath request.body '/a/test/text()'}}

JSONPath helper

It is similarly possible to extract JSON values or sub documents via JSONPath using the jsonPath helper. Given the JSON

{
  "outer": {
    "inner": "Stuff"
  }
}

The following will render “Stuff” into the output:

{{jsonPath request.body '$.outer.inner'}}

And for the same JSON the following will render { "inner": "Stuff" }:

{{jsonPath request.body '$.outer'}}

Date and time helpers

A helper is present to render the current date/time, with the ability to specify the format (via Java’s SimpleDateFormat) and offset.

{{now}}
{{now offset='3 days'}}
{{now offset='-24 seconds'}}
{{now offset='1 years'}}
{{now offset='10 years' format='yyyy-MM-dd'}}

Dates can be rendered in a specific timezone (the default is UTC):

{{now timezone='Australia/Sydney' format='yyyy-MM-dd HH:mm:ssZ'}}

Pass epoch as the format to render the date as UNIX epoch time (in milliseconds), or unix as the format to render the UNIX timestamp in seconds.

{{now offset='2 years' format='epoch'}}
{{now offset='2 years' format='unix'}}

Dates can be parsed from other model elements:

{{date (parseDate request.headers.MyDate) offset='-1 days'}}

Random value helper

Random strings of various kinds can be generated:

{{randomValue length=33 type='ALPHANUMERIC'}}
{{randomValue length=12 type='ALPHANUMERIC' uppercase=true}}
{{randomValue length=55 type='ALPHABETIC'}}
{{randomValue length=27 type='ALPHABETIC' uppercase=true}}
{{randomValue length=10 type='NUMERIC'}}
{{randomValue length=5 type='ALPHANUMERIC_AND_SYMBOLS'}}
{{randomValue type='UUID'}}

String trim helper

Use the trim helper to remove whitespace from the start and end of the input:

{{trim request.headers.X-Padded-Header}}

{{#trim}}
    
    Some stuff with whitespace
     
{{/trim}}

Base64 helper

The base64 helper can be used to base64 encode and decode values:

{{base64 request.headers.X-Plain-Header}}
{{base64 request.headers.X-Encoded-Header decode=true}}

{{#base64}}
Content to encode     
{{/base64}}

{{#base64 decode=true}}
Q29udGVudCB0byBkZWNvZGUK     
{{/base64}}

URL encoding helper

The urlEncode helper can be used to URL encode and decode values:

{{urlEncode request.headers.X-Plain-Header}}
{{urlEncode request.headers.X-Encoded-Header decode=true}}

{{#urlEncode}}
Content to encode     
{{/urlEncode}}

{{#urlEncode decode=true}}
Content%20to%20decode     
{{/urlEncode}}

Form helper

The formData helper parses its input as an HTTP form, returning an object containing the individual fields as attributes. The helper takes the input string and variable name as its required parameters, with an optional urlDecode parameter indicating that values should be URL decoded. The folowing example will parse the request body as a form, then output a single field formField3:

{{formData request.body 'form' urlDecode=true}}}{{{form.formField3}}

If the form submitted has multiple values for a given field, these can be accessed by index:

{{formData request.body 'form' urlDecode=true}}}{{{form.multiValueField.1}}, {{{form.multiValueField.2}}
{{formData request.body 'form' urlDecode=true}}}{{{form.multiValueField.first}}, {{{form.multiValueField.last}}

Regular expression extract helper

The regexExtract helper supports extraction of values matching a regular expresson from a string.

A single value can be extracted like this:

{{regexExtract request.body '[A-Z]+'}}"

Regex groups can be used to extract multiple parts into an object for later use (the last parameter is a variable name to which the object will be assigned):

{{regexExtract request.body '([a-z]+)-([A-Z]+)-([0-9]+)' 'parts'}}
{{parts.0}},{{parts.1}},{{parts.2}}

Size helper

The size helper returns the size of a string, list or map:

{{size 'abcde'}}
{{size request.query.things}}

Custom helpers

Custom Handlebars helpers can be registered with the transformer on construction:

Helper<String> stringLengthHelper = new Helper<String>() {
    @Override
    public Object apply(String context, Options options) throws IOException {
        return context.length();
    }
};

@Rule
public WireMockRule wm = new WireMockRule(options()
    .extensions(new ResponseTemplateTransformer(false), "string-length", stringLengthHelper)
);