--- title: Response Templates description: Generate dynamic mock responses using Mustache, Velocity, or JavaScript templates with access to request data, UUIDs, timestamps, and helper objects. layout: page pageOrder: 4 section: 'Mock Server' subsection: true sitemap: priority: 0.8 changefreq: 'monthly' lastmod: 2019-11-10T08:00:00+01:00 ---

## Response Templates

MockServer supports dynamic response templates that generate responses based on request data, built-in variables, and helper objects. The following template features are supported:

- Template Formats — three template engines, each with different trade-offs:
  - Mustache — simple syntax, conditional logic, JsonPath and XPath extraction
  - Velocity — Apache Velocity engine with conditionals, loops, math, and JSON/XML body parsing
  - JavaScript — full ES2023+ JavaScript via the GraalVM Polyglot engine (bundled)
- Templates in JSON Initializer Files — defining templates in JSON expectation files
- Response Template Testing — test templates locally using `ResponseTemplateTester`
- Request Model Variables — access request fields (method, path, headers, body, etc.) in templates
- Multi-Value And Single Value Maps — access headers, parameters, and cookies by key, entry set, values, or key set
- Dynamic Model Variables — timestamps, UUIDs, random integers, and random bytes
- Template Helper Objects — rich helper objects available in all template formats:
  - JWT Helper — generate signed JWTs and JWKS for testing OAuth2/OIDC flows
  - String Helper — trim, capitalize, URL/Base64 encode/decode, substring, replace
  - JSON Transform Helper — merge, sort, extract fields, add/remove elements, pretty-print
  - Date Helper — date formatting, arithmetic, and epoch conversion
  - Calc Helper — random numbers, rounding, min/max, abs, ceil/floor, number formatting

## Templates in JSON Initializer Files

When defining response templates in JSON expectation initializer files (loaded via MOCKSERVER_INITIALIZATION_JSON_PATH), newlines within template strings must be represented as \\n because JSON does not support multi-line string values. For example:

    {
      "httpRequest": {
        "path": "/some/path"
      },
      "httpResponseTemplate": {
        "templateType": "MUSTACHE",
        "template": "{ 'statusCode': 200, 'body': 'line1\\nline2' }"
      }
    }

Complex multi-line templates can become difficult to read and maintain in JSON format. For templates with significant logic or formatting, consider using a class-based ExpectationInitializer instead. A Java class initializer allows you to define templates as normal multi-line strings and provides full IDE support for editing and debugging.

See initializing expectations for details on both JSON and class-based initializers.

## Response Template Testing

To test response templates locally is it possible to use the org.mockserver.templates.ResponseTemplateTester for fast feedback and iteration

mustache templates can be tested locally as follows:

    // inputs
    String template = "{\n" +
        "    'statusCode': 200,\n" +
        "    'body': \"{'method': '{{ request.method }}', 'path': '{{ request.path }}', 'headers': '{{ request.headers.host.0 }}'}\"\n" +
        "}";
    HttpRequest request = request()
        .withPath("/somePath")
        .withMethod("POST")
        .withHeader(HOST.toString(), "mock-server.com")
        .withBody("some_body");

    // execute
    HttpResponse httpResponse = ResponseTemplateTester.testMustacheTemplate(template, request);

    // result
    System.out.println("httpResponse = " + httpResponse);

velocity templates can be tested locally as follows:

    // inputs
    String template = "{\n" +
        "    'statusCode': 200,\n" +
        "    'body': \"{'method': '$request.method', 'path': '$request.path', 'headers': '$request.headers.host[0]'}\"\n" +
        "}";
    HttpRequest request = request()
        .withPath("/somePath")
        .withMethod("POST")
        .withHeader(HOST.toString(), "mock-server.com")
        .withBody("some_body");

    // execute
    HttpResponse httpResponse = ResponseTemplateTester.testVelocityTemplate(template, request);

    // result
    System.out.println("httpResponse = " + httpResponse);

javascript templates can be tested locally as follows:

    // inputs
    String template = "return {\n" +
        "    'statusCode': 200,\n" +
        "    'body': '{\\'method\\': \\'' + request.method + '\\', \\'path\\': \\'' + request.path + '\\', \\'headers\\': \\'' + request.headers.host[0] + '\\'}'\n" +
        "};";
    HttpRequest request = request()
        .withPath("/somePath")
        .withMethod("POST")
        .withHeader(HOST.toString(), "mock-server.com")
        .withBody("some_body");

    // execute
    HttpResponse httpResponse = ResponseTemplateTester.testJavaScriptTemplate(template, request);

    // result
    System.out.println("httpResponse = " + httpResponse);

## Request Model Variables

All templates formats have access to the following request fields

- method

  mustache: | `{{ request.method }}`

  velocity: | `$!request.method`

  javascript: | `request.method`

- path

  mustache: | `{{ request.path }}`

  velocity: | `$!request.path`

  javascript: | `request.path`

- path parameters (see below for multi-value map access patterns)

  mustache: | `{{ request.pathParameters.<key>.<index> }}`

  velocity: | `$!request.pathParameters[<key>][<index>]`

  javascript: | `request.pathParameters[<key>][<index>]`

- query string parameters (see below for multi-value map access patterns)

  mustache: | `{{ request.queryStringParameters.<key>.<index> }}`

  velocity: | `$!request.queryStringParameters[<key>][<index>]`

  javascript: | `request.queryStringParameters[<key>][<index>]`

- headers (see below for multi-value map access patterns)

  mustache: | `{{ request.headers.<key>.<index> }}`

  velocity: | `$!request.headers[<key>][<index>]`

  javascript: | `request.headers[<key>][<index>]`

- cookies (see below for single-value map access patterns)

  mustache: | `{{ request.cookies.<key> }}`

  velocity: | `$!request.cookies[<key>]`

  javascript: | `request.cookies[<key>]`

- body

  `request.body` returns the raw request body as a string. To access individual fields within a JSON body, use JsonPath (Mustache), `$json.parse()` (Velocity), or `JSON.parse()` (JavaScript) as shown in the examples below.

  mustache: | `{{ request.body }}`

  velocity: | `$!request.body`

  javascript: | `request.body`

- secure

  mustache: | `{{ request.secure }}`

  velocity: | `$!request.secure`

  javascript: | `request.secure`

- client certificate chain

  During TLS connections MockServer requests clients to optionally present certificates i.e. optional mTLS.
  If the client presents certificates this field is populated with a list of the clients certificates.
  Each item in the list contains the following fields:

  - issuerDistinguishedName as a `string`
  - subjectDistinguishedName as a `string`
  - serialNumber as a `string`
  - signatureAlgorithmName as a `string`
  - certificate as a `java.security.cert.X509Certificate`

  mustache: | `{{ request.clientCertificateChain }}`

  velocity: | `$!request.clientCertificateChain`

  javascript: | `request.clientCertificateChain`

- remote address

  The address of the TCP connection to MockServer; typically the client's address, unless there is a NAT device or load balancer between the client and MockServer.

  mustache: | `{{ request.remoteAddress }}`

  velocity: | `$!request.remoteAddress`

  javascript: | `request.remoteAddress`

- keep alive

  True is the client requested HTTP keep alive.

  mustache: | `{{ request.keepAlive }}`

  velocity: | `$!request.keepAlive`

  javascript: | `request.keepAlive`

## Request Multi-Value And Single Value Maps

The `request` variable contains the follow multi-value maps fields:

- `request.headers`
- `request.pathParameters`
- `request.queryStringParameters`

The `request` variable contains the follow single-value maps fields:

- `request.cookies`

These multi-value or single-value maps can be accessed in the following ways:

- values by key

  mustache: | `{{ request.headers.<key>.<index> }}` `{{ request.queryStringParameters.<key>.<index> }}` `{{ request.headers.<key>.<index> }}`

  velocity: | `$!request.pathParameters[<key>][<index>]` `$!request.queryStringParameters[<key>][<index>]` `$!request.headers[<key>][<index>]`

  javascript: | `request.pathParameters[<key>][<index>]` `request.queryStringParameters[<key>][<index>]` `request.headers[<key>][<index>]`

- entries as set

  each entry has a `key` and a `value` field
  for multi-value maps the `value` is a list
  for single-value maps the `value` is a string

  mustache: | `{{ request.pathParameters.entrySet }}` `{{ request.queryStringParameters.entrySet }}` `{{ request.headers.entrySet }}`

  velocity: | `$!request.pathParameters.entrySet` `$!request.queryStringParameters.entrySet` `$!request.headers.entrySet`

  javascript: | not available

- values as list

  mustache: | `{{ request.pathParameters.values }}` `{{ request.queryStringParameters.values }}` `{{ request.headers.values }}`

  velocity: | `$!request.pathParameters.values` `$!request.queryStringParameters.values` `$!request.headers.values`

  javascript: | `for (pathParameterKey in request.pathParameters) { var values = request.pathParameters[pathParameterKey]; }` `for (queryStringParameterKey in request.queryStringParameters) { var values = request.queryStringParameters[queryStringParameterKey]; }` `for (headerKey in request.headers) { var values = request.headers[headerKey]; }`

- keys as set

  mustache: | `{{ request.pathParameters.keySet }}` `{{ request.queryStringParameters.keySet }}` `{{ request.headers.keySet }}`

  velocity: | `$!request.pathParameters.keySet` `$!request.queryStringParameters.keySet` `$!request.headers.keySet`

  javascript: | `for (pathParameterKey in request.pathParameters) { // ... }` `for (queryStringParameterKey in request.queryStringParameters) { // ... }` `for (headerKey in request.headers) { // ... }`

## Dynamic Model Variables

All templates formats also have access to the following built-in dynamic variables. They return unique values each time they are used.

Tip: for deterministic testing, you can freeze or control the server clock so that date/time variables (`now_iso_8601`, `now_epoch`, `now_rfc_1123`) and the `dates` helper return predictable values.

- date & time in ISO-8601 i.e. 2011-12-03T10:15:30Z

  mustache: | `{{ now_iso_8601 }}`

  velocity: | `$!now_iso_8601`

  javascript: | `now_iso_8601`

- unix epoch, the number of seconds that have elapsed since January 1, 1970

  mustache: | `{{ now_epoch }}`

  velocity: | `$!now_epoch`

  javascript: | `now_epoch`

- date & time in RFC 1123 i.e. Tue, 3 Jun 2008 11:05:30 GMT

  mustache: | `{{ now_rfc_1123 }}`

  velocity: | `$!now_rfc_1123`

  javascript: | `now_rfc_1123`

- uuid as string

  mustache: | `{{ uuid }}`

  velocity: | `$!uuid`

  javascript: | `uuid`

- random integer between 0 and 9 inclusive

  mustache: | `{{ rand_int_10 }}`

  velocity: | `$!rand_int_10`

  javascript: | `rand_int_10`

- random integer between 0 and 99 inclusive

  mustache: | `{{ rand_int_100 }}`

  velocity: | `$!rand_int_100`

  javascript: | `rand_int_100`

- random data 16 bytes long

  mustache: | `{{ rand_bytes_16 }}`

  velocity: | `$!rand_bytes_16`

  javascript: | `rand_bytes_16`

- random data 32 bytes long

  mustache: | `{{ rand_bytes_32 }}`

  velocity: | `$!rand_bytes_32`

  javascript: | `rand_bytes_32`

- random data 64 bytes long

  mustache: | `{{ rand_bytes_64 }}`

  velocity: | `$!rand_bytes_64`

  javascript: | `rand_bytes_64`

- random data 128 bytes long

  mustache: | `{{ rand_bytes_128 }}`

  velocity: | `$!rand_bytes_128`

  javascript: | `rand_bytes_128`

## Template Helper Objects

In addition to the simple dynamic variables above, all template formats have access to helper objects that provide rich functionality for string manipulation, JSON processing, date/time arithmetic, math operations, JWT generation, and realistic fake data generation. These helpers are accessed as objects with methods.

### JWT Helper (`jwt`)

Generates signed JSON Web Tokens (JWTs) and JSON Web Key Sets (JWKS) for testing OAuth2/OIDC flows. Tokens are signed with RSA-256 using an auto-generated key pair.

Method | Description | Example Output
--- | --- | ---
`jwt.generate()` | Generate a JWT with default claims (sub, iss, aud, iat, exp) | `eyJhbGciOiJSUzI1NiJ9...`
`jwt.generate(claims)` | Generate a JWT with custom claims (Velocity/JS only) | `eyJhbGciOiJSUzI1NiJ9...`
`jwt.jwks()` | Return the JWKS (public key set) for verifying tokens | `{"keys":[{"kty":"RSA",...}]}`

Usage examples:

- Mustache: `{{ jwt }}` (generates a default JWT) or `{{ jwt.jwks }}`
- Velocity: `$jwt.generate()` or `$jwt.jwks()`
- JavaScript: `jwt.generate()` or `jwt.jwks()`

### String Helper (`strings`)

Provides string manipulation functions useful for transforming request data in response templates.

Method | Description | Example
--- | --- | ---
`strings.trim(value)` | Remove leading and trailing whitespace | `strings.trim(" hello ")` → `"hello"`
`strings.capitalize(value)` | Capitalize the first letter | `strings.capitalize("hello")` → `"Hello"`
`strings.uppercase(value)` | Convert to uppercase | `strings.uppercase("hello")` → `"HELLO"`
`strings.lowercase(value)` | Convert to lowercase | `strings.lowercase("HELLO")` → `"hello"`
`strings.urlEncode(value)` | URL-encode a string | `strings.urlEncode("a=b")` → `"a%3Db"`
`strings.urlDecode(value)` | URL-decode a string | `strings.urlDecode("a%3Db")` → `"a=b"`
`strings.base64Encode(value)` | Base64-encode a string | `strings.base64Encode("hello")` → `"aGVsbG8="`
`strings.base64Decode(value)` | Base64-decode a string | `strings.base64Decode("aGVsbG8=")` → `"hello"`
`strings.substringBefore(value, sep)` | Get substring before the first occurrence of separator | `strings.substringBefore("a-b", "-")` → `"a"`
`strings.substringAfter(value, sep)` | Get substring after the first occurrence of separator | `strings.substringAfter("a-b", "-")` → `"b"`
`strings.length(value)` | Return the length of a string | `strings.length("hello")` → `5`
`strings.contains(value, search)` | Check if a string contains a substring | `strings.contains("hello", "ell")` → `true`
`strings.replace(value, target, replacement)` | Replace all occurrences of target with replacement | `strings.replace("hello", "l", "r")` → `"herro"`

Usage examples:

- Velocity: `$strings.uppercase($!request.method)`
- JavaScript: `strings.base64Encode(request.body)`

### JSON Transform Helper (`jsonTransform`)

Provides JSON manipulation functions for merging, sorting, and extracting data from JSON strings. Named `jsonTransform` to avoid collision with Velocity's built-in `$json` (JsonTool).

Method | Description | Example
--- | --- | ---
`jsonTransform.merge(json1, json2)` | Merge two JSON objects (json2 fields overwrite json1) | `jsonTransform.merge('{"a":1}', '{"b":2}')` → `'{"a":1,"b":2}'`
`jsonTransform.sort(jsonArray, field)` | Sort a JSON array of objects by a field | `jsonTransform.sort('[{"n":"b"},{"n":"a"}]', "n")`
`jsonTransform.arrayAdd(jsonArray, element)` | Add an element to a JSON array | `jsonTransform.arrayAdd('[1,2]', '3')` → `'[1,2,3]'`
`jsonTransform.remove(json, fieldName)` | Remove a field from a JSON object | `jsonTransform.remove('{"a":1,"b":2}', "a")` → `'{"b":2}'`
`jsonTransform.prettyPrint(json)` | Pretty-print a JSON string | `jsonTransform.prettyPrint('{"a":1}')`
`jsonTransform.field(json, fieldName)` | Extract a single field value from a JSON object | `jsonTransform.field('{"name":"test"}', "name")` → `"test"`
`jsonTransform.size(jsonArray)` | Return the number of elements in a JSON array | `jsonTransform.size('[1,2,3]')` → `3`

Usage examples:

- Velocity: `$jsonTransform.field($!request.body, "username")`
- JavaScript: `jsonTransform.merge(request.body, '{"status":"processed"}')`

### Date Helper (`dates`)

Provides date/time arithmetic and formatting functions. All times are UTC-based.

Method | Description | Example Output
--- | --- | ---
`dates.format(pattern)` | Format current time with a pattern (e.g., `yyyy-MM-dd`) | `"2026-05-11"`
`dates.plusSeconds(n)` | Current time plus n seconds (ISO-8601) | `"2026-05-11T10:15:30Z"`
`dates.plusMinutes(n)` | Current time plus n minutes (ISO-8601) | `"2026-05-11T10:20:00Z"`
`dates.plusHours(n)` | Current time plus n hours (ISO-8601) | `"2026-05-11T11:15:00Z"`
`dates.plusDays(n)` | Current time plus n days (ISO-8601) | `"2026-05-12T10:15:00Z"`
`dates.minusSeconds(n)` | Current time minus n seconds (ISO-8601) |
`dates.minusMinutes(n)` | Current time minus n minutes (ISO-8601) |
`dates.minusHours(n)` | Current time minus n hours (ISO-8601) |
`dates.minusDays(n)` | Current time minus n days (ISO-8601) |
`dates.epochSeconds()` | Current time as Unix epoch seconds | `1747048530`
`dates.epochMillis()` | Current time as Unix epoch milliseconds | `1747048530000`
`dates.epochSecondsPlus(n)` | Epoch seconds plus n seconds | `"1747048590"`
`dates.epochSecondsMinus(n)` | Epoch seconds minus n seconds | `"1747048470"`

Usage examples:

- Velocity: `$dates.plusHours(1)` (token expiry 1 hour from now)
- JavaScript: `dates.format("yyyy-MM-dd")`
- Mustache: `{{ dates }}` (outputs current ISO-8601 timestamp via toString)

### Calc Helper (`calc`)

Provides mathematical functions for generating random numbers, rounding, and formatting. Named `calc` to avoid collision with Velocity's built-in `$math` (MathTool).

Method | Description | Example
--- | --- | ---
`calc.randomInt(min, max)` | Random integer between min and max (inclusive) | `calc.randomInt(1, 100)` → `42`
`calc.randomDouble()` | Random double between 0.0 and 1.0 | `0.7312...`
`calc.randomDouble(min, max)` | Random double between min and max | `calc.randomDouble(1.0, 5.0)`
`calc.abs(value)` | Absolute value | `calc.abs(-5)` → `5`
`calc.min(a, b)` | Minimum of two integers | `calc.min(3, 7)` → `3`
`calc.max(a, b)` | Maximum of two integers | `calc.max(3, 7)` → `7`
`calc.round(value, scale)` | Round to specified decimal places | `calc.round(3.14159, 2)` → `3.14`
`calc.format(value, pattern)` | Format a number with a DecimalFormat pattern | `calc.format(1234.5, "#,##0.00")` → `"1,234.50"`
`calc.ceil(value)` | Round up to nearest integer | `calc.ceil(3.1)` → `4.0`
`calc.floor(value)` | Round down to nearest integer | `calc.floor(3.9)` → `3.0`

Usage examples:

- Velocity: `$calc.randomInt(1, 1000)`
- JavaScript: `calc.round(calc.randomDouble(0.0, 100.0), 2)`

### Faker Helper (`faker`)

Generates realistic fake data for names, addresses, emails, phone numbers, and 250+ other categories using DataFaker. A single shared `Faker` instance is exposed as `faker` in all template engines. The instance is thread-safe and produces random values on each invocation.

Expression | Description | Example Output
--- | --- | ---
`faker.name().firstName()` | Random first name | `"Emory"`
`faker.name().lastName()` | Random last name | `"Johnson"`
`faker.name().fullName()` | Random full name | `"Dr. Jane Smith"`
`faker.internet().emailAddress()` | Random email address | `"john.doe@example.com"`
`faker.internet().url()` | Random URL | `"https://www.example.com"`
`faker.address().city()` | Random city name | `"Brittneymouth"`
`faker.address().streetAddress()` | Random street address | `"123 Main St"`
`faker.address().zipCode()` | Random ZIP/postal code | `"90210"`
`faker.phoneNumber().cellPhone()` | Random phone number | `"(555) 123-4567"`
`faker.lorem().sentence()` | Random sentence of text | `"Lorem ipsum dolor sit amet."`
`faker.number().numberBetween(1, 100)` | Random integer in range | `42`
`faker.company().name()` | Random company name | `"Acme Corp"`

Usage examples:

- Velocity: `$faker.name().firstName()` or `$faker.internet().emailAddress()`
- Mustache: `{{ faker.name.firstName }}` or `{{ faker.internet.emailAddress }}`
- JavaScript: `faker.name().firstName()` or `faker.internet().emailAddress()`

The full list of available providers (name, address, internet, company, finance, medical, etc.) is documented in the DataFaker providers reference.

## Mustache Response Templates

The following shows a basic example for a mustache format response template

    new ClientAndServer(1080)
        .when(request().withPath("/some/path"))
        .respond(
            template(
                HttpTemplate.TemplateType.MUSTACHE,
                "{\n" +
                    "     'statusCode': 200,\n" +
                    "     'cookies': {\n" +
                    "          'session': '{{ request.headers.Session-Id.0 }}'\n" +
                    "     },\n" +
                    "     'headers': {\n" +
                    "          'Client-User-Agent': [ '{{ request.headers.User-Agent.0 }}' ]\n" +
                    "     },\n" +
                    "     'body': '{{ request.body }}'\n" +
                    "}"
            )
        );

### Mustache Syntax

#### Variables

In mustache a variable is referenced using double braces, for example, `{{ request.method }}` will print the method field of the request variable.

`{{ name }}` will try to find the name key in the current model context; which can be changed, using sections, as described below.

If no matching field is found an empty string will be returned.

The following basic template example demonstrates using multiple variables:

    {
      'statusCode': 200,
      'body': {
        'method': '{{ request.method }}',
        'path': '{{ request.path }}',
        'headers': '{{ request.headers.host.0 }}'
      }
    }

#### Sections

Sections have the following uses:

- to change the model context
- as an if-else-statement
- to loop over arrays or iterables

A section begins with a tag starting with a pound and ends with a matching tag starting with a slash.

For example `{{#request.cookies}}` starts a request.cookies section and `{{/request.cookies}}` closes the section.

How a section behaves depends on the section's model variable as follows

- boolean values enable or disable the section like an if-statement; with unresolvable variables, null variables or empty strings all being treated as false
- arrays, iterators, and iterable variables cause the section to loop over each item; with empty collections never executing the section
- other objects result in a single execution of the section using the section's model variable as the context

The following example template demonstrates using a section to iterate the entrySet in the header map:

    {
      'statusCode': 200,
      'body': "{'headers': '{{#request.headers.entrySet}}{{ key }}={{ value.0 }} {{/request.headers.entrySet}}'}"
    }

And produces the following example output:

    {
      "statusCode" : 200,
      "body" : "{'headers': 'host=mock-server.com content-type=plain/text '}"
    }

#### Inverted Sections

An inverted section begins with a tag starting with a caret and ends with a matching tag starting with a slash.

For example `{{^-first}}` starts a -first section and `{{/-first}}` closes the section. This section therefore applies for all items in a list except the first item.

Inverted sections render once based on the inverse value of the key, they will be rendered if the key doesn't exist, is false, is an empty string, or is an empty list.

The following example template demonstrates using a section to iterate the entrySet in the header map using an inverted section and the special variable -first to add commas before all headers except the first:

    {
      'statusCode': 200,
      'body': "{'headers': [{{#request.headers.entrySet}}{{^-first}}, {{/-first}}'{{ key }}={{ value.0 }}'{{/request.headers.entrySet}}]}"
    }

And produces the following example output:

    {
      "statusCode" : 200,
      "body" : "{'headers': ['host=mock-server.com', 'content-type=plain/text']}"
    }

#### Special Variables

#### this

`this` refers to the context object itself such as the current item when iterating over a collection

#### -first and -last

You can use the special variables `-first` and `-last` when using collections.

`-first` resolves to true when inside a section on the first iteration, it resolves to false at all other times. It resolves to false for sections with a singleton value rather a collection.

`-last` resolves to true when inside a section on the last iteration, it resolves to false at all other times.

#### -index

The `-index` special variable resolves to 1 for the first iteration, 2 for the second so on. It resolves to 0 at all other times including sections with a singleton value rather a collection.

The following example template demonstrates using this and -first to list header values

    {
        'statusCode': 200,
        'body': "{'headers': [{{#request.headers.values}}{{^-first}}, {{/-first}}'{{ this.0 }}'{{/request.headers.values}}]}"
    }

And produces the following example output:

    {
      "statusCode" : 200,
      "body" : "{'headers': ['mock-server.com', 'plain/text']}"
    }

The following example template demonstrates using this, -first and -index to list header keys

    {
        'statusCode': 200,
        'body': "{'headers': [{{#request.headers.keySet}}{{^-first}}, {{/-first}}'{{ -index }}:{{ this }}'{{/request.headers.keySet}}]}"
    }

And produces the following example output:

    {
      "statusCode" : 200,
      "body" : "{'headers': ['1:host', '2:content-type']}"
    }

#### JsonPath

It is possible to use JsonPath expressions to extract values from request bodies containing JSON with a `{{#jsonPath}}` section, follow by a `{{#jsonPathResult}}` section

For details of the full JsonPath syntax please see github.com/json-path

The following example template demonstrates using `{{#jsonPath}}` follow by `{{#jsonPathResult}}` to extract a list and single value from a request body:

    {
        'statusCode': 200,
        'body': "{'titles': {{#jsonPath}}$.store.book{{/jsonPath}}[{{#jsonPathResult}}{{^-first}}, {{/-first}}'{{title}}'{{/jsonPathResult}}], 'bikeColor': '{{#jsonPath}}$.store.bicycle.color{{/jsonPath}}{{jsonPathResult}}'}"
    }

In this example the first JsonPath expression `$.store.book` returns a list of objects which is iterated over in the section `{{#jsonPathResult}}`.

The second JsonPath expression `$.store.bicycle.color` returns a single value which is returned using the variable tag `{{jsonPathResult}}`.

Given the following request:

    {
      "path" : "/somePath",
      "body" : {
        "store" : {
          "book" : [ {
            "category" : "reference",
            "author" : "Nigel Rees",
            "title" : "Sayings of the Century",
            "price" : 18.95
          }, {
            "category" : "fiction",
            "author" : "Herman Melville",
            "title" : "Moby Dick",
            "isbn" : "0-553-21311-3",
            "price" : 8.99
          } ],
          "bicycle" : {
            "color" : "red",
            "price" : 19.95
          }
        },
        "expensive" : 10
      }
    }

The example produces:

    {
      "statusCode" : 200,
      "body" : "{'titles': ['Sayings of the Century', 'Moby Dick'], 'bikeColor': 'red'}"
    }

#### XPath

It is possible to use XPath expressions to extract values from request bodies containing XML with a `{{#xPath}}` section.

The `{{#xPath}}` section only supports outputting the result of the XPath expression as a string, if an XML fragment is matched the string content of all the elements is printed.

For a quick summary the XPath syntax please see w3schools, for details of the full XPath syntax please see www.w3.org

The following example template demonstrates using `{{#xPath}}` to multiple items from a request body:

    {
        'statusCode': 200,
        'body': "{'titles': ['{{#xPath}}/store/book/title{{/xPath}}', '{{#xPath}}//book[2]/title{{/xPath}}'], 'bikeColor': '{{#xPath}}//bicycle/color{{/xPath}}'}"
    }

Given a request with the following xml body:

    <?xml version="1.0" encoding="UTF-8" ?>
    <store>
      <book>
        <category>reference</category>
        <author>Nigel Rees</author>
        <title>Sayings of the Century</title>
        <price>18.95</price>
      </book>
      <book>
        <category>fiction</category>
        <author>Herman Melville</author>
        <title>Moby Dick</title>
        <isbn>0-553-21311-3</isbn>
        <price>8.99</price>
      </book>
      <bicycle>
        <color>red</color>
        <price>19.95</price>
      </bicycle>
      <expensive>10</expensive>
    </store>

The example produces:

    {
      "statusCode" : 200,
      "body" : "{'titles': ['Sayings of the Century', 'Moby Dick'], 'bikeColor': 'red'}"
    }

## Velocity Response Templates

The following shows a basic example for a Velocity format response template

    new ClientAndServer(1080)
        .when(request().withPath("/some/path"))
        .respond(
            template(
                HttpTemplate.TemplateType.VELOCITY,
                "{\n" +
                    "     'statusCode': 200,\n" +
                    "     'cookies': { \n" +
                    "          'session': '$!request.headers['Session-Id'][0]'\n" +
                    "     },\n" +
                    "     'headers': {\n" +
                    "          'Client-User-Agent': [ '$!request.headers['User-Agent'][0]' ]\n" +
                    "     },\n" +
                    "     'body': '$!request.body'\n" +
                    "}"
            )
        );

### Velocity Syntax

For full Velocity syntax see: Velocity User Guide the following section provide a basic summary and examples of Velocity syntax.

#### Variables

In velocity a variable is referenced using a dollar, for example, `$request.method` will print the method field of the request variable.

`$name` will try to find the name variable in the current model.

If no matching variable is found for the variable expression the expression is printed, unless a quiet expression notation is used as follows `$!name`

The following basic template example demonstrates using multiple variables:

    {
      'statusCode': 200,
      'body': {
        'method': '#!request.method',
        'path': '#!request.path',
        'headers': '#!request.headers.host.0'
      }
    }

Methods can also be called on variables, for example, `$request.getMethod()` will call the getMethod() method of the request variable.

New variables can be defined using a `#set` directive, for example, `#set ($message="Hello World")` will create a new variables call message.

#### Conditionals

Conditional expressions are possible using `#if`, `#elseif` and `#else` directives, as follows:

    #if($request.method == 'POST' && $request.path == '/somePath')
        {
            'statusCode': 200,
            'body': "{'name': 'value'}"
        }
    #else
        {
            'statusCode': 406,
            'body': "$!request.body"
        }
    #end

#### Loops

Loops are possible using the `#foreach` directives, as follows:

    {
        'statusCode': 200,
        'body': "{'headers': [#foreach( $value in $request.headers.values() )'$value[0]'#if( $foreach.hasNext ), #end#end]}"
    }

The example produces:

    {
      "statusCode" : 200,
      "body" : "{'headers': ['mock-server.com', 'plain/text']}"
    }

#### Mathematical

In addition to the dynamic model variables it is possible to perform basic mathematical operations, as follows:

    #set($percent = $number / 100)
    #set($remainder = $dividend % $divisor)

A range operator is also supported which can be useful in conjunction with `#set` and `#foreach`

    #set($array = [0..10])
    #foreach($item in $arr)
        $item
    #end

For additional mathematical functionality it is also possible to use the MathTool or NumberTool in velocity response templates.

    #set($power = $math.pow($number, 2))
    #set($max = $math.max($number, 10))

#### Json Bodies

The JsonTool can be used to help parse JSON bodies, as follows:

    #set($jsonBody = $json.parse($!request.body))

    {
        'statusCode': 200,
        'body': "{'titles': [#foreach( $book in $jsonBody.store.book )'$book.title'#if( $foreach.hasNext ), #end#end], 'bikeColor': '$jsonBody.store.bicycle.color'}"
    }

Given the following request:

    {
      "path" : "/somePath",
      "body" : {
        "type" : "JSON",
        "json" : {
          "store" : {
            "book" : [ {
              "category" : "reference",
              "author" : "Nigel Rees",
              "title" : "Sayings of the Century",
              "price" : 18.95
            }, {
              "category" : "fiction",
              "author" : "Herman Melville",
              "title" : "Moby Dick",
              "isbn" : "0-553-21311-3",
              "price" : 8.99
            } ],
            "bicycle" : {
              "color" : "red",
              "price" : 19.95
            }
          },
          "expensive" : 10
        }
      }
    }

The example produces:

    {
      "statusCode" : 200,
      "body" : "{'titles': ['Sayings of the Century', 'Moby Dick'], 'bikeColor': 'red'}"
    }

#### XML Bodies

The XmlTool can be used to help parse XML bodies, execute XPath and XML traversal.

The following example shows how to use XmlTool for XPath:

    #set($xmlBody = $xml.parse($!request.body))

    {
        'statusCode': 200,
        'body': "{'key': '$xml.find('/element/key/text()')', 'value': '$xml.find('/element/value/text()')'}"
    }

Given the following request:

    {
      "path" : "/somePath",
      "body" : "<element><key>some_key</key><value>some_value</value></element>"
    }

The example produces:

    {
      "statusCode" : 200,
      "body" : "{'key': 'some_key', 'value': 'some_value'}"
    }

#### Velocity Tools

The following velocity tools are available for velocity response templates:

- CollectionTool
- ComparisonDateTool
- DisplayTool
- EscapeTool
- MathTool
- NumberTool
- JsonTool
- XmlTool

## JavaScript Response Templates

The following shows a basic example for a JavaScript format response template

    new ClientAndServer(1080)
        .when(request().withPath("/some/path"))
        .respond(
            template(
                HttpTemplate.TemplateType.JAVASCRIPT,
                "return {\n" +
                    "     'statusCode': 200,\n" +
                    "     'cookies': {\n" +
                    "          'session' : request.headers['session-id'][0]\n" +
                    "     },\n" +
                    "     'headers': {\n" +
                    "          'Client-User-Agent': request.headers['User-Agent']\n" +
                    "     },\n" +
                    "     'body': request.body\n" +
                    "};"
            )
        );

### JavaScript Syntax

All javascript response templates should return the response as an object as shown in the example above.

JavaScript response templates support ES6 syntax for Java 9 to 14, for a summary of ES6 syntax see w3schools.

JavaScript response templates support ES5 syntax for Java 8, for a summary of ES5 syntax see w3schools.

#### JavaScript Engine Support

MockServer uses the GraalVM Polyglot JavaScript engine for JavaScript templates. The engine is bundled with all official Docker images and the standalone JAR. It supports ES2023+ syntax, including template literals, async/await, destructuring, optional chaining, and the full modern JavaScript language.

If you are embedding MockServer as a library and need JavaScript templating, add `org.graalvm.polyglot:polyglot` and `org.graalvm.polyglot:js` (both at version 25.0.3 or later) to your classpath. Nashorn (`org.openjdk.nashorn:nashorn-core`) is no longer supported; the JSR-223 bridge was dropped in GraalJS 25.x and Nashorn was removed from MockServer.

#### Variables

In javascript a variable is referenced directly, for example, `request.method` will return the method field of the request variable.

The following basic template example demonstrates using multiple variables:

    return {
        'statusCode': 200,
        'body': '{\'method\': \'' + request.method + '\', \'path\': \'' + request.path + '\', \'header\': \'' + request.headers.host[0] + '\'}'
    };

#### Conditionals

Conditional expressions are possible, as follows:

    if (request.method === 'POST' && request.path === '/somePath') {
        return {
            'statusCode': 200,
            'body': JSON.stringify({name: 'value'})
        };
    } else {
        return {
            'statusCode': 406,
            'body': request.body
        };
    }

#### Loops

Looping is possible, as follows:

    var headers = '';
    for (header in request.headers) {
      headers += '\'' + request.headers[header] + '\', ';
    }
    return {
        'statusCode': 200,
        'body': '{\'headers\': [' + headers.slice(0, -2) + ']}'
    };

The example produces:

    {
      "statusCode" : 200,
      "body" : "{'headers': ['mock-server.com', 'plain/text']}"
    }