Parameter Type Description
copy An object An object specifying the request field and response token, as well as a way of selecting the value from the request field
copy.from A string or an object The name of the request field to copy from, or, if the request field is an object, then an object specifying the path to the request field. For example,
{ "from": "body" }
and
{ "from": { "query": "q" } }
are both valid.
copy.into A string The token to replace in the response with the selected request value. There is no need to specify which field in the response the token will be in; all response tokens will be replaced in all response fields. Sometimes, the request selection returns multiple values. In those cases, you can add an index to the token, while the unindexed token represents the first match. For example, if you specify
{ "into": "${NAME}" }
as your token configuration, then both ${NAME} and ${NAME}[0] will be replaced by the first match, ${NAME}[1] will be replaced by the second match, and so on.
copy.using An object The configuration needed to select values from the response
copy.using.method An string The method used to select the value(s) from the request. Allowed values are regex, xpath, and jsonpath.
copy.using.selector An string The selector used to select the value(s) from the request. For a regex, this would be the pattern, and the replacement value will be the entire match. Match groups using parentheses are supported and can be replaced using indexed tokens as described in the copy[].into description. xpath and jsonpath selectors work on XML and JSON documents. If the request value does not match the selector (including through XML or JSON parsing errors), nothing is replaced.
copy.using.ns An object For xpath selectors, the ns object maps namespace aliases to URLs
copy.using.options An object For regex selectors, the options object describes the regular expression options
copy.using.options.ignoreCase A boolean Uses a case-insensitive regular expression
copy.using.options.multiline A boolean Uses a multiline regular expression

The copy behavior supports dynamically replacing values in the response with something that comes from the request. It relies on you adding tokens of your own choosing into the response fields you want replaced. We'll look at the following examples:

Regular expressions

The following example shows multiple regular expression matches on request fields to copy into the response.

POST /imposters HTTP/1.1
Host: localhost:<%= port %>
Accept: application/json
Content-Type: application/json

{
  "port": 8585,
  "protocol": "http",
  "stubs": [
    {
      "responses": [
        {
          "is": {
            "statusCode": "${code}",
            "headers": {
              "X-Test": "${header}"
            },
            "body": "The request name was ${name}. Hello, ${name}!"
          },
          "behaviors": [
            {
              "copy": {
                "from": "path",
                "into": "${code}",
                "using": { "method": "regex", "selector": "\\d+" }
              }
            },
            {
              "copy": {
                "from": { "headers": "X-Request" },
                "into": "${header}",
                "using": { "method": "regex", "selector": ".+" }
              }
            },
            {
              "copy": {
                "from": { "query": "name" },
                "into": "${name}",
                "using": {
                  "method": "regex",
                  "selector": "MOUNT\\w+$",
                  "options": { "ignoreCase": true }
                }
              }
            }
          ]
        }
      ]
    }
  ]
}

This example shows off many of the options of the copy behavior. For example, we can plug tokens into any of the response fields (including the statusCode), and it shows how to navigate object request fields, like the name querystring parameter. It shows an example of using regular expressions options to get a case-insensitive regular expression to capture the name query parameter. It also shows matching multiple request fields using an array of copy configurations. Let's see what happens when we craft a request to match all of those selectors:

GET /statusCode/400?ignore=this&name=mountebank HTTP/1.1
Host: localhost:8585
X-REQUEST: Header value
HTTP/1.1 400 Bad Request
X-Test: Header value
Connection: close
Date: Thu, 28 Dec 2016 11:37:31 GMT
Transfer-Encoding: chunked

The request name was mountebank. Hello, mountebank!

xpath

The following example shows a simple namespaced xpath match to grab the first title field in an XML document and copy it into the BOOK response token.

POST /imposters HTTP/1.1
Host: localhost:<%= port %>
Accept: application/json
Content-Type: application/json

{
  "port": 8586,
  "protocol": "http",
  "stubs": [
    {
      "responses": [
        {
          "is": {
            "body": "Have you read BOOK?"
          },
          "behaviors": [
            {
              "copy": {
                "from": "body",
                "into": "BOOK",
                "using": {
                  "method": "xpath",
                  "selector": "//isbn:title",
                  "ns": {
                    "isbn": "http://schemas.isbn.org/ns/1999/basic.dtd"
                  }
                }
              }
            }
          ]
        }
      ]
    }
  ]
}

The ns object map is optional and can be ignored if your xpath selector doesn't depend on namespaces. It doesn't matter how many name elements exist in the XML. Without using indexed tokens, only the first match will be used:

POST /names HTTP/1.1
Host: localhost:8586

<books xmlns:isbn="http://schemas.isbn.org/ns/1999/basic.dtd">
  <book>
    <isbn:title>Game of Thrones</isbn:title>
    <isbn:summary>Dragons and political intrigue</isbn:summary>
  </book>
  <book>
    <isbn:title>Harry Potter</isbn:title>
    <isbn:summary>Dragons and a boy wizard</isbn:summary>
  </book>
  <book>
    <isbn:title>The Hobbit</isbn:title>
    <isbn:summary>A dragon and short people</isbn:summary>
  </book>
</books>
HTTP/1.1 200 OK
Connection: close
Date: Thu, 28 Dec 2016 11:37:31 GMT
Transfer-Encoding: chunked

Have you read Game of Thrones?

jsonpath

The following example translates the XML example above into JSON. To make it more interesting, we'll show it using the tcp protocol

POST /imposters HTTP/1.1
Host: localhost:<%= port %>
Accept: application/json
Content-Type: application/json

{
  "port": 8587,
  "protocol": "tcp",
  "stubs": [
    {
      "responses": [
        {
          "is": {
            "data": "Have you read BOOK?"
          },
          "behaviors": [
            {
              "copy": {
                "from": "data",
                "into": "BOOK",
                "using": {
                  "method": "jsonpath",
                  "selector": "$..title"
                }
              }
            }
          ]
        }
      ]
    }
  ]
}

Again, by default only the first match will be used:

echo '{
  "books": [
    {
      "title": "Game of Thrones",
      "summary": "Dragons and political intrigue"
    },
    {
      "title": "Harry Potter",
      "summary": "Dragons and a boy wizard"
    },
    {
      "title": "The Hobbit",
      "summary": "A dragon and short people"
    }
  ]
}' | nc localhost 8587
Have you read Game of Thrones?
DELETE /imposters/8587 HTTP/1.1 Host: localhost:<%= port %>

Indexed replacements

Finally, let's show an example that uses multiple matches for a given selector. To show that the same approach works for multiple selection methods, we'll show it for both regular expressions and jsonpath:

POST /imposters HTTP/1.1
Host: localhost:<%= port %>
Accept: application/json
Content-Type: application/json

{
  "port": 8588,
  "protocol": "http",
  "stubs": [
    {
      "responses": [
        {
          "is": {
            "body": "${BOOK}[1]: ${SUMMARY}[0]\n${BOOK}[2]: ${SUMMARY}[1]\n${BOOK}[3]: ${SUMMARY}[2]"
          },
          "behaviors": [
            {
              "copy": {
                "from": "body",
                "into": "${SUMMARY}",
                "using": {
                  "method": "jsonpath",
                  "selector": "$..summary"
                }
              }
            },
            {
              "copy": {
                "from": { "query": "books" },
                "into": "${BOOK}",
                "using": {
                  "method": "regex",
                  "selector": "([^,]+),([^,]+),(.+)$"
                }
              }
            }
          ]
        }
      ]
    }
  ]
}

Note the mismatched indexes between the two selection methods. This is because we use the standard regular expression semantics around matched groups, which is that the first element in the matches will be the entire matched expression, the second element will be the first parenthesized match group, and so on. Also note that ${SUMMARY}[0] and ${SUMMARY} will be treated identically. We'll trigger the substitutions with the following request:

POST /?books=Game%20of%20Thrones,Harry%20Potter,The%20Hobbit HTTP/1.1
Host: localhost:8588

{
  "books": [
    {
      "title": "Game of Thrones",
      "summary": "Dragons and political intrigue"
    },
    {
      "title": "Harry Potter",
      "summary": "Dragons and a boy wizard"
    },
    {
      "title": "The Hobbit",
      "summary": "A dragon and short people"
    }
  ]
}
HTTP/1.1 200 OK
Connection: close
Date: Thu, 28 Dec 2016 11:37:31 GMT
Transfer-Encoding: chunked

Game of Thrones: Dragons and political intrigue
Harry Potter: Dragons and a boy wizard
The Hobbit: A dragon and short people