Matching requests to send responses

When Traffic Parrot receives a request via any protocol or technology like HTTP, JMS, gRPC and others, it will try to simulate the system it is replacing by sending back a response to the client that sent the request.

To decide which response to send, it will go through all the request to response mappings it has available to find the response to be returned.

What is a request to response mapping?

A request to response mapping defines which response to return given a request. For example, in HTTP, you could say:

For any request to URL '/hello' that is a GET request return a response with body 'Hello World!'

The way you do that in Traffic Parrot is by using the user interface to record mappings, import them or add them manually.

Here is an example HTTP request to response mapping viewed in Traffic Parrot web user interface:
Sample HTTP request to response mapping in Traffic Parrot
All of the mappings Traffic Parrot has access to are stored on the filesystem in JSON files. Here is the same mapping you just saw above in the web user interface but now in JSON formad stored in trafficparrot-enterprise-x.y.z/mappings folder on the disk:
{
  "id" : "a6263f39-5826-48a5-a409-4d78037c303e",
  "request" : {
    "url" : "/MODApis/Api/v2/Quote/json?AAPL",
    "method" : "GET"
  },
  "response" : {
    "status" : 200,
    "body" : "{\r\n  \"Status\": \"SUCCESS\",\r\n  \"High\": 116.91,\r\n  \"MSDate\": 42664,\r\n  \"Change\": -0.46,\r\n  \"LastPrice\": 116.6,\r\n  \"Timestamp\": \"Fri Oct 21 00:00:00 UTC-04:00 2016\",\r\n  \"ChangePercentYTD\": 105.26,\r\n  \"Name\": \"Apple Inc\",\r\n  \"Open\": 116.81,\r\n  \"Volume\": 23192665,\r\n  \"Low\": 116.28,\r\n  \"ChangeYTD\": 105.26,\r\n  \"ChangePercent\": -0.3929608748,\r\n  \"MarketCap\": 628292453800\r\n}",
    "headers" : {
      "Content-Type" : "text/javascript; charset=UTF-8"
    }
  },
  "uuid" : "a6263f39-5826-48a5-a409-4d78037c303e"
}

Workflow: matching a request to find a response

After the mappings have been created, a typical workflow when Traffic Parrot is simulating a system (replaying the responses) will be:
  1. Traffic Parrot receives a request
  2. Traffic Parrot goes through the list of all mappings (for example for http it lists all files in trafficparrot-enterprise-x.y.z/mappings folder on the disk) and tries to use the request matchers in a given mapping to match the request it just received
  3. If the request received matches the request in the mapping, it returns the response defined in that same mapping
  4. If the request received does not match the request in the mapping, it tries to match the next mapping in the list of mappings
  5. If there are no mappings left to match in the list of mappings, it returns the default response indicating a mapping was not found. For example for HTTP it will return a status code 900 and response body "Traffic Parrot Virtual Service: No responses matched the given request"

Available request matchers

Traffic Parrot support matching attributes of requests using the following matchers.

For the complete cross-protocol list of every matcher and its mapping JSON options, including matchers that are not shown in the editor dropdowns, see the matchers reference further down this page.

Protocol/technology Matchers available
HTTP(S) list of HTTP(S) matchers
JMS list of JMS matchers
Native IBM MQ list of MQ matchers
gRPC list of gRPC matchers
Thrift list of Thrift matchers
Files list of files matchers

Request matcher examples

Here is a collection of matcher examples that cover typical request matching use cases.

Matches JSONPath
Use case JSON to match JSONPath
Has field that exists, even if it contains a null value
{
  "field" : null
}
$[?(@.field)]
Does not have a particular field at all
{
  "other" : "any"
}
$[?(!(@.field))]
Has field matching regular expression
{
  "name" : "John"
}
$[?(@.name =~ /^J[a-z]+$/)]
Has field not matching regular expression
{
  "name" : "Other"
}
$[?(!(@.name =~ /^J[a-z]+$/))]
Has field with value equal to
{
  "name" : "John"
}
$[?(@.name == 'John')]
Has multiple fields with value equal to
{
  "name" : "John",
  "lastName" : "Smith"
}
$[?(@.name == 'John' && @.lastName == 'Smith')]
Has field with value equal to either
{
  "name" : "Bob"
}
{
  "name" : "John"
}
$[?(@.name == 'John' || @.name == 'Bob')]
Has array containing field with value equal to
{
  "root" : {
    "items" : [
      {
        "id": "1111"
      }
    ]
  }
}
$.root[?('1' in @.items[*].id)]
Has array containing fields with values equal to
{
  "root" : {
    "items" : [
      {
        "id": "1"
      },
      {
        "id": "2"
      }
    ]
  }
}
$.root[?('1' in @.items[*].id && '2' in @.items[*].id)]
Has fields at multiple depths
{
  "id": 1,
  "items": [
    {
      "id": 2,
    }
  ]
}
$[?(@.id == 1 && 2 in @.items[*].id)]

Matchers reference

A request to response mapping uses one or more matchers to decide whether an incoming request matches. This section is the complete reference of every matcher Traffic Parrot understands in mapping JSON, together with a copy-ready example for each.

The mapping editor in the web user interface offers a subset of the available matchers through its dropdown menus — the most common ones for each protocol. Additional matchers, inherited from the bundled request-matching engine, are not shown in those dropdowns but can still be used by editing the mapping JSON directly (on disk in the mappings folder, or through the import and API surfaces). Those are listed in the JSON-only matchers section and are each labelled JSON-only.

Matchers marked Traffic Parrot extension are added by Traffic Parrot on top of the bundled engine. The remaining matchers are inherited from the bundled request-matching engine.

Where each matcher applies. Not every matcher makes sense on every protocol, so each entry below has an Applies to note. In the examples, body matchers appear inside a bodyPatterns array on the request and URL matchers appear as top-level request fields, which is how they are stored in the mapping JSON.

Editor-offered matchers

These matchers are available from the dropdown menus in the mapping editor. The Applies to column shows which editor surfaces offer each one. A matcher may still be usable in mapping JSON for a protocol where the editor does not list it, but the column reflects what the editor exposes.

Matcher (JSON key) Description Applies to
any / anythingMatches any body, including an empty one. The editor shows this as any; in JSON the HTTP and gRPC forms use anything via an empty body-patterns list, while the messaging form uses the anything key.HTTP body, JMS, Native IBM MQ, gRPC payload
equalToExact, character-for-character string equality.HTTP body, JMS, Native IBM MQ, File name
containsThe body contains the given substring.HTTP body, JMS, Native IBM MQ, gRPC payload, File name
doesNotContainThe body does not contain the given substring.HTTP body, JMS, Native IBM MQ, gRPC payload, File name
matchesThe body matches the given regular expression.HTTP body, JMS, Native IBM MQ, gRPC payload, File name
doesNotMatchThe body does not match the given regular expression.HTTP body, JMS, Native IBM MQ, gRPC payload, File name
equalToJsonSemantic JSON equality — the body and the expected value represent the same JSON document regardless of formatting.HTTP body, JMS, Native IBM MQ, gRPC payload
matchesJson Traffic Parrot extensionSemantic JSON comparison with the expected value supplied as inline JSON rather than an escaped string.HTTP body, JMS, Native IBM MQ, gRPC payload
matchesJsonPathA JSONPath expression selects a value from the body; the request matches when the expression resolves.HTTP body, JMS, Native IBM MQ, gRPC payload
equalToXmlSemantic XML equality, ignoring insignificant whitespace and attribute order.HTTP body, JMS, Native IBM MQ
matchesXml Traffic Parrot extensionMatches an XML body against an XML template, comparing element and attribute values.HTTP body, JMS, Native IBM MQ
matchesXPathAn XPath expression selects a node from the XML body; the request matches when the node is present (optionally with a value sub-matcher).HTTP body, JMS, Native IBM MQ
matchesSwiftField Traffic Parrot extensionExtracts a SWIFT financial-message field by tag and matches its value against a regular expression.JMS, Native IBM MQ
matchesFixField Traffic Parrot extensionExtracts a FIX financial-protocol field by tag number and matches its value against a regular expression.JMS, Native IBM MQ
binaryEqualToByte-for-byte equality against a Base64-encoded expected value, for binary message bodies.JMS only
absentMatches when the body is absent (no request body present).HTTP body

HTTP requests also support four URL matchers, chosen from the Request URL dropdown. These are top-level request fields rather than body patterns.

Matcher (JSON key) Description Applies to
urlEqualToThe full URL, including query string, equals the given value.HTTP URL
urlMatchingThe full URL, including query string, matches the given regular expression.HTTP URL
urlPathEqualToThe URL path, ignoring the query string, equals the given value.HTTP URL
urlPathMatchingThe URL path, ignoring the query string, matches the given regular expression.HTTP URL

Body matcher examples

Each body matcher is one entry in the bodyPatterns array. The HTTP examples below show the matcher in a minimal mapping; the same body-pattern entry is used in the JMS, Native IBM MQ and gRPC mappings (within their respective request shapes).

equalTo
{
  "request": {
    "method": "POST",
    "url": "/orders",
    "bodyPatterns": [
      { "equalTo": "expected request body" }
    ]
  },
  "response": { "status": 200 }
}
contains
{
  "request": {
    "bodyPatterns": [
      { "contains": "ORDER-" }
    ]
  },
  "response": { "status": 200 }
}
doesNotContain
{
  "request": {
    "bodyPatterns": [
      { "doesNotContain": "DRAFT" }
    ]
  },
  "response": { "status": 200 }
}
matches
{
  "request": {
    "bodyPatterns": [
      { "matches": "ORDER-[0-9]{6}" }
    ]
  },
  "response": { "status": 200 }
}
doesNotMatch
{
  "request": {
    "bodyPatterns": [
      { "doesNotMatch": ".*TEST.*" }
    ]
  },
  "response": { "status": 200 }
}
equalToJson
{
  "request": {
    "bodyPatterns": [
      { "equalToJson": "{ \"id\": 1, \"name\": \"Widget\" }" }
    ]
  },
  "response": { "status": 200 }
}
matchesJson Traffic Parrot extension

The expected value is supplied as inline JSON, so it does not need to be escaped into a string.

{
  "request": {
    "bodyPatterns": [
      { "matchesJson": { "id": 1, "name": "Widget" } }
    ]
  },
  "response": { "status": 200 }
}
matchesJsonPath
{
  "request": {
    "bodyPatterns": [
      { "matchesJsonPath": "$.customer.id" }
    ]
  },
  "response": { "status": 200 }
}
equalToXml
{
  "request": {
    "bodyPatterns": [
      { "equalToXml": "<order><id>1</id></order>" }
    ]
  },
  "response": { "status": 200 }
}
matchesXml Traffic Parrot extension
{
  "request": {
    "bodyPatterns": [
      { "matchesXml": "<order><id>1</id></order>" }
    ]
  },
  "response": { "status": 200 }
}
matchesXPath
{
  "request": {
    "bodyPatterns": [
      { "matchesXPath": "//order/id/text()" }
    ]
  },
  "response": { "status": 200 }
}
matchesSwiftField Traffic Parrot extension

Available on the JMS and Native IBM MQ message body. The field is the SWIFT field tag; matches is a regular expression applied to that field's value.

{
  "request": {
    "bodyPatterns": [
      { "matchesSwiftField": { "field": "20", "matches": "TXNREF.*" } }
    ]
  },
  "response": { "status": 200 }
}
matchesFixField Traffic Parrot extension

Available on the JMS and Native IBM MQ message body. The field is the FIX tag number; matches is a regular expression applied to that tag's value.

{
  "request": {
    "bodyPatterns": [
      { "matchesFixField": { "field": "35", "matches": "D" } }
    ]
  },
  "response": { "status": 200 }
}
binaryEqualTo

Offered by the JMS editor for binary (bytes) message bodies. The expected value is Base64-encoded.

{
  "request": {
    "bodyPatterns": [
      { "binaryEqualTo": "AQIDBA==" }
    ]
  },
  "response": { "status": 200 }
}
absent
{
  "request": {
    "url": "/health",
    "bodyPatterns": [
      { "absent": true }
    ]
  },
  "response": { "status": 200 }
}

URL matcher examples

urlEqualTo
{
  "request": {
    "method": "GET",
    "urlEqualTo": "/orders?status=open"
  },
  "response": { "status": 200 }
}
urlMatching
{
  "request": {
    "method": "GET",
    "urlMatching": "/orders\\?status=(open|closed)"
  },
  "response": { "status": 200 }
}
urlPathEqualTo
{
  "request": {
    "method": "GET",
    "urlPathEqualTo": "/orders"
  },
  "response": { "status": 200 }
}
urlPathMatching
{
  "request": {
    "method": "GET",
    "urlPathMatching": "/orders/[0-9]+"
  },
  "response": { "status": 200 }
}

JSON-only matchers (not in the editor dropdown)

The matchers below are inherited from the bundled request-matching engine (and, where noted, are Traffic Parrot extensions) but are not offered in any editor dropdown. Use them by editing the mapping JSON directly — in the mapping file on disk, through import, or through the API. Each is labelled JSON-only. Several are flag variants of an editor matcher: the same matcher key plus extra sibling fields that the editor does not expose.

equalTo with caseInsensitive JSON-only

Case-insensitive exact match. Add the sibling flag caseInsensitive next to equalTo.

{
  "request": {
    "bodyPatterns": [
      { "equalTo": "expected body", "caseInsensitive": true }
    ]
  },
  "response": { "status": 200 }
}

equalToJson flags JSON-only

ignoreArrayOrder treats two JSON arrays with the same elements in a different order as equal. ignoreExtraElements ignores additional fields in the actual body that are not present in the expected value. Both default to false and are added as siblings of equalToJson.

{
  "request": {
    "bodyPatterns": [
      {
        "equalToJson": "{ \"items\": [\"a\", \"b\"] }",
        "ignoreArrayOrder": true,
        "ignoreExtraElements": true
      }
    ]
  },
  "response": { "status": 200 }
}

matchesJsonSchema JSON-only

Validates the request body against a JSON Schema. The optional schemaVersion sibling selects the schema dialect; valid values are V4, V6, V7, V201909 and V202012. When omitted, the default is V202012.

{
  "request": {
    "bodyPatterns": [
      {
        "matchesJsonSchema": "{ \"type\": \"object\", \"required\": [\"id\"], \"properties\": { \"id\": { \"type\": \"integer\" } } }",
        "schemaVersion": "V7"
      }
    ]
  },
  "response": { "status": 200 }
}

equalToXml advanced flags JSON-only

equalToXml accepts several optional sibling flags that the editor does not expose:

  • enablePlaceholders — allow placeholder tokens in the expected XML to match arbitrary values.
  • placeholderOpeningDelimiterRegex / placeholderClosingDelimiterRegex — customise the placeholder delimiters (default ${ and }).
  • exemptedComparisons — an array of XML comparison types to skip (for example NAMESPACE_URI, SCHEMA_LOCATION).
  • ignoreOrderOfSameNode — treat repeated sibling elements with the same name as order-independent.
  • namespaceAwareness — how strictly XML namespaces are compared; valid values are STRICT, LEGACY and NONE.
{
  "request": {
    "bodyPatterns": [
      {
        "equalToXml": "<order><id>${anything}</id></order>",
        "enablePlaceholders": true,
        "placeholderOpeningDelimiterRegex": "\\$\\{",
        "placeholderClosingDelimiterRegex": "\\}",
        "exemptedComparisons": ["NAMESPACE_URI", "SCHEMA_LOCATION"],
        "ignoreOrderOfSameNode": true,
        "namespaceAwareness": "LEGACY"
      }
    ]
  },
  "response": { "status": 200 }
}

matchesJsonPath advanced form JSON-only

The advanced form takes an object with an expression plus an inner value sub-matcher, so you can assert the value selected by the JSONPath rather than only its presence. The inner sub-matcher can be any string-value matcher (equalTo, contains, matches, and so on).

{
  "request": {
    "bodyPatterns": [
      {
        "matchesJsonPath": {
          "expression": "$.customer.id",
          "equalTo": "12345"
        }
      }
    ]
  },
  "response": { "status": 200 }
}

matchesXPath advanced form JSON-only

The advanced form takes an expression plus an inner value sub-matcher, and optionally an xPathNamespaces map to bind namespace prefixes used in the expression.

{
  "request": {
    "bodyPatterns": [
      {
        "matchesXPath": {
          "expression": "//s:order/s:id/text()",
          "contains": "1"
        },
        "xPathNamespaces": {
          "s": "http://example.com/shop"
        }
      }
    ]
  },
  "response": { "status": 200 }
}

Date and time: before, after, equalToDateTime JSON-only

Compare a date/time in the request against an expected moment. before matches values earlier than the expected, after matches later values, and equalToDateTime matches the same moment. The expected value may be a literal timestamp or an offset expression such as now +3 days. Optional sibling flags:

  • actualFormat — the date/time format of the value in the request (when it is not ISO-8601).
  • truncateExpected / truncateActual — truncate before comparing; valid units are YEARS, MONTHS, DAYS, HOURS, MINUTES, SECONDS (and the broader truncation forms such as FIRST_DAY_OF_MONTH).
  • applyTruncationLast — apply truncation after the offset rather than before.
  • expectedOffset / expectedOffsetUnit — shift the expected moment by a number of units (SECONDS, MINUTES, HOURS, DAYS, MONTHS, YEARS).
{
  "request": {
    "bodyPatterns": [
      {
        "before": "now +1 days",
        "actualFormat": "yyyy-MM-dd'T'HH:mm:ss",
        "truncateExpected": "DAYS",
        "expectedOffset": 1,
        "expectedOffsetUnit": "DAYS"
      }
    ]
  },
  "response": { "status": 200 }
}

Logical operators: and, or, not JSON-only

Compose sub-matchers. and and or take an array of sub-matchers; the body matches when all (and) or any (or) of them match. not takes a single sub-matcher and matches when that sub-matcher does not.

{
  "request": {
    "bodyPatterns": [
      {
        "and": [
          { "contains": "ORDER-" },
          { "doesNotContain": "DRAFT" }
        ]
      }
    ]
  },
  "response": { "status": 200 }
}
{
  "request": {
    "bodyPatterns": [
      {
        "or": [
          { "equalTo": "PING" },
          { "equalTo": "HEALTHCHECK" }
        ]
      }
    ]
  },
  "response": { "status": 200 }
}
{
  "request": {
    "bodyPatterns": [
      {
        "not": { "contains": "TEST" }
      }
    ]
  },
  "response": { "status": 200 }
}

matchesPathTemplate JSON-only

A string-value matcher that matches a value against a path template with named variables, such as /users/{id}. The value matches when it fits the template's shape regardless of the concrete variable values. It is used wherever a string-value matcher is accepted, for example as the value sub-matcher of a matchesJsonPath or matchesXPath expression that selects a path string from the body.

{
  "request": {
    "bodyPatterns": [
      {
        "matchesJsonPath": {
          "expression": "$.resourcePath",
          "matchesPathTemplate": "/users/{id}"
        }
      }
    ]
  },
  "response": { "status": 200 }
}

matchesGraphQL Traffic Parrot extension JSON-only

Matches a GraphQL request body (a JSON document with a query field) by comparing the canonical form of the incoming query against the expected query, so two queries that differ only in insignificant whitespace, field order or argument order are treated as equal. GraphQL requests are typically sent as an HTTP POST body.

{
  "request": {
    "method": "POST",
    "url": "/graphql",
    "bodyPatterns": [
      { "matchesGraphQL": "query { user(id: 1) { name email } }" }
    ]
  },
  "response": { "status": 200 }
}

About the matchers reference

This reference is maintained by hand. It lists every matcher Traffic Parrot accepts in mapping JSON for the version of the documentation you are reading; the set of matchers can change between releases, so always read the page that matches your installed version.

For the matchers offered by each protocol's editor, see the per-protocol pages linked from Available request matchers above.

Mapping folder (directory) structure

Traffic Parrot stores request to response mappings on the filesystem.

Protocol/technology Mappings location
HTTP(S) mappings and __files (where it stores bodies of responses during a recording)
JMS jms-mappings
Native IBM MQ ibm-mq-mappings
gRPC grpc-mappings
Thrift thrift-mappings
Files file-mappings

You can change the root directory by changing the value of the trafficparrot.virtualservice.trafficFilesRootUrl property.

XPath tutorials

XPath (XML Path Language) is a query language for finding and selecting elements in an XML document. Traffic Parrot allows to match requests using XPath.

We recommend the following reading to users who would like to take their XPaths skills to an advanced level: