<!-- Generated from https://trafficparrot.com/documentation/5.65.x/release_notes.html by scripts/generate-md-mirrors.sh. Do not edit: edit the .html and regenerate. -->

# Release notes and changelog

<a id="version-5-65-0"></a>
## 5.65.0 – 02 Nov 2026

<a id="highlights-5-65-0"></a>
### Highlights

Five things worth knowing about this release. The full list of features, changes and fixes follows.

<a id="highlight-validate-captured-traffic"></a>
#### `trafficparrot validate` compares your mappings with real traffic

Give the command a HAR file, or a directory of them, with `-Dtrafficparrot.validate.traffic=<path>`, and for each captured exchange it finds the mapping that would have served the request, works out what that mapping would have answered and compares it with what the real service answered: status, content type and body, by structure or by value. The report names the mappings that drift, the captured requests no mapping matches and the mappings no capture reached, and prints no header values, query strings or bodies. See [Checking mappings against captured traffic](https://trafficparrot.com/documentation/5.65.x/http.html#validate-cli-traffic).

<a id="highlight-sftp-server"></a>
#### Traffic Parrot can be the SFTP server

Switch on the embedded SFTP server with `trafficparrot.file.sftp.server.enabled=true` and it is the server a system under test uploads request files to and downloads replies from, so a file gateway flow needs no SFTP server of its own. Its users come from `sftp-server-users.json`, each confined to a home directory of its own, and one Local File System connection on the server root lets one replay session serve every user. Needs a licence that includes file messaging. See [Traffic Parrot as the SFTP server](https://trafficparrot.com/documentation/5.65.x/filemessage.html#sftp-server).

<a id="highlight-mountebank-import"></a>
#### Mountebank imposters import as HTTP mappings

Upload the file `mb save` writes, or one imposter's JSON, on the HTTP **Import** page or through the import API: each stub of an `http` or `https` imposter becomes mappings in the imposter's order, predicates become request matchers, a stub with several responses becomes a scenario that cycles through them, and `wait`, `proxy` and `defaultResponse` have their counterparts. A stub using something with no mapping equivalent is skipped with a warning naming it, and the rest of the file imports. See [Traffic Parrot for Mountebank users](https://trafficparrot.com/documentation/5.65.x/mountebank_users.html).

<a id="highlight-binary-files"></a>
#### Binary files pass through file recording and replay unchanged

A PGP, zip or EBCDIC file is forwarded while recording, saved with the mapping and written on replay byte for byte, on Local File System, SFTP and FTP connections. Recording a request file that is not text makes a mapping that matches it by name and by its exact bytes, the Files and native IBM® MQ mapping editors offer the same `binaryEqualTo` matcher, and a reply can be any file under `__files` with a `bodyType` of `BYTES`. See [Binary files](https://trafficparrot.com/documentation/5.65.x/filemessage.html#binary-files).

<a id="highlight-bearer-token-guard"></a>
#### A stub can require a token from the mock OAuth2/OIDC provider

The `matchesValidBearerToken` request matcher matches only a request whose `Authorization` header carries an unexpired JWT signed by a key the named [mock OAuth2/OIDC provider](https://trafficparrot.com/documentation/5.65.x/oauth2-mock.html) publishes, read from the mock's mappings in the same scenario on every request. A request without such a token falls through to the next mapping, so a catch-all on the same URL at a lower priority answers the `401`. In the HTTP mapping editor it is the **Require OAuth2 bearer token from mock** field. See [Requiring a token from the mock on a stub](https://trafficparrot.com/documentation/5.65.x/oauth2-mock.html#guard).

Also in this release: the Files replay page takes a [script](https://trafficparrot.com/documentation/5.65.x/filemessage.html#replay-script) of consume and reply pairs, an HTTP extension that could not be loaded is [listed above the mappings](https://trafficparrot.com/documentation/5.65.x/logging.html#left-out-at-start) rather than only logged, [CICS bridge conversations can be recorded](https://trafficparrot.com/documentation/5.65.x/cics.html#recording), the virtual service HTTPS listener can be [limited to chosen TLS versions and cipher suites](https://trafficparrot.com/documentation/5.65.x/user_guide.html#https-certificates-tls), a mapping added through the WireMock admin API is held in memory unless marked persistent, `trafficparrot validate` checks every HTTP, JMS, IBM® MQ and file message mapping file against its schema, and the SDK's JMS classes move to the `messaging` package with their old names kept and deprecated.

### Features

- **The Files replay page takes a script.** Choose **Script** on the Files replay page to run several consume and reply pairs in one replay session: each block names the connection to consume request files from (`RequestRootDirectory`), the connection to write responses to (`ResponseRootDirectory`) and the subdirectories to consume (`RequestSubdirectories`), in quotes, with a blank line between blocks. The IBM® MQ page's keys are still accepted, so a script written for the Files replay API keeps running. Starting with Script chosen and nothing typed is refused with `Please enter a replay script, or choose Manual`, on the IBM MQ replay page too. Through the API, a script session needs `parameterType` set to `SCRIPT`. See [Replaying using a script](https://trafficparrot.com/documentation/5.65.x/filemessage.html#replay-script).
- **Mountebank imposters import as HTTP mappings.** Upload the file `mb save` writes, or one imposter's JSON, on the HTTP **Import** page, or post it to the import API: each stub of an `http` or `https` imposter becomes one or more mappings in the imposter's order, the first stub at the highest priority; predicates become request matchers, with Mountebank's case-insensitive comparison kept where a matcher has the switch; a stub with several responses becomes a scenario that cycles through them; `wait` becomes a fixed delay, a `proxy` response a proxy mapping, and `defaultResponse` a catch-all mapping. A stub using something with no mapping equivalent, for example `inject`, `decorate`, `shellTransform`, `copy`, `lookup`, `except`, `requestFrom`, `form` or `ip`, or a `wait` given as a function, is skipped with a warning naming it, as is a `tcp` or `smtp` imposter, and the rest of the file imports. See [Traffic Parrot for Mountebank users](https://trafficparrot.com/documentation/5.65.x/mountebank_users.html).
- **Create a stub by pasting a cURL command.** Paste a command, for example one copied with Copy as cURL from the browser DevTools, into **Paste a cURL command** on the HTTP **Import** page and click Preview: each command becomes one stub that matches its method, path and query and answers `200`, and the command's headers and body are offered under **Also match on** as opt-in request matchers, so a stub is as strict as you tick; a ticked `Authorization` or `Cookie` value is saved in the mapping file. The host is not matched. A `.curl` file imports the same way, through the page or the import API, where `matchHeader` and `matchBody` select the matchers. See [Importing from a cURL command](https://trafficparrot.com/documentation/5.65.x/http.html#import-http-curl).
- **Traffic Parrot can be the SFTP server.** An embedded SFTP server, off by default and switched on with `trafficparrot.file.sftp.server.enabled=true`, is the server a system under test uploads request files to and downloads replies from, so a file gateway flow needs no SFTP server of its own. Its users, each with a password or an OpenSSH `authorized_keys` file, come from `sftp-server-users.json`, and each is confined to its own home directory under `sftp-server-root`; a Local File System connection on that directory lets one replay session serve every user. The host key is generated on the first start and kept, or is one you supply. An upload is visible to replay only once the client closes it, a refused login is logged with the user, its home directory and the reason, and the server speaks SFTP only, with no shell, command, SCP or port forwarding. Needs a licence that includes file messaging. See [Traffic Parrot as the SFTP server](https://trafficparrot.com/documentation/5.65.x/filemessage.html#sftp-server) and the [`trafficparrot.file.sftp.server` properties](https://trafficparrot.com/documentation/5.65.x/properties.html#file-properties).
- **An HTTP extension that cannot be loaded is shown, not only logged.** A class named in `trafficparrot.http.responsetransformers` that is left out when a WireMock server starts (not on the classpath, no usable constructor, or a constructor that throws) is now listed in the notice above the [HTTP mappings list](https://trafficparrot.com/documentation/5.65.x/http.html#add-edit-http-mappings), beneath the mapping files left out, as `HTTP extension <class> was left out: <reason>`, and `GET /http/management/skippedExtensions` answers the same list as JSON, one entry per class and reason, ending with the servers it applies to when that is not every one; before, the log was the only sign. That endpoint and the two `skippedMappingFiles` ones are now in the OpenAPI reference. See [Traffic Parrot started but one of my mocks or extensions is missing](https://trafficparrot.com/documentation/5.65.x/logging.html#left-out-at-start).
- **`trafficparrot validate` checks HTTP mappings against captured traffic.** Give the command a HAR 1.2 file, or a directory of them, with `-Dtrafficparrot.validate.traffic=<path>` (a browser's network export, a proxy or gateway capture, or Traffic Parrot's own [HAR export](https://trafficparrot.com/documentation/5.65.x/http.html#export-http-har) after proxying to the real service) and, for each captured exchange, it finds the mapping that would have served the request with the server's matching rules, works out what that mapping would have answered (templates are rendered with the captured request) and compares it with what the real service answered: status, content type and body, by structure by default (a field present on one side only, a changed type) or by value with `-Dtrafficparrot.validate.traffic.compare=values`, with volatile fields listed in an ignore file by the JSONPath or XPath the report prints. The report gains the mappings that drift (with up to five differences each), the captured requests no mapping matches, the mappings no capture reached, and the mappings it cannot compare (proxy, fault, a helper that reads a data source, a binary body file) with their reasons; it prints no header values, query strings or bodies. The findings warn by default; `-Dtrafficparrot.validate.traffic.fail=true` makes drift and unmatched requests exit `1`. The check writes nothing. Without the option the command's output and exit code are unchanged. See [Checking mappings against captured traffic](https://trafficparrot.com/documentation/5.65.x/http.html#validate-cli-traffic).
- **Binary files pass through file recording and replay byte for byte.** A file that is not text, such as a PGP, zip or EBCDIC file, is forwarded while recording, saved with the mapping and written on replay unchanged, on Local File System, SFTP and FTP connections. Recording a request file that is not valid UTF-8 makes a mapping that matches it by file name and by content, with a `binaryEqualTo` of the file's exact bytes beside the file-name matcher, so two binary files of one name are each answered by their own mapping on replay, and with its reply saved to `__files/file-message-<mapping id>-<reply file name>` as a `BYTES` body. A mapping you write replies with any file under `__files` the same way, with `bodyFileName` and a `bodyType` of `BYTES`; an inline `BYTES` body holds its content as base64. The Files **Add/Edit** page shows a binary reply as base64, as the JMS editor shows a bytes message, and saves it back byte for byte; a Save whose body is not base64 is refused and the mapping is left as it was. For a custom file message response transformer, the SDK's `FileMessage` gains `bytes()` and `ofBytes(fileName, bytes, timestamp)`, and a `FileMessageResponse` with a `BYTES` body type writes the bytes its base64 encodes. See [Binary files](https://trafficparrot.com/documentation/5.65.x/filemessage.html#binary-files).
- **A file message or native IBM® MQ mapping matches a binary request on its content.** The Files and native IBM® MQ **Add/Edit** mapping editors now offer *equal to base64* (`binaryEqualTo`) as the request body matcher, as the JMS editor does: the request matches when its bytes equal the Base64 value, byte for byte. For a file that is the file's exact content, the way to match a file that is not text on its content, and the file name matcher applies as well. For an IBM MQ message it is the message bytes as Traffic Parrot read them: the raw bytes of an `MQFMT_NONE` or RFH-wrapped body, or for an `MQFMT_STRING` body the UTF-8 encoding of its text; recording an IBM MQ message still writes a text matcher. It is accepted as the top-level `bodyMatcher` only, with the Base64 inline: not inside `and`, `or` or `not`, and a `bodyFileName` reference on it is refused when the mappings load, which leaves that protocol's mappings page empty until it is fixed. The file message and IBM MQ [mapping schemas](https://trafficparrot.com/documentation/5.65.x/generate-mocks-with-ai-agent.html#agents-md) accept it. See [Request file body matchers](https://trafficparrot.com/documentation/5.65.x/filemessage.html#request-body-matchers) and [Request body matchers](https://trafficparrot.com/documentation/5.65.x/ibmmq.html#request-body-matchers).
- **A stub can require a valid token from a mock OAuth2/OIDC provider.** The `matchesValidBearerToken` request matcher, a key of the `requestMatchers` custom matcher beside `matchesScript`, matches only a request whose `Authorization` header carries a `Bearer` token that is an unexpired RS256 JWT signed by a key the named [mock OAuth2/OIDC provider](https://trafficparrot.com/documentation/5.65.x/oauth2-mock.html) publishes in its JWKS, read from the mock's mappings in the same scenario on every request; `oauth2Mock` names the mock, `default` when left out, and `iss` and `aud` are not compared. A request without such a token falls through to the next mapping, so a catch-all on the same URL at a lower priority answers the `401`. In the HTTP mapping editor the guard is the **Require OAuth2 bearer token from mock** field under the request matching script, kept through a save, beside any script. A refused token is logged at `INFO` with a fixed reason and never the token, and a guard naming a mock that publishes no JWKS logs a `WARN` naming the likely causes, one of which is saving the mock's JWKS mapping in the editor, which drops its `oauth2Mock` metadata: edit that mapping as JSON instead. See [Requiring a token from the mock on a stub](https://trafficparrot.com/documentation/5.65.x/oauth2-mock.html#guard).
- **CICS bridge conversations can be recorded.** With [`trafficparrot.ibmmq.cicsBridge.enabled`](https://trafficparrot.com/documentation/5.65.x/properties.html#ibmmq-properties) set to `true`, IBM® MQ queue recording between an application and the real CICS bridge records each call as a mapping: it matches the program name and the COMMAREA decoded by the program's copybook, and replies with the bridge's settable `MQCIH` fields, the reply COMMAREA decoded by the reply copybook and the bridge's bytes as `CommareaHex`, which replay sends byte for byte until a decoded field is edited. The forwarded request is the client's message unchanged, `Authenticator` included, and the `Authenticator` is never recorded or logged. See [Recording a bridge conversation](https://trafficparrot.com/documentation/5.65.x/cics.html#recording).
- **The virtual service HTTPS listener can be limited to chosen TLS protocol versions and cipher suites.** `trafficparrot.virtualservice.https.tls.protocols` and `trafficparrot.virtualservice.https.tls.cipherSuites` replace the Java defaults (TLSv1.3 and TLSv1.2, with the SSL protocols and the RSA key exchange, SHA-1, MD5, NULL and anonymous suites excluded) with the versions and suites to offer, and `trafficparrot.virtualservice.https.tls.protocols.exclude` and `trafficparrot.virtualservice.https.tls.cipherSuites.exclude` add to the default exclusions; an entry may be a regular expression, and an excluded version or suite stays excluded whatever the include list says. All four ship blank, so an existing installation offers what it did. The versions and suites in force are logged when each listener starts, an entry that matches no version or suite the JVM supports is reported as a warning naming the property, a selection that leaves nothing to offer is logged as an error, and a handshake offering only an excluded suite or version is refused. The default exclusions stay in force whatever the include lists name. The settings also cover the TLS connector the recording proxy uses when browser proxying is enabled; the gRPC virtual service's TLS port, which has TLS settings of its own, and the web user interface's HTTPS port are not covered and keep the defaults. See [Restrict the TLS protocol versions and cipher suites](https://trafficparrot.com/documentation/5.65.x/user_guide.html#https-certificates-tls) and the [`trafficparrot.virtualservice.https.tls` properties](https://trafficparrot.com/documentation/5.65.x/properties.html#virtualservice-properties).
- **New `{{bodyFileExists}}` helper.** A mapping that picks its response file from the request (`"bodyFileName": "products/{{request.pathSegments.[1]}}.json"`) can check the file exists first, in a request matcher script, so a request for a missing file reaches a lower-priority mapping instead of answering `500`. The helper only checks that a file exists under `__files`; it never reads it, and a name that leaves `__files` is `false`. See [One mapping for a directory of responses](https://trafficparrot.com/documentation/5.65.x/http.html#file-backed-responses-lookup).

### Changes

- `trafficparrot validate` now checks every HTTP, JMS, native IBM® MQ and file message mapping file against the [mapping schema](https://trafficparrot.com/documentation/5.65.x/generate-mocks-with-ai-agent.html#agents-md) for its format, so a run that passed before now exits `1` on a mapping with an unknown or misspelt field, an HTTP method outside the schema's list (such as `PROPFIND`), a number in quotes, a file message `BYTES` body that is not base64, or a file that is not JSON, reported under `Some HTTP mappings do not match the HTTP mapping schema:` or `Some messaging mappings do not match the messaging schema:` with the file, the schema and each mismatch. gRPC mappings are not checked this way, and how the server loads mappings is unchanged. To keep such a file, list it under `exclude.files` in `http-schema.properties` or `messaging-schema.properties` in the files root, for example `exclude.files=mappings/custom-method.json`; to turn a check off, run with `-Dtrafficparrot.validate.http.schema.check=false` or `-Dtrafficparrot.validate.messaging.schema.check=false`. [Upgrading](https://trafficparrot.com/documentation/5.65.x/user_guide.html#upgrade) carries both properties files. See [Checking mappings against their schemas](https://trafficparrot.com/documentation/5.65.x/http.html#validate-cli-mapping-schema).
- A CICS bridge reply that gives both `COMMAREA` and `CommareaHex` is now accepted: the bytes are sent while the reply copybook decodes them to exactly those fields, and the fields are encoded otherwise, which is how a recorded mapping replays until a decoded field is edited. Before, a reply with the two keys together was refused. See [Replying](https://trafficparrot.com/documentation/5.65.x/cics.html#replying).
- The JSON view a CICS bridge request is matched on, logged under `CICS bridge request as Traffic Parrot matches it` and shown on the IBM® MQ **Requests** page, now leads with `ProgramName` and the decoded `COMMAREA` (or `CommareaNotDecoded` and `CommareaHex`), followed by `MQMD` and `MQCIH`. It led with `MQMD` and the `MQCIH` fields, which pushed the decoded fields past the requests page's cut. Matching by field name is unchanged; a matcher written over the whole text of the view, such as a regular expression, follows the new order. See [The request as Traffic Parrot matches it](https://trafficparrot.com/documentation/5.65.x/cics.html#request-view).
- The JMS, native IBM® MQ and file message mapping editors' `AND`, `OR` and `NOT` sub-matchers can now be `matches CICS field`, `matches SWIFT field` or `matches FIX field`, and a mapping file that combines them opens in the editor with its sub-matchers shown. Saving a mapping whose `and` or `or` has a sub-matcher the editor cannot show, such as a nested `and`, is now refused with `Sub-matcher 3 cannot be shown in the editor, so saving it would drop it: edit the mapping file instead` and the file is left unchanged; the HTTP and gRPC editors refuse such a mapping the same way. Each editor used to save the mapping without that sub-matcher. See [The matchesCicsField matcher](https://trafficparrot.com/documentation/5.65.x/cics.html#matches-cics-field) and [Authoring not in the messaging editor](https://trafficparrot.com/documentation/5.65.x/request_matching.html#not-in-messaging-editor).
- On every requests page (HTTP, gRPC, JMS, IBM® MQ, Files) and in the Static Files preview, a JSON body is now laid out from the text it was received with, so numbers such as `1500.00`, `0.0000001` and 20-digit integers, escapes, duplicate keys and key order show as sent; before, the body was re-parsed, which showed `1e-7` and rounded long numbers. A JSON body over 1,000,000 characters, or nested deeper than 1000 levels, is shown as received. An expanded IBM MQ, JMS or Files requests row now shows the message's whole body (up to 1,000,000 characters), not its first 500; the heading reads `Request Body (cut short)` while it loads or past that ceiling. See [Pretty-printed request and response bodies](https://trafficparrot.com/documentation/5.65.x/http.html#request-log-body-formatting).
- [`trafficparrot.file.remote.temporaryFileNames`](https://trafficparrot.com/documentation/5.65.x/properties.html#file-properties) now applies to Local File System connections as well as to SFTP and FTP ones: a file in a local request directory whose name matches one of the patterns, by default `*.tmp`, `*.part` and `*.filepart`, is left alone, when replaying and when recording, and is picked up under its final name once renamed, so a client that uploads under a temporary name and renames the file when done is consumed once. A local directory whose files to consume carry such names needs the property changed; an empty value skips no names. Traffic Parrot's own in-progress uploads are always skipped. See [How files on SFTP and FTP servers are picked up](https://trafficparrot.com/documentation/5.65.x/filemessage.html#remote-file-pickup).
- The SDK can build a native IBM® MQ response that sends an `MQMessage` with the messaging `DestinationLookup`: `IbmMqResponse.withResponseMessage(destination, message, fixedDelayMilliseconds, Optional.of(com.trafficparrot.sdk.messaging.DestinationLookup.USE_MAPPING_RESPONSE_DESTINATION))`. The `com.trafficparrot.sdk.ibmmq.DestinationLookup` it replaces stays deprecated, and plugins built against earlier SDKs keep working unchanged. See [Custom native IBM MQ response transformers](https://trafficparrot.com/documentation/5.65.x/dynamic.html#custom-nativeibmmq-response-transformers).
- The SDK's JMS classes `JmsResponse`, `JmsResponseTransformer`, `TextJmsResponseTransformer`, `JmsResponseBuilder`, `JmsProperty`, `JmsMessageType` and `JmsNamespaceBridge` are now in `com.trafficparrot.sdk.messaging`, the package that already holds `Destination`, `DestinationType`, `MessageBodyType` and `DestinationLookup`. Their `com.trafficparrot.sdk.jms` names still work and are deprecated, so a plugin compiled against an earlier SDK runs unchanged; import the `messaging` package in new code. See [Custom JMS response transformers](https://trafficparrot.com/documentation/5.65.x/dynamic.html#custom-jms-response-transformers).
- A `requestMatchers` custom matcher whose `parameters` name a matcher Traffic Parrot does not have, a misspelt `matchesValidBearerToken` beside a `matchesScript` for example, now fails the request with a `500` that names the unknown key. Before, the unknown key was skipped and the mapping matched on the matchers it did recognise, so a guard that was never applied looked as if it were. See [Require a token from a mock OAuth2/OIDC provider](https://trafficparrot.com/documentation/5.65.x/request_matching.html#require-bearer-token).
- A file message mapping whose inline `text` has a `bodyType` of `BYTES` must now hold that text as base64, and the response file is written as the bytes it encodes; before, such a body was written out as text, unchanged. A mapping whose `BYTES` body is not base64 is refused when the mappings load, with an error naming the mapping file, and, as for any invalid file message mapping, the Files pages list no mappings and replay matches nothing until it is fixed: change its `bodyType` to `TEXT`, or encode the content as base64. Text that happens to be made only of base64 characters is not refused: it loads, and the file is written as the bytes it decodes to. Before upgrading, run [`trafficparrot validate`](https://trafficparrot.com/documentation/5.65.x/http.html#validate-cli) on the files root: it reports a `BYTES` body that is not base64 under `Some messaging mappings do not match the messaging schema:`, without loading the mappings. A mapping with any other body type, or none, is unaffected. See [Binary reply from a file](https://trafficparrot.com/documentation/5.65.x/filemessage.html#binary-files-reply).
- A mapping added through the WireMock admin API (`POST /api/http/__admin/mappings`, a WireMock client's `stubFor`, the Testcontainers client's `stub()`) without `"persistent": true` is now held in memory, as in WireMock: it serves at once, no file is written under `mappings/`, at equal priority it answers ahead of a mapping file matching the same request, and it is gone on reset or restart. The [HTTP mappings list](https://trafficparrot.com/documentation/5.65.x/http.html#add-edit-http-mappings) marks such a mapping **Not saved**; that marker is a button that writes it to a file, and the editor shows the same note and saving from it writes the file. A mapping added with `"persistent": true` at the top level of its JSON is written to the selected scenario's `mappings/` directory, as every mapping added through the API was before, and [`trafficparrot.http.mappings.persistentByDefault=true`](https://trafficparrot.com/documentation/5.65.x/properties.html#http-mappings-persistent-by-default) brings that back for every mapping added through the API. Mappings added in the web user interface, by recording, by the MCP tools and by import on the HTTP **Import** page are written to files, as before, and so are OpenAPI, HAR, cURL and WireMock ZIP files posted to the import API; a Pact or Mountebank file posted to the import API is held in memory, like a mapping added through the admin API. WireMock's reset calls, `POST /api/http/__admin/reset` and `POST /api/http/__admin/mappings/reset`, now keep every mapping file and reload it, with stateful mappings back at `Started`, and forget the mappings held in memory; before, both deleted every mapping file. `DELETE /api/http/__admin/mappings` still deletes every mapping and every mapping file, and so does the Testcontainers client's `reset()`, which calls it first. See [A clean start for every test](https://trafficparrot.com/documentation/5.65.x/user_guide.html#junit-spring-tests-reset).
- The [SDK workspace project](https://trafficparrot.com/documentation/5.65.x/dynamic.html#custom-handlebar-helpers)'s example tests use JUnit Jupiter (JUnit 6), and its `pom.xml` declares `org.junit.jupiter:junit-jupiter` as a test dependency in place of `junit:junit` and pins the Maven Surefire plugin, so a Maven older than 3.9 runs the Jupiter tests instead of silently skipping them; build it with the bundled `./mvnw`, as the page shows. If you added JUnit 4 tests to your copy of the workspace, add `junit:junit` and `org.junit.vintage:junit-vintage-engine` as test dependencies to keep running them.
- The [Testcontainers](https://trafficparrot.com/documentation/5.65.x/testcontainers.html) example workspace's `pom.xml` pins the Maven Surefire plugin, so its JUnit Jupiter examples also run on a Maven older than 3.9, as the SDK workspace's now do.
- IBM® MQ and file messaging now record every request message received, matched or not, in the request journal, as JMS does, and the new endpoints `DELETE /api/ibmMq/requests` and `POST /api/ibmMq/requests/count`, with the same pair under `/api/fileMessage/requests`, reset the selected scenario's journal and count the messages matching a pattern, like `/api/jms/requests`. `DELETE` also empties that protocol's **Requests** page. The journal keeps up to [`trafficparrot.virtualservice.maxRequestJournalEntries`](https://trafficparrot.com/documentation/5.65.x/properties.html#virtualservice-properties) messages per scenario (`1000` by default), and a native IBM MQ message whose body cannot be read is logged as skipped and not recorded. See the [IBM MQ](https://trafficparrot.com/documentation/5.65.x/ibmmq.html#requests-page) and [Files](https://trafficparrot.com/documentation/5.65.x/filemessage.html#requests-page) Requests page sections.
- For each scenario, the JMS, IBM® MQ and file message request journals now keep at most 1/32 of Traffic Parrot's maximum heap of message text in each of their two lists, the messages received and the unmatched ones (about 4 MB a list at the default `-Xmx128m`), dropping the oldest messages first, so a request count covers the most recent messages.

### Fixes

- An unchanged Save in the JMS, native IBM® MQ or file message **Add/Edit mapping** page now keeps a request body matcher that reads its value from a file (a `bodyFileName` object as the matcher's value) as that reference, with its other options such as `caseInsensitive`, and the mapping goes on matching the file's contents. The editor used to save the reference as the matcher's literal JSON text, so the mapping never matched again. A reference to a file that does not exist, or that resolves outside `__files`, is now refused on Save and nothing is written. See [Request body matcher value from a file](https://trafficparrot.com/documentation/5.65.x/jms.html#edit-jms-request-body-file).
- `equalToXml` request matching no longer fails intermittently with an error, or gives a wrong match, when several requests are matched against the same stub at once. Two stubs that differ only in [`ignoreOrderOfSameNode`](https://trafficparrot.com/documentation/5.65.x/request_matching.html#json-only-matchers) no longer answer with each other's setting when matched at the same time.
- An XSLT or XPath implementation named on the command line with `-Djavax.xml.transform.TransformerFactory=<class>` or `-Djavax.xml.xpath.XPathFactory:http://java.sun.com/jaxp/xpath/dom=<class>` is now kept. Startup used to replace both with the JDK's own for the whole JVM, so an extension that relies on, for example, Saxon got the JDK's implementation. Only a `-D` is kept; a factory chosen through `jaxp.properties` or `META-INF/services` is still replaced. Traffic Parrot's own XML matching and XPath keep using the JDK's implementations, so their results do not change.
- Importing a Pact file through the import API (`POST /http/management/importMappings`) or inside a ZIP file now adds its mappings; before, the import reported them without adding them. Importing a Pact file from the HTTP **Import** page's preview was unaffected.
- Importing an OpenAPI specification: a request or response example that is a JSON array now keeps every element in order; before, each element was a copy of the first, and an array of arrays of different lengths failed the import. An array of maps (`additionalProperties` with required properties) now keeps each map's values.
- HTTP skeletons from an OpenAPI specification: a query parameter example now follows the parameter's `style` and `explode` (for example `ids=a,b` for `form` not exploded, `ids=a|b` for `pipeDelimited`, `filter[status]=open` for `deepObject`), and a string example keeps the parameter name (`status=open`, not just `open`). A Swagger 2 array query parameter with no `collectionFormat` gives `ids=a,b` (`csv`, the Swagger 2 default) and `collectionFormat: multi` gives `ids=a&ids=b`; before, both repeated the first value.
- An OpenAPI operation with no `responses` no longer fails the whole import: it imports with a default `200` response, as one with an empty `responses` does. OpenAPI request validation now validates requests to such an operation, so an invalid one gets a `400` where it used to be served, and the mappings schema check reports the default `200` as not defined in the specification, as it does for an empty `responses`.
- An OpenAPI import no longer fails when a response key is not a status code (`100` to `999`), a range such as `4XX`, or `default`, for example a lowercase `4xx` or a typo. That response is skipped with a warning naming it, and the rest of the specification imports. Request validation also skips such a response, with a warning on each request to that operation; before, a request it should have refused was served unvalidated. A key with a leading zero or sign, such as `0200`, used to import as `200` and is now skipped the same way.
- A [fault](https://trafficparrot.com/documentation/5.65.x/http.html#fault-delay-faults) now reaches a client speaking HTTP/2, over TLS or cleartext after the h2c upgrade. An HTTP/2 client used to receive a `500` in place of the fault. `Connection reset by peer` resets the TCP connection, which an HTTP/2 client shares between its requests, so every other request in flight on that connection fails with it. See [What differs over HTTP/2](https://trafficparrot.com/documentation/5.65.x/http.html#http2-differences).
- Over HTTP/2 (over TLS, and cleartext after the h2c upgrade) a request now presents its `:authority` as the `Host` header, so a `Host` header matcher matches it instead of answering `900`, and `{{request.headers.Host}}` renders the authority instead of a template error. A recording made from an HTTP/2 client keeps its `Host` matcher, and `trafficparrot validate` matches `Host` in a HAR captured over HTTP/2 the same way. A request that sends a `Host` header, and an HTTP/1.1 request, are unchanged.
- An open [HTTP](https://trafficparrot.com/documentation/5.65.x/http.html) or [gRPC](https://trafficparrot.com/documentation/5.65.x/grpc.html) mappings page no longer writes a stack trace to the [log](https://trafficparrot.com/documentation/5.65.x/logging.html) every second for each mapping whose body file is missing or outside `__files`. Each such file is now logged once per mapping, and again if it goes missing after being restored; a missing file's stack trace is at `DEBUG`, and a file outside `__files` is logged with its stack trace once.
- Upgrading now carries the coverage check allowlists: `openapi-coverage.properties`, `grpc-coverage.properties` and `messaging-coverage.properties` in the traffic files root are copied into the new installation, by the bundled upgrade and by the standalone upgrade helper script alike. They were left behind, so after an upgrade `trafficparrot validate` reported again every operation, method and destination you had deliberately left unmocked. See [Upgrading Traffic Parrot](https://trafficparrot.com/documentation/5.65.x/user_guide.html#upgrade) and the allowlists for [OpenAPI](https://trafficparrot.com/documentation/5.65.x/http.html#validate-cli-allowlist), [gRPC](https://trafficparrot.com/documentation/5.65.x/grpc.html#validate-grpc-allowlist) and [messaging](https://trafficparrot.com/documentation/5.65.x/jms.html#validate-messaging-allowlist).
- Recording a response the recorded system sends with `Content-Encoding: deflate` now stores the body decoded, as gzip and Brotli responses already were: the body file holds the text and the mapping replays it uncompressed. Before, the deflate bytes were saved as they arrived with the header dropped, so the mapping replayed them labelled as plain text. A response in a coding Traffic Parrot cannot decode, such as `zstd`, is now stored as it arrived with its `Content-Encoding` kept on the mapping, where before that header was dropped too; it replays byte for byte when its `Content-Type` is a binary type such as `application/octet-stream`, and with a text `Content-Type` the bytes that are not valid UTF-8 are replaced on replay. See [Compressed responses](https://trafficparrot.com/documentation/5.65.x/http.html#recording-compressed-responses).
- A [JMS response transformer](https://trafficparrot.com/documentation/5.65.x/dynamic.html#custom-jms-response-transformers) plugin compiled against an older SDK that reads a `JmsResponse`'s `destination`, and a [native IBM® MQ](https://trafficparrot.com/documentation/5.65.x/dynamic.html#custom-nativeibmmq-response-transformers) or file message response transformer plugin compiled against an older SDK that overrides a `doTransform` taking a `com.trafficparrot.sdk.jms.Destination`, work again without being recompiled. On recent releases the field read failed with `NoSuchFieldError` when a message reached the plugin, so no response was sent and later messages on that queue went unanswered, and the old-signature override was never called, so the message was answered with an error saying the plugin must implement `doTransform`.
- Recording an exchange whose request body is labelled JSON but does not parse, because a [request storage rewrite rule](https://trafficparrot.com/documentation/5.65.x/http.html#recording-request-body-rewriting) broke it or because it arrived that way, now records the mapping, matching that body as exact text rather than as JSON, and the client receives the recorded system's response. Before, nothing was recorded and the client received a `500` from the proxy even though the recorded system had already handled the request. A rewrite rule that breaks a body is still reported in the [log](https://trafficparrot.com/documentation/5.65.x/logging.html) as an error naming the URL and the rules. A JSON part of a `multipart/form-data` request that a rule leaves invalid is recorded the same way, that part matched as exact text.
- A user name and password in the backend URL entered on the WebSocket [Record](https://trafficparrot.com/documentation/5.65.x/websocket.html#recording-websocket) page no longer appear in `trafficparrot.log`. The lines that report recording starting, the backend being connected to for each client connection, and a backend that could not be reached printed the URL as entered, so `ws://user:secret@backend.example.com:9000` was written to the [log](https://trafficparrot.com/documentation/5.65.x/logging.html) with the password; they now print `ws://[REDACTED]@backend.example.com:9000`. The message that refuses a URL that does not start with `ws://` or `wss://`, names no host or cannot be parsed, shown on the page and written to the log, quotes the URL the same way. Such a URL is still accepted, the Record page still shows it as entered while recording, and log files written before the upgrade (`logs/trafficparrot.log*`) still hold what was typed.
- `trafficparrot validate` now reads the `-D` options on its command line, on Linux, macOS and Windows and wherever on the line they are typed. An option after the files root was ignored and one before it was taken for the files root, so the documented `-Dtrafficparrot.validate.helper.policy.check=true` never ran the [helper-policy check](https://trafficparrot.com/documentation/5.65.x/generate-mocks-with-ai-agent.html#validate-helpers) and the command exited `0` on a mapping using a denied helper. An option given to the JVM itself keeps working. See [Running the command](https://trafficparrot.com/documentation/5.65.x/http.html#validate-cli-usage).
- The JMS, IBM® MQ and file message **Add/Edit mapping** pages now save a mapping whose form, response body included, is up to [`trafficparrot.multipart.upload.max.size.mb`](https://trafficparrot.com/documentation/5.65.x/properties.html#virtualservice-properties) (default `10` MB). A Save over about 200 KB used to fail with `400: Unable to parse form content`. Base64 and the form encoding grow a binary reply by about 40%, so a binary file of up to about 7 MB can be saved at the default. See [Binary replies in the editor](https://trafficparrot.com/documentation/5.65.x/filemessage.html#binary-files-editor).
- The startup log no longer prints the virtual service keystore password. The `Loaded configuration` line written to the [log](https://trafficparrot.com/documentation/5.65.x/logging.html) on every start rendered the whole configuration, including `trafficparrot.virtualservice.keystoreAndTruststore.jks.password` and the default scenario's key store, key manager and trust store passwords, in clear; each now prints as `[REDACTED]`, as the `Loaded properties` line beside it already did. Log files written before the upgrade (`logs/trafficparrot.log*`) still hold the value.
- A JMS text message, or a bytes message read as printable characters, that reaches a mapping whose request body matcher is `binaryEqualTo` is now compared with it by its bytes (for a text message, the UTF-8 encoding of its text) and goes on to the other mappings when they differ. Before, matching stopped with `Only byte messages are supported` when such a message reached that mapping, so it was skipped with an error in the [log](https://trafficparrot.com/documentation/5.65.x/logging.html) and left unanswered.
- Starting or stopping HTTP [recording](https://trafficparrot.com/documentation/5.65.x/http.html#recording-http) or [passthrough proxying](https://trafficparrot.com/documentation/5.65.x/http.html#passthrough-proxy), which restarts the HTTP virtual service, now stops the previous instance's [webhook callback](https://trafficparrot.com/documentation/5.65.x/http.html#add-edit-webhook) threads with it; they used to be left running for the life of the process, one set per restart. A callback still waiting out its delay at that moment is not sent and is noted in the [log](https://trafficparrot.com/documentation/5.65.x/logging.html); one already being sent is left to finish, after the restart has waited up to 5 seconds for it, and is noted in the log. Callbacks fired by the restarted virtual service are unaffected.
- The `{{xPathList}}` helper and the `SoapMessageSigner` response transformer no longer read external entities or external DTDs from the XML they parse, so an entity declared in a request body can no longer read a file from the Traffic Parrot host into a response: the reference contributes nothing, and the document is otherwise parsed as before, a DOCTYPE included, with the parser settings the `equalToXml` and `matchesXPath` matchers use. The SDK workspace examples `MoveDatesInXmlRequestTransformer`, `MoveDatesInXmlResponseTransformer`, `TransformAndProxyRequestMessage` and `TransformAndProxyResponseMessage` refuse a DOCTYPE outright in the bodies they read; an extension built from an earlier copy of one of them should set the same two `DocumentBuilderFactory` features, `FEATURE_SECURE_PROCESSING` and `disallow-doctype-decl`.
- A request count whose body is empty or missing now counts every message, as `{}` does. `POST /api/jms/requests/count` used to answer `500` to such a request.

### Documentation

- Every code sample on the documentation pages and in the tutorials was run against the product, and the ones that did not work as shown were corrected. Among them: Handlebars block helpers closed with the wrong name, mapping JSON with a trailing comma, a `bodyPatterns` array in a JMS, IBM® MQ or file message mapping, which take a single `bodyMatcher` object instead, and the Java DSL names `urlEqualTo`, `urlMatching`, `urlPathEqualTo` and `urlPathMatching` shown as JSON keys in place of `url`, `urlPattern`, `urlPath` and `urlPathPattern`. The validate command is shown as `trafficparrot.sh validate`, with the allowlist hint its report prints, and the [SDK extension](https://trafficparrot.com/documentation/5.65.x/dynamic.html#custom-handlebar-helpers) and [PDF transformer](https://trafficparrot.com/documentation/5.65.x/dynamic.html#built-in-transformers) setup steps, the [shipped logging configuration](https://trafficparrot.com/documentation/5.65.x/logging.html) and several shown API responses and log lines now match what the product does.

<a id="version-5-64-1"></a>
## 5.64.1 – 28 Oct 2026

<a id="highlights-5-64-0"></a>
### Highlights

Five things worth knowing about this release. The full list of features, changes and fixes follows.

<a id="highlight-cics-bridge"></a>
#### Traffic Parrot stands in for the CICS bridge

Set `trafficparrot.ibmmq.cicsBridge.enabled` to `true` and a native IBM® MQ virtual service answers CICS DPL bridge requests as the bridge does: the COMMAREA is decoded with the program's COBOL copybooks, the request is matched on the program name, the decoded fields and the `MQCIH`, and the reply's COMMAREA is encoded from JSON by the reply copybook. Nothing runs on the mainframe. See [CICS over IBM® MQ](https://trafficparrot.com/documentation/5.65.x/cics.html).

<a id="highlight-recording-redaction"></a>
#### Credentials stay out of a recording

Set `trafficparrot.http.recording.redaction.enabled` to `true` and the `Authorization`, `Cookie`, `Set-Cookie` and `Proxy-Authorization` headers, and any header you name, are masked in what recording saves to disk and in the per-request log entry, replaced by a placeholder or dropped. The client recording through Traffic Parrot still receives the backend's real headers. See [Redacting credential headers during recording](https://trafficparrot.com/documentation/5.65.x/http.html#recording-header-redaction).

<a id="highlight-extension-database-connections"></a>
#### Your extension gets Traffic Parrot's database connections

An extension with a public constructor taking `TrafficParrotServices` is handed the JDBC connections named in `database-connections.json`, opened as the `dataSource` helper opens them, so a transformer that generates test data writes to the database the helper reads, with no copy of the credentials and no reflection into Traffic Parrot's classes. See [Using Traffic Parrot's database connections](https://trafficparrot.com/documentation/5.65.x/dynamic.html#custom-extensions-database-connections).

<a id="highlight-templates-page"></a>
#### Handlebars partials have a page of their own

**Tools**, **Templates** lists every `.hbs` file under the traffic files directory and edits it in place, offering Traffic Parrot's helpers by name as you type `{{`; the next response that includes the partial renders the saved version, with no restart. A partial can no longer include a file outside the traffic files directory. See [Template files](https://trafficparrot.com/documentation/5.65.x/dynamic.html#template-files).

<a id="highlight-testcontainers-extensions-cypress"></a>
#### Testcontainers: your jars, your properties, and a Cypress suite

The Testcontainers module now supplies your extension jars and property overrides, `withExtensionJar(Path)` and `withProperty(key, value)`, so an extension, a JDBC driver and a `database-connections.json` of your own load from an unedited release zip, and the example workspace shares one Traffic Parrot across every test class in the JVM. A Cypress suite does the same with the `testcontainers` npm package, starting Traffic Parrot once before the first spec and stopping it after the last. See [Adding your extensions and configuration](https://trafficparrot.com/documentation/5.65.x/testcontainers.html#extensions-and-configuration) and [From a Cypress suite](https://trafficparrot.com/documentation/5.65.x/testcontainers.html#cypress).

Also in this release: SFTP and FTP connections pick up complete files only, a native IBM® MQ request matcher can read its value from a file, a webhook can read the headers of the response it follows, the Settings page shows the database connections and the extension jars, a property set on the command line is honoured when the properties file leaves it out, a signed-in user without the edit role can no longer change anything, and a [mock OAuth2/OIDC provider](https://trafficparrot.com/documentation/5.65.x/oauth2-mock.html) is scaffolded into a scenario in one request.

### Features

- **Traffic Parrot stands in for the IBM® MQ CICS bridge.** With [`trafficparrot.ibmmq.cicsBridge.enabled`](https://trafficparrot.com/documentation/5.65.x/properties.html#ibmmq-properties) set to `true`, a native IBM® MQ virtual service answers CICS DPL bridge requests (format `MQCICS`: an `MQCIH`, the program name and the COMMAREA) as the bridge does. The COMMAREA is decoded with the program's COBOL copybooks, named in `copybooks/programs.json`, and the request is matched as a JSON view of the program name, the decoded fields, the MQMD user and the `MQCIH` fields, with the new `matchesCicsField` matcher (a field path and `equalTo`, `matches` or a comparison) or any JSON matcher. The reply is built from the mapping's JSON: the settable `MQCIH` fields, and the COMMAREA encoded with the reply copybook or given as hex, with the `cicsField` helper echoing request fields into it; it goes to the request's reply-to queue, correlated to its message id. A text message on a queue whose mapping uses CICS fields is warned about in the log, and the `MQCIH` `Authenticator` never reaches the log. The IMS bridge is not covered. See [CICS over IBM® MQ](https://trafficparrot.com/documentation/5.65.x/cics.html).
- **Credential headers can be redacted while recording.** Set [`trafficparrot.http.recording.redaction.enabled`](https://trafficparrot.com/documentation/5.65.x/properties.html#recording-properties) to `true` in `trafficparrot.properties` and the `Authorization`, `Cookie`, `Set-Cookie` and `Proxy-Authorization` headers, plus any header named in `trafficparrot.http.recording.redaction.headers`, are masked in what recording saves to disk: the recorded response headers, and the request headers recording matches on. `trafficparrot.http.recording.redaction.strategy` chooses between `PLACEHOLDER`, which replaces each value with `trafficparrot.http.recording.redaction.placeholder` (`***REDACTED***` unless you change it) and so changes what the saved request matcher expects, and `DROP`, which leaves the header out. The client recording through Traffic Parrot still receives the backend's real headers, a mapping created in the web user interface or through the admin API is saved as written, and the per-request entry in the [log](https://trafficparrot.com/documentation/5.65.x/logging.html) shows the covered headers redacted the same way, whether or not a recording is running. Off by default. See [Redacting credential headers during recording](https://trafficparrot.com/documentation/5.65.x/http.html#recording-header-redaction).
- **A custom extension can use Traffic Parrot's database connections.** An extension with a public constructor taking a `TrafficParrotServices`, from the `trafficparrot-sdk`, is created with it, and `services.databaseConnections().dataSource(connectionId)` is a `javax.sql.DataSource` for the JDBC connection of that id in `database-connections.json`, opened as the `dataSource` helper opens it. So a transformer that generates test data writes to the database the helper reads, with no copy of the credentials and no reflection into Traffic Parrot's classes, and an edit to the file takes effect on the next call. This works for every extension type, and an extension without such a constructor is created as before. The SDK workspace project gains `InsertRecordWithDatabaseConnection`, a transformer that inserts a record and answers with its id, with a unit test that passes it an in-memory database. See [Using Traffic Parrot's database connections](https://trafficparrot.com/documentation/5.65.x/dynamic.html#custom-extensions-database-connections).
- A [webhook (callback)](https://trafficparrot.com/documentation/5.65.x/http.html#add-edit-webhook) can read the headers of the response Traffic Parrot served, as `{{originalResponse.headers.headerName}}`, beside `{{originalResponse.status}}` and `{{originalResponse.body}}`, in every template a callback has: URL, method, headers, body and the enabled condition. A header the mapping's response template rendered is read as rendered. The shape is that of `{{request.headers}}`: the name matches in any case, and a header sent more than once keeps every value, `{{originalResponse.headers.headerName.[1]}}` being the second. See [Request data](https://trafficparrot.com/documentation/5.65.x/dynamic.html#request-data-http).
- **Handlebars partials have a page of their own.** **Tools**, **Templates** lists every `.hbs` file under the traffic files directory by its path, `templates/sql/customer-exists.hbs` for example, with a filter, and **Edit** opens it in an editor that shows the name a template includes it with, `{{> templates/sql/customer-exists.hbs}}`, and offers Traffic Parrot's helpers by name when you type `{{`, inserting the chosen helper's snippet. **Save** writes the file, and the next response that includes the partial renders the saved version, with no restart. A save over a file that changed on disk since it was opened is refused with the reason shown, and **Edit** reloads it. The page lists, loads and saves the files through the same mechanism as the **Current configuration files** editor on the **Settings** page, so [`trafficparrot.gui.config.files.allowedFilesToEdit`](https://trafficparrot.com/documentation/5.65.x/properties.html#gui-properties) governs which files it lists, and loading and saving need `traffic-parrot-gui-edit-role` when the web user interface login is on; a user without the role sees the list and a notice saying so. Creating or deleting a partial is still done on disk. See [Template files](https://trafficparrot.com/documentation/5.65.x/dynamic.html#template-files).
- **SFTP and FTP connections pick up complete files only, and pick up a file of a name already answered.** A file in a polled request directory is picked up once it has been listed with the same size and modified time at two consecutive polls, so a large file still being uploaded is left alone until it is complete. Names matching [`trafficparrot.file.remote.temporaryFileNames`](https://trafficparrot.com/documentation/5.65.x/properties.html#file-properties), `*.tmp,*.part,*.filepart` unless you change it, are never picked up, and nor are Traffic Parrot's own in-progress uploads. A file that matches a mapping is now deleted from the request directory before the response is written, on every driver, so a client that uploads its next file under the same name as soon as it sees the response has that file picked up too; previously a second file of a name already picked up in the session was never picked up. A file that matches no mapping stays and is not picked up again unless it changes. The two-poll check and the property apply to SFTP and FTP connections only. See [How files on SFTP and FTP servers are picked up](https://trafficparrot.com/documentation/5.65.x/filemessage.html#remote-file-pickup).
- A **native IBM® MQ** mapping's request `bodyMatcher` can now [read its expected value from a file](https://trafficparrot.com/documentation/5.65.x/ibmmq.html#edit-mq-request-body-file) under `__files`, by replacing the matcher's inline value with a `bodyFileName` object, as a [JMS](https://trafficparrot.com/documentation/5.65.x/jms.html#edit-jms-request-body-file) or [file message](https://trafficparrot.com/documentation/5.65.x/filemessage.html#request-body-matcher-from-file) mapping's request matcher can. The file is read when the mapping loads, resolved against the `__files` directory beside the mapping's `ibm-mq-mappings` directory (per scenario for scenario-scoped mappings) and contained to it. Only the top-level `bodyMatcher` supports it: a `bodyFileName` nested inside `and`, `or` or `not`, or one naming a file that does not exist, is refused when the IBM® MQ mappings load, with an error that names the mapping file, the matcher and the file. The [Static Files](https://trafficparrot.com/documentation/5.65.x/http.html#static-files-browser) page counts the file as in use and exporting a scenario bundles it. The IBM® MQ [mapping schema](https://trafficparrot.com/documentation/5.65.x/generate-mocks-with-ai-agent.html#agents-md) served at `/schemas` now describes the file form on the top-level `bodyMatcher` only, and the JMS and IBM® MQ schemas now require at least two operands in an `and` or `or`, which is what the mapping loader has always required, so `trafficparrot validate` reports a one-operand form before the mapping is loaded.
- **The Testcontainers module supplies your extension jars and property overrides.** `withExtensionJar(Path)` copies a jar into the container's `lib/external` directory before it starts, so an extension or a JDBC driver loads with no edited release zip, and `withProperty(key, value)` adds a `key=value` override to the start command of a container built from a release zip, as if the property were set in `trafficparrot.properties`. The example workspace gains two examples that share one Traffic Parrot across every test class in the JVM, one of them started with an extension, a driver and a `database-connections.json` of its own. See [Adding your extensions and configuration](https://trafficparrot.com/documentation/5.65.x/testcontainers.html#extensions-and-configuration) and [One Traffic Parrot for the whole suite](https://trafficparrot.com/documentation/5.65.x/testcontainers.html#shared-suite).
- **The Settings page shows the database connections and the extension jars.** Two read-only cards. **Database connections** lists the selected scenario's `database-connections.json`, each connection with its id, type, URL, driver, user and other settings and every password shown as `****`; the file is read as the `dataSource` helper reads it, so a file the helper would refuse shows the helper's reason. **Extension jars** lists the `.jar` files in `lib/external`, the directory the launcher puts on the classpath, with each jar's size and modified time. Each card opens from a deep link, `/settings.html#collapseDatabaseConnections` and `/settings.html#collapseExtensionJars`.
- **A mock OAuth2/OIDC provider, scaffolded in one request.** `POST /api/http/oauth2-mocks` writes three ordinary HTTP mappings into the selected scenario: an OpenID Connect discovery document whose endpoint URLs resolve against the address the request arrived on, a JWKS, and a token endpoint that issues RS256-signed JWTs for the `client_credentials` grant, so a system under test discovers the mock by its issuer, fetches its keys and obtains tokens as it would from a real provider, and a real OIDC client library completes both without special handling. The request body sets the mock's name, the issuer (which also decides where the endpoints are mounted), the audience, extra claims, the token lifetime (zero or negative issues an already-expired token, for testing expiry), the public base URL the mock advertises behind a proxy or on a published port, and an optional client id and secret the token endpoint then requires. Each mock signs with its own RSA key, kept in the token mapping, so the key id it publishes and every token it issued stay valid across a restart; a second scaffold of the same name, or onto paths other mappings already answer, is refused with `409` rather than replacing the key. When the web user interface login is on, the request needs `traffic-parrot-gui-edit-role`. See [Mock OAuth2/OIDC provider](https://trafficparrot.com/documentation/5.65.x/oauth2-mock.html).

### Changes

- [`trafficparrot.http.recording.request.storage.rewrite.regex`](https://trafficparrot.com/documentation/5.65.x/properties.html#recording-properties) rules now also apply to `multipart/form-data` request bodies, part by part. Previously a multipart body was recorded unchanged, with no warning, even when rules were set, so a credential in a form field was saved raw. Each part is now decoded with the charset from its own `Content-Type` (UTF-8 when it names none) and the rules run on that part on its own, so a rule cannot match across a part boundary. A part that a rule matches is re-encoded in full, as a non-multipart body already was, so a rule that matches inside a file upload re-encodes that part: keep uploads out of a recording by [giving the Recording URL a path](https://trafficparrot.com/documentation/5.65.x/http.html#recording-filter-path) rather than by relying on the rules to miss them. A rewrite that leaves a JSON part invalid is treated as one that leaves a JSON body invalid: the exchange is not recorded, and an error naming the URL and the rules is written to the [log](https://trafficparrot.com/documentation/5.65.x/logging.html). An installation that sets no rules is unaffected. See [Rewriting request bodies during recording](https://trafficparrot.com/documentation/5.65.x/http.html#recording-request-body-rewriting).
- While [`trafficparrot.http.recording.request.storage.rewrite.regex`](https://trafficparrot.com/documentation/5.65.x/properties.html#recording-properties) rules are set, the `Request received:` entry the [log](https://trafficparrot.com/documentation/5.65.x/logging.html) writes for each request to the virtual service now shows the request body as the rules rewrite it, whether or not a recording is running, and closes with a line naming what was redacted. Previously the entry carried the body as received, so a rule that kept a credential out of the recorded mapping did not keep it out of the log. `trafficparrot.virtualservice.httpRequestLoggingDisabled=true` still removes the entry, an entry the rules leave unchanged is as before, the URL is logged as received, and the request journal, which the [HTTP Request Log](https://trafficparrot.com/documentation/5.65.x/http.html#request-log-overview) page shows, keeps the body as received. See [Rewriting request bodies during recording](https://trafficparrot.com/documentation/5.65.x/http.html#recording-request-body-rewriting).
- When an [MCP tool](https://trafficparrot.com/documentation/5.65.x/mcp.html#tools) fails unexpectedly, the answer is now a tool result with `isError: true` whose text names the tool and the reason, for example `Tool 'list_scenarios' failed: Permission denied. The cause is in the Traffic Parrot log.`, where before it was a JSON-RPC `-32603` error with a fixed message that pointed only at the log. MCP `2025-11-25` files a tool's failure under tool execution errors, which the client shows to the assistant, whereas a protocol error it may drop; so the assistant can act on the reason. The reason is a permission error, a missing file, a file that already exists, the operating system's text for any other file-system failure, or otherwise the type of the exception, and never a path, because the response goes into the assistant's context and on to its model provider. The cause, with its stack trace, is still in the Traffic Parrot log. A call in a batch that fails in dispatch, before its tool runs, is still `-32603`. See [Running a tool](https://trafficparrot.com/documentation/5.65.x/mcp.html#running-a-tool).
- An [MCP tool](https://trafficparrot.com/documentation/5.65.x/mcp.html#tools) argument that the tool rejects, as missing, of the wrong type or out of range, is now answered as a tool result with `isError: true` whose text names the argument, for example `Argument 'id' is required` or `Argument 'dryRun' must be true or false, but was 'no'`, where before it was a JSON-RPC `-32602` error. MCP `2025-11-25`, the revision Traffic Parrot advertises, classifies input validation as a tool execution error so that the client shows the message to the assistant, which can then correct the call, whereas a protocol error the client may drop. A call no tool gets to judge is still `-32602`: `tools/call` without a `name`, a tool this instance does not offer, or `arguments` that is not an object. The `AGENTS.md` brief in the install directory says the same. See [the error-code table](https://trafficparrot.com/documentation/5.65.x/mcp.html#errors).
- A `matchesXPath` request body matcher given an expression alone, with no value sub-matcher, now matches only when the expression selects at least one node or evaluates to boolean `true`. An expression that evaluates to a number, a string or `false` used to match every XML body, so `count(//item) = 99` matched a body with two items; it now matches none, and `count(//item) = 2` matches the two-item body alone. This applies to HTTP, JMS and native IBM® MQ mappings alike, and the matcher's description in the editor's request matchers help panel now says the same. A mapping that relied on such an expression matching should select a node, or compare the value, instead. See [the matchers reference](https://trafficparrot.com/documentation/5.65.x/request_matching.html#matchers-reference).
- Upgraded bundled JRE from 21.0.11 to 21.0.12.1
- The shipped [`trafficparrot.gui.config.files.allowedFilesToEdit`](https://trafficparrot.com/documentation/5.65.x/properties.html#gui-properties) gains `.hbs$`, so the **Current configuration files** editor on the **Settings** page now lists Handlebars partials among the files; the **Templates** page under **Tools** is the place to edit them (see [Template files](https://trafficparrot.com/documentation/5.65.x/dynamic.html#template-files)). An installation upgraded with the upgrade script keeps the list its `trafficparrot.properties` already holds, as it keeps every setting, so add `.hbs$` to it yourself to see partials on either page; a fresh installation has the new list.
- Saving a file in the **Current configuration files** editor on the **Settings** page, or a partial on the **Templates** page, now keeps an LF-only file's line breaks: a file that uses LF alone is saved with LF. A file with CRLF or mixed line breaks, a file with no line break, and a new file are saved with CRLF, as every saved file was before. A JSON file does not notice the difference; a plain-text partial served as a response body does.
- The gRPC mapping editor shows request metadata as rows by default, in a **Request metadata matching** card below the request and response panels, with a matcher per entry (equal to, contains, a regular expression or a date/time comparison), and exception metadata as rows on the Exception tab. The `key: value` text form of each is under **Edit as text** beneath its rows, as for HTTP request and response headers, and the two stay in step. What is saved is unchanged: a mapping saved without an edit is the same mapping. See [Request metadata](https://trafficparrot.com/documentation/5.65.x/grpc.html#edit-grpc-request-metadata).
- The `wss4j`, `opensaml`, `openws` and `xmltooling` libraries are no longer bundled. Traffic Parrot never used them: SOAP message signing uses Apache Santuario (`xmlsec`) directly, which is still bundled. A plugin, or a JAR under `lib/external`, that relied on finding them on the classpath must now bring its own copy.

### Fixes

- The [HTTP Request Log](https://trafficparrot.com/documentation/5.65.x/http.html#request-log-overview) now shows the status the client received, in the **Status** column and in the row's details alike, including when a `{{modifyResponse 'statusCode' 404}}` response template or a proxied backend set it after the mapping was matched. Previously the column showed the status in the mapping's response definition, so a row read `200` for a response the client received as `404` while the details panel showed the served one. A mapping with no `status` now reads `200`, the status it is served with, where the cell was blank, and a fault that sends no status line leaves the cell blank, where it read `200`. See [Assert a request was made](https://trafficparrot.com/documentation/5.65.x/http.html#verifying-requests-assert-made).
- With `trafficparrot.gui.security.mode` set to `LOGIN_PROPERTIES`, the log pages that every virtual service HTTP and HTTPS port serves under `/__logs` (`/__logs/virtualservice/`, the Traffic Parrot log, and `/__logs/access/`, the access logs; a scenario's own ports included) now ask for the web user interface login. They answered anyone who could reach the port, with no login, while the same pages on the web user interface port asked for one. Stubs and the admin API on the virtual service ports are unchanged, and so is the [Logs page](https://trafficparrot.com/documentation/5.65.x/user_guide.html#start-logs), which reads them through the web user interface port with the login you signed in with. Read the pages through the Logs page or the HTTPS port rather than a plain-HTTP port, which sends the password unencrypted.
- An **Azure AMQP 1.0** connection in `jms-connections.json` loads and connects again, where one such entry used to stop every JMS connection in the file loading after an upgrade. An entry whose `jmsProvider` is not one Traffic Parrot knows is now skipped, with one WARN in the [log](https://trafficparrot.com/documentation/5.65.x/logging.html) naming the entry and the file it is in, rather than stopping the other connections loading. See [JMS connections](https://trafficparrot.com/documentation/5.65.x/jms.html#define-jms-connections).
- **JMS mappings recorded through an IBM® MQ 10 client** now replay. That client adds a `JMS_IBM_MsgToken` property to every message it receives and refuses to set it again, so a mapping that had recorded it could not be replayed: each matching request was logged as skipped and no response was sent. New installations no longer record the property, which joins the default of [trafficparrot.jms.skipRecordingProperties](https://trafficparrot.com/documentation/5.65.x/properties.html#advanced-properties). A mapping recorded earlier still carries it, and Traffic Parrot now sends the response without it and writes a WARN naming the property to the [log](https://trafficparrot.com/documentation/5.65.x/logging.html), where before no response was sent. The same applies to any other `JMSX` or `JMS_` property the JMS provider refuses to set; a refused property outside those two namespaces still fails the response as before, because it is more likely a mistake in the mapping than a property the provider owns. Upgrading keeps the skip list your installation already has, so if you record through an IBM MQ 10 client, add `JMS_IBM_MsgToken` to it yourself.
- Saving or deleting a mapping from a **mappings list** page now closes the edit dialog and refreshes the list when the list's automatic reload is stopped, or is paused because a tooltip is open or text on the page is selected. The reload that a save or delete issues could be cut short by the next paused reload tick, so the dialog stayed open and the list went on showing the mapping as it was before the change until the automatic reload ran again. This applies to the HTTP, gRPC, JMS, native IBM® MQ, file message and WebSocket mappings lists alike.
- Opening the [HTTP](https://trafficparrot.com/documentation/5.65.x/http.html) or [gRPC](https://trafficparrot.com/documentation/5.65.x/grpc.html) mappings list no longer changes what a mapping with a response body file serves, and neither does an OpenAPI export, a mapping schema check at startup, or a save of a gRPC mapping whose file name Traffic Parrot generates, which read the mappings the same way. With [`trafficparrot.virtualservice.mapping.cache.milliseconds`](https://trafficparrot.com/documentation/5.65.x/properties.html#caching-properties) above `0` (the shipped `performance-profile-settings/trafficparrot.performance.properties` sets `10000000`), listing the mappings made such a mapping answer with the text the list shows in place of its file until the cache expired: `(Traffic Parrot: not a text body)` for a binary file, the `Problem loading body file` message for a file that could not be read, or a text file's contents as they were when listed.
- A mapping whose response `bodyFileName` points outside the scenario's `__files` directory no longer breaks the HTTP and gRPC mappings lists. The list request failed, so the page showed no mappings, and adding a gRPC mapping failed too, until that mapping was deleted. The mapping is now listed with the reason its file cannot be read. [`trafficparrot validate`](https://trafficparrot.com/documentation/5.65.x/http.html#validate-cli) now treats such a mapping as it treats one whose body file is missing, validating the reason as the response body, where before it stopped with exit code `2` on an HTTP mapping and skipped a gRPC one. The OpenAPI export, which failed on such a mapping, now completes with the reason as that mapping's response body, and the mapping schema checks at startup, which stopped Traffic Parrot starting, now report the mapping only where an OpenAPI specification or proto covers it.
- The HTTP and gRPC editors now refuse a response body file name outside the scenario's `__files` when the save keeps a binary body, including a re-save of an existing mapping that already names one (such a mapping could not serve its body anyway).
- The gRPC management file endpoints, `/grpc/management/file/<name>` on the management port, no longer put a filesystem path in an error response. A name outside the scenario's `__files` directory, or naming that directory itself, is refused with `400` and `Invalid file name` on every verb, where before a save or delete answered `500` with the directory's absolute path, a delete named at the directory removed it when it was empty, and a read of it answered its listing. A missing file answers `404` and `File not found`, and any other failure a fixed `500` message, with the detail in the [log](https://trafficparrot.com/documentation/5.65.x/logging.html). The gRPC export leaves out a body file whose name is refused, where before the zip was cut short at that mapping.
- A JMS, native IBM® MQ or file message mapping whose response body file is missing from `__files`, or resolves outside it, is now reported without filesystem paths. The mappings list, which the Add/Edit page loads, a delete or edit of any mapping of that protocol, and the AsyncAPI and Pact specification imports answered `500` naming the body file and the mapping file by their paths; the reason now reads, for example, `Body file 'reply.txt' referenced from mapping 'orders.json' was not found.`, with the paths in the [log](https://trafficparrot.com/documentation/5.65.x/logging.html). The export, which answered a 200 zip with its `__files` entries missing, now answers that `500` too. A zip import that cannot write an entry reports `Could not import zip entry '<entry>'` rather than the entry's path.
- An IBM® MQ, JMS or file message mapping file with no `id` now shows correctly on the Add/Edit page and can be edited and deleted there. Previously the list raised a DataTables warning, the edit dialog opened empty, and while such a file was present, editing or deleting other mappings could fail.
- Loading and saving files under **Settings**, **Current configuration files**, now needs `traffic-parrot-gui-edit-role` when the web user interface login is on (`trafficparrot.gui.security.mode=LOGIN_PROPERTIES`). A signed-in user holding `traffic-parrot-gui-role` alone was offered **Load**, and the `/api/configuration/files` endpoints answered that user any listed file's content and accepted its changes and new files, so the shipped `readonly` user could read, change or create any `.json`, `.csv` or `.properties` file the editor lists. Those endpoints now answer `403` naming the role, and the page shows such a user the file names and a line saying which role loading and saving need; the names list stays open to every signed-in user. File names on the page are now shown as written, where a name containing markup was rendered as HTML. With the default `ALLOW_ALL` nothing changes. See [Role based access](https://trafficparrot.com/documentation/5.65.x/user_guide.html#role-based-access) and [`trafficparrot.gui.config.files.notAllowedFilesToEdit`](https://trafficparrot.com/documentation/5.65.x/properties.html#gui-properties).
- ActiveMQ, RabbitMQ, FTP and SFTP connection passwords, and the internal broker's keystore password, no longer appear in `trafficparrot.log`. The lines that report a JMS connection being created and a messaging record or replay page being rendered printed each configured connection with its password; they now print `[REDACTED]` in its place, and a password that is not set is still shown as not set, so a failed login can be told from a missing password. Native IBM® MQ connection passwords were already masked. Log files written before the upgrade (`logs/trafficparrot.log*`) still hold them.
- An OpenAPI response keyed by a range such as `4XX` no longer fails the import. The specification allows `1XX` to `5XX` as response keys, and importing one stopped with `For input string: "4XX"` after the operations before it had already saved, from the [Import](https://trafficparrot.com/documentation/5.65.x/http.html#import-http-rest-api) page, the skeletons upload and the [`generate_mappings_from_openapi`](https://trafficparrot.com/documentation/5.65.x/mcp.html#tools) MCP tool alike. A range response is now imported at the first code in the range, `400` for `4XX`, and where the specification also defines that code explicitly the explicit example is the one imported. OpenAPI request validation ([`trafficparrot.openapi.request.validation.mode`](https://trafficparrot.com/documentation/5.65.x/properties.html#openapi-properties)) answers an invalid request whose validation response is keyed by a range at that first code too, where before such a request was served unvalidated and an error was written to the [log](https://trafficparrot.com/documentation/5.65.x/logging.html). See [Matching response code](https://trafficparrot.com/documentation/5.65.x/http.html#import-http-matching-response-code).
- The `Admin request received:` entries in the [log](https://trafficparrot.com/documentation/5.65.x/logging.html), one per request to the virtual service's admin API, no longer carry the value of an `Authorization` or `Proxy-Authorization` header. The value is replaced with `*****` and the scheme is kept, so an entry reads `Authorization: [Basic *****]`. With `trafficparrot.gui.security.mode` set to `LOGIN_PROPERTIES` the web user interface sends the signed-in user's own credential with every admin API request it makes through `/api/http`, and Traffic Parrot sends an internal one on every start, so both were written to the log as sent. The `Request received:` entry for stub traffic is redacted while [credential header redaction](https://trafficparrot.com/documentation/5.65.x/http.html#recording-header-redaction) is on or [request storage rewrite rules](https://trafficparrot.com/documentation/5.65.x/http.html#recording-request-body-rewriting) are set, and otherwise carries the request's headers as received.
- An `equalToXml` request body matcher with `namespaceAwareness` set to `NONE` now matches a document whose elements have siblings, such as a SOAP envelope holding a `Header` and a `Body`, and an element holding both text and child elements (mixed content) now matches under every `namespaceAwareness` setting. Neither matched before. See [JSON-only matchers](https://trafficparrot.com/documentation/5.65.x/request_matching.html#json-only-matchers).
- A `matchesJsonSchema` request body matcher whose schema is written as a JSON object rather than as a string, through the admin API or in a mapping file, is now saved and read back as an object, and a `schemaVersion` the mapping does not declare is no longer added to it. Saving through the admin API used to rewrite the matcher, turning the object into an escaped string and appending `"schemaVersion": "V202012"`. What the matcher matches is unchanged: a mapping that declares no version still validates against JSON Schema 2020-12. The Add/Edit mapping editors add no `schemaVersion` either, and a mapping whose schema is an object keeps that form through an unedited Save. See [JSON-only matchers](https://trafficparrot.com/documentation/5.65.x/request_matching.html#json-only-matchers).
- Saving a mapping in the HTTP, gRPC, JMS, native IBM® MQ or file message Add/Edit mapping editor now keeps the request body matcher options the editor cannot author, whether or not the matcher value was edited: a `matchesJsonSchema` keeps its `schemaVersion`, an `equalTo` its `caseInsensitive`, an `equalToJson` its `ignoreArrayOrder` and `ignoreExtraElements`, and a `matchesJsonPath` its advanced form with a value sub-matcher. Save rebuilt the matcher from the dropdown and the text field alone, so a schema declaring `V4` was saved with `V202012`, which can change what it matches, and the other options were dropped. An option is kept while the matcher chosen in the dropdown stays the same, and dropped when you choose another matcher. A request body matcher that reads its value from a file (`bodyFileName`) still loses its sibling options on Save. Also fixed in the HTTP and gRPC editors: after opening a mapping whose request body matcher reads from a file, saving a different mapping with an inline request body no longer writes that body into the first mapping's file. See [JSON-only matchers](https://trafficparrot.com/documentation/5.65.x/request_matching.html#json-only-matchers).
- A Handlebars partial can no longer include a file outside the traffic files directory. A partial's name is resolved against the selected scenario's directory, or the traffic files directory when no scenario is selected, and a name that resolves outside it, or to a file that does not exist, is now reported as a missing partial, with the reason in the [log](https://trafficparrot.com/documentation/5.65.x/logging.html). A mapping that included a file from outside the traffic files directory now answers an error: move the file under it. See [Template files](https://trafficparrot.com/documentation/5.65.x/dynamic.html#template-files).
- Upgrading with the upgrade script now keeps the web user interface user store and the Handlebars partials, and prints no setting values. `trafficparrot.gui.login.properties` was not carried, so an installation with the login on came up with the shipped `admin` and `readonly` users and their password; it is now copied whole, so a shipped user you removed stays removed. The `templates` and `responses` directories and any `.hbs` file at the installation root are carried too, where before a partial had to be copied by hand. The upgrade's output, which it also writes to `tp.out` in the new installation, now names each carried setting without its value, where before it printed the value of every setting it merged: passwords, the MCP token and a licence passed as `-Dtrafficparrot.license.content` among them. If you upgraded an installation before this change, check that its `trafficparrot.gui.login.properties` holds only the users you want, and that its `tp.out` holds nothing you would not keep in a log. The standalone upgrade helper script, which takes the release zip and the previous installation as its arguments, carries the same files, merges a directory on macOS, where before it carried nothing, copies a directory reached through a symbolic link as that directory's contents, and ends with an error naming what it could not copy rather than reporting a complete upgrade. See [Upgrading Traffic Parrot](https://trafficparrot.com/documentation/5.65.x/user_guide.html#upgrade).
- Under the web user interface login (`trafficparrot.gui.security.mode=LOGIN_PROPERTIES`), a signed-in user without `traffic-parrot-gui-edit-role` can no longer change Traffic Parrot. The role was checked only when a page was drawn, so the mapping editors hid their controls from such a user, but nothing checked it on the way in: the shipped `readonly` user could create a mapping through `POST /api/http/__admin/mappings`, duplicate one, start a recording, switch the scenario, clear a request log, upload a static file or run an import, from the pages that still showed those controls and through every API the web user interface port serves. Every request that could change Traffic Parrot now needs the edit role: any method other than `GET`, `HEAD` and `OPTIONS`, and any request carrying a body. A user with `traffic-parrot-gui-role` alone is refused with `403` and a JSON body naming the role, which the pages show as the error. The request log queries that take their criteria in a `POST` body stay open to a reader: `requests/find`, `requests/count`, the near-miss queries and `mappings/find-by-metadata` through `/api/http`, the gRPC and JMS request counts, and the WebSocket `messages/find` and `messages/count`. On `/mcp`, a tool that changes something is refused as a tool result with `isError: true` naming the role, before it runs; listing the tools and calling the seven that only read is unchanged. Stub traffic forwarded to the virtual service through the web user interface port now needs the edit role too while the login is on; the virtual service port itself, its `/__admin` API and the management ports are not behind the login, as before. With the default `ALLOW_ALL` nothing changes. See [Role based access](https://trafficparrot.com/documentation/5.65.x/user_guide.html#role-based-access).
- A `-D` system property, including one set through `JAVA_TOOL_OPTIONS`, or a `key=value` argument to the start script now sets a property that the loaded properties file leaves out. Such an override was ignored and the bundled default applied, which the startup log listed under `Using default values from` as if nothing had been set: on an installation upgraded from an earlier release, whose `trafficparrot.properties` lacks every property added since, or with a file named by `trafficparrot.properties.filename` that holds only the keys you set, `-Dtrafficparrot.virtualservice.http.port=2001` left the virtual service on `8081`, and `-Dtrafficparrot.http.recording.redaction.enabled=true` left redaction off. The startup log's `Using system property overrides` line now lists such a key. A fresh installation's shipped file holds every property, so it was unaffected. Precedence is unchanged: a system property wins over the file, which wins over the bundled default.
- The `dataSource` helper now works on a fresh installation with `database-connections.json` as shipped. The shipped file carries a Couchbase example, and reading any connection from a file that holds one needed the Couchbase client, which the release does not bundle, so every `dataSource` call failed with `NoClassDefFoundError: com/couchbase/client/core/env/Authenticator`, the JDBC connections beside the example included, until the example was deleted from the file. The file now reads without the client. A Couchbase connection used while its JARs are not in `lib/external` answers an error naming `lib/external`, and the JDBC connections beside it work. See [Data source](https://trafficparrot.com/documentation/5.65.x/dynamic.html#data-source).
- An unmatched native IBM® MQ or file message is now listed on that protocol's **Requests** page with its near misses, the mappings closest to it and the field each one missed on, when [`trafficparrot.messaging.diagnostics.enabled`](https://trafficparrot.com/documentation/5.65.x/properties.html#jms-properties) is `true`, and **Clear** empties the list, as on the JMS page. The property named all three protocols but only JMS was connected, and JMS recorded nothing at the shipped mapping cache setting, `trafficparrot.virtualservice.mapping.cache.milliseconds=0`, so its page stayed at `0 MESSAGES` however the property was set. The messaging request journal is now safe to write from several receive threads at once: a JMS virtual service with more than one request destination, or whose Requests page was read during traffic, could leave a received message unanswered, and the journal could grow past `trafficparrot.virtualservice.maxRequestJournalEntries` until restart. With the property `false`, near misses are no longer computed. Near misses are listed under the selected scenario, whichever scenario's virtual service received the message, and a file whose name does not match is shown as a Body Content mismatch.
- A **JMS response property** value containing `;` now keeps it when the mapping is saved, including when the mapping is opened and saved without changes: everything after the second `;` on a `name;type;value` line is the value. A line without a type or a value is refused with a message naming the line, instead of an error that pointed to the logs. See [Response properties](https://trafficparrot.com/documentation/5.65.x/jms.html#edit-jms-response-properties).
- The `size` helper now counts the entries of a map, as the [WireMock helpers](https://trafficparrot.com/documentation/5.65.x/dynamic.html#wiremock-helpers) list says it does: `{{size request.query}}` and `{{size (parseJson request.body)}}` render the count, where before each rendered an error such as `{{ size ERROR: cannot get size of 'java.util.HashMap' }}` in the response. A string or a list is counted as before. A map that stands for a failed helper is not counted: when the map comes from a `dataSource` call that reported an error, `size` renders that error rather than `0`, where before it rendered an error naming an internal class.
- **Internalize** under **Tools** now writes each response column of a native IBM® MQ mapping with several responses into the response it was exported from. The `MappingData.csv` header names each response's queue, but every column was written into every response, so after an Internalize, even of an unedited export, all the responses of such a mapping carried the body of whichever column was processed last. A column whose header names a queue the mapping no longer sends to is refused with an error naming that queue and the queues the mapping does send to, and the rest of the file is applied as before. A mapping with one response is unaffected.
- A native IBM® MQ response that could not be scheduled within a minute, because the request queue's **Maximum messages in progress**, the largest value among the mappings that read the queue, were all in flight, was dropped: the request had already been consumed, the [log](https://trafficparrot.com/documentation/5.65.x/logging.html) read `Skipping IBM MQ message`, and no response was sent. Traffic Parrot now keeps waiting for a slot and writes a WARN, `Still waiting to schedule a response message to <queue>`, to the log, and the requests it has not yet consumed stay on the queue. A queue is unaffected while any mapping that reads it leaves the field at its default.
- Under concurrent requests, with `trafficparrot.virtualservice.mapping.cache.milliseconds` at its default of 0, a request could intermittently be answered 900, no responses matched, although a mapping matched it, most often where request matcher scripts sat above a fallback mapping. Every request now matches against the complete set of mappings. The same fix covers gRPC, and JMS and IBM® MQ when a non-zero mapping cache is set.
- With `trafficparrot.virtualservice.handlebars.throwErrors=true`, a `dataSource` query that fails, because the connection id is unknown, the table is missing, the SQL is invalid or the database is down, is now answered with an HTTP 500 even when the helper is given a `default`, and so is every other error the helper would otherwise write into the body: no rows with no default, a placeholder with no value, and a single value asked of a query that returned several. A query that runs and returns no rows with a default still serves the default. With the property at its default of `false`, a failure the default covers is now logged at WARN, `Returning default value '[]' because of error '...'`, where before it was logged at INFO. A custom helper that reports an error without throwing can honour the property through the new `protected static throwErrorsEnabled()` on `TrafficParrotHelper`.
- An HTTP extension named in `trafficparrot.http.responsetransformers` that cannot be loaded, such as a jar carrying its own copy of the SDK or a class that is not on the classpath, no longer stops the HTTP virtual service from starting, and the HTTP pages of the console no longer fail on it: it is left out, with an ERROR in the log naming the class and the reason, and the other extensions are loaded. A mapping file that cannot be loaded, because it is not valid JSON, is not a mapping, or names a request body file that is missing, is left out the same way, with one ERROR naming the file and the reason, and the other mappings, HTTP and gRPC, are still served, where before every mock answered 500 while the file was broken, or Traffic Parrot did not start. A `validate` run still fails on such a file.
- The HTTP and gRPC mapping lists show each mapping file left out that way, in a warning above the table: one line per file, or per mapping of a file whose mappings fail one at a time, naming it by its path exactly as the ERROR in the [log](https://trafficparrot.com/documentation/5.65.x/logging.html) does, with the reason, so the line can be searched for in the log. The warning is refreshed with the list's automatic reload and goes once the file loads; before, the log was the only sign. `GET /http/management/skippedMappingFiles` and `GET /grpc/management/skippedMappingFiles` on the management port answer the same list as JSON.
- A `dataSource` query on a database connection that contains a colon which is not a placeholder, such as the time literal `'12:30'` or the cast `42::varchar`, now runs. The helper's own check for placeholders without a value read every `:name` in the SQL as a placeholder, so it refused such a query before it ran, with `Parameter values not specified: [:30, :varchar]`. For a database connection the check now follows the same named-parameter rules the query runs with: a colon inside a quoted literal, a quoted identifier, a comment or a `::` cast is not a placeholder, and a placeholder the call gives no value is still refused by name. Because the check now reads the SQL as the database does, its refusals shift with it: a placeholder inside a comment is no longer reported, and `&name`, `:id.json` and `:age2` given only `age` are refused as missing before the query runs, where before the query failed inside the driver and `default` covered it. CSV and Excel sources are unchanged, and still treat a quoted `:name` as a placeholder. See [Data source](https://trafficparrot.com/documentation/5.65.x/dynamic.html#data-source).
- The CA truststore shipped as `certificates/virtualservice-CA-certificate.jks` now holds the current Traffic Parrot CA certificate, the same one as `certificates/virtualservice-CA-certificate.pem` and the one every shipped server certificate is issued from. It still held the CA from before the December 2025 rotation, so a client that trusted the keystore trusted none of the shipped certificates and failed the TLS handshake; a client trusting the PEM was unaffected. The alias, `trafficparrot-ca`, and the password are unchanged, so a client configured for the keystore needs only the new file.
- The [SDK workspace project](https://trafficparrot.com/documentation/5.65.x/dynamic.html#custom-handlebar-helpers) zip now builds on a machine whose Maven cache does not already hold `org.unsynchronized:jdeserialize`, a library the SDK depends on that Maven Central does not host: the zip's `repo/` directory carries it next to the SDK, with its licence under `licenses/`. The workspace's build stopped at `Could not find artifact org.unsynchronized:jdeserialize:jar:2.0.2` unless an earlier build had already cached it. The zip also no longer carries a `.surefire-<hash>` file, the test-run statistics left behind by the build that produced it.

### Documentation

- Added **[CICS over IBM® MQ](https://trafficparrot.com/documentation/5.65.x/cics.html)**: how Traffic Parrot stands in for the CICS DPL bridge, the copybooks and their index, the request view, matching, replying, and a walkthrough that runs end to end on the free IBM® MQ developer container with a sample program and a Java client; and **[Traffic Parrot for CA LISA / DevTest users](https://trafficparrot.com/documentation/5.65.x/devtest_users.html)**, which maps DevTest's IBM MQ transport and copybook data protocol onto those pieces and says what is not covered. The [IBM® MQ matchers table](https://trafficparrot.com/documentation/5.65.x/ibmmq.html#request-body-matchers) gains `matchesCicsField`, and the [properties reference](https://trafficparrot.com/documentation/5.65.x/properties.html#ibmmq-properties) the `trafficparrot.ibmmq.cicsBridge.enabled` row.
- The [MCP endpoint](https://trafficparrot.com/documentation/5.65.x/mcp.html#tools) reference now lists `get_body_file`: a read-only tool that returns one of the selected scenario's `__files` entries as text, by the name `get_mapping` reports as `bodyFileName`, so an assistant can see a response body that is stored in a file instead of inline. Only that scenario's `__files` directory is readable, a binary file is refused with its size, and contents past 64 KB come back cut short with `truncated` set. The tool counts on that page and on [Generate mocks with an AI agent](https://trafficparrot.com/documentation/5.65.x/generate-mocks-with-ai-agent.html) now read thirteen tools, seven of which only read.
- The [HTTP](https://trafficparrot.com/documentation/5.65.x/http.html#import-http-rest-api) and [gRPC](https://trafficparrot.com/documentation/5.65.x/grpc.html#import-grpc-rest-api) pages and the [OpenAPI documentation](https://trafficparrot.com/documentation/5.65.x/openapi/index.html) now describe the `POST /http/management/importMappings` and `POST /grpc/management/importMappings` responses as the endpoints answer them: the ids of the imported mappings, plus `warnings` when part of an HTTP upload could not be imported. The HTTP page also says that an imported mapping records the file it came from as `tp.import.source` and that importing a file of the same name again replaces the earlier import, and both pages say what happens when an imported mapping is written to the file of an existing one.
- Added a **[Hoverfly middleware in Traffic Parrot](https://trafficparrot.com/documentation/5.65.x/hoverfly-middleware.html)** how-to page for users migrating from Hoverfly. It maps Hoverfly's *Modify*/*Synthesize* middleware, a language-agnostic executable fed the HTTP pair as JSON on stdin and returning mutated JSON on stdout, onto Traffic Parrot's [`external-process`](https://trafficparrot.com/documentation/5.65.x/dynamic.html#external-process-transformer) response transformer, with a concept-mapping table (Hoverfly's global `-middleware` flag against the global opt-in plus per-mapping `transformers`/`transformerParameters` model), a copy-pasteable uppercase-body Python example, the [versioned envelope](https://trafficparrot.com/documentation/5.65.x/dynamic.html#external-process-envelope) migration notes, and the differences to expect (response-only, one process per request, HTTP only, per-mapping opt-in).
- Added **[Traffic Parrot in JUnit and Spring Boot tests](https://trafficparrot.com/documentation/5.65.x/user_guide.html#junit-spring-tests)** to the user guide: how the build starts and stops Traffic Parrot around the integration-test phase with the Maven or Gradle plugin, how a test points the code under test at its port, how to reserve every port at build time when builds share a CI host, and what to clear between tests (the request journal, scenario state and key-value state). The [For WireMock Users](https://trafficparrot.com/documentation/5.65.x/wiremock_users.html) page's reset row now names those three calls; it named the mapping cleanup feature, which consolidates recorded mappings into a new scenario and is not a reset.
- Added [When each extension runs](https://trafficparrot.com/documentation/5.65.x/dynamic.html#custom-extensions-when-they-run): where each extension type sits relative to request matching and response rendering. A Handlebars helper runs during rendering; an HTTP response definition transformer and the JMS, Native IBM MQ and file message response transformers run before it, on the mapping's response as written; an HTTP response transformer runs after it, on the response the client is about to receive.
- Added [Adding an extension jar and configuration without rebuilding the zip](https://trafficparrot.com/documentation/5.65.x/dynamic.html#custom-extensions-without-rezipping): the `lib/external` directory, and the three ways to set a property from outside the zip, on the command line, through `JAVA_TOOL_OPTIONS`, or in a properties file of your own that holds only the keys you set, each with its Docker form and the startup log line that confirms it.
- The templates on the [Per-test data recipe](https://trafficparrot.com/documentation/5.65.x/recipe-per-test-data.html) page, and in its [example zip](https://trafficparrot.com/documentation/5.65.x/downloads/per-test-data-example.zip), are now laid out across lines with indentation: a helper call's arguments one per line inside the tag, where they render nothing, and a JSON response one field per line. The request matcher script that decides the 409 keeps rendering exactly `true` or `false`, with a `~` on each tag beside the layout and a comment saying why. The responses they render are unchanged.
- Added [From a Cypress suite](https://trafficparrot.com/documentation/5.65.x/testcontainers.html#cypress) to the [Testcontainers](https://trafficparrot.com/documentation/5.65.x/testcontainers.html) page: a `cypress.config.js` that builds the image from the module's Dockerfile with the `testcontainers` npm package, starts Traffic Parrot once in `setupNodeEvents` with your jars and traffic files copied in and your properties on the start command, hands its URL to every spec through the returned config, and stops it on `after:run`, with the two specs that use it.

<a id="version-5-63-1"></a>
## 5.63.2 – 22 Sep 2026

<a id="highlights-5-63-1"></a>
### Highlights

Four things worth knowing about this release. The full list of features, changes and fixes follows.

<a id="highlight-testcontainers"></a>
#### Start Traffic Parrot from your JUnit tests

The new [Testcontainers module](https://trafficparrot.com/documentation/5.65.x/testcontainers.html) starts Traffic Parrot in a container from a release zip, or from an image you already have, mounts your mappings and hands the test the URL to point at. `TrafficParrotClient` stubs, verifies and resets over the admin API from the same test, and a downloadable example workspace runs a JUnit 5 and a JUnit 4 example against a release zip with nothing else configured.

```
@Container
static final TrafficParrotContainer TRAFFIC_PARROT = TrafficParrotContainer
        .fromReleaseZip(Paths.get("/downloads/trafficparrot-no-jre-5.63.2.zip"))
        .withPackagedTrafficFiles(MountableFile.forClasspathResource("traffic-files"));
```

<a id="highlight-signed-webhooks"></a>
#### Signed webhooks, in both directions

A mock can now send a callback that carries the signature the receiving code verifies, as a payment provider or a source-control host does: `{{hmac webhookBody key='...'}}` in a callback header signs exactly the bytes the receiver gets. On the way in, `{{hmacMatches}}` in a request matcher script accepts only the correctly signed callbacks the system under test sends. `{{hash}}` covers ETags and checksums, and `HmacSigningTransformer` gains hex and Base64url encodings, a signature prefix, and always runs last. See [Signing an outbound webhook](https://trafficparrot.com/documentation/5.65.x/dynamic.html#sign-webhook) and [Verify an inbound webhook signature](https://trafficparrot.com/documentation/5.65.x/request_matching.html#verify-signed-webhook).

![The HTTP mapping editor opened on a mapping whose webhook callback carries a Stripe-Signature header computed by the hmac helper over the callback body](https://trafficparrot.com/documentation/5.65.x/img/whats-new/5.63.1/signed-webhook.webp)

<a id="highlight-agents-brief"></a>
#### Your AI assistant can write the mappings

The `AGENTS.md` brief that ships in the install directory now covers writing mapping files as well as the MCP tools: where the instance serves its mapping schemas and helper policy, the ground rules for a mapping written from a contract, how to load it, and the `trafficparrot validate` check. An assistant given the brief can write gRPC, JMS, native IBM® MQ and file message mappings, which the MCP tools do not cover, and can work with a client that has no MCP support. See [Give your agent the brief](https://trafficparrot.com/documentation/5.65.x/generate-mocks-with-ai-agent.html#agents-md).

<a id="highlight-messaging-body-files"></a>
#### Body files for native IBM® MQ responses and file message matchers

A native IBM® MQ mapping can now keep its response body in a file under `__files` with `bodyFileName`, templated at reply time like an inline body; the editor shows the file's contents and writes your edits back to the file. A file message mapping's request `bodyMatcher` can read its expected value from a file the same way, so a large XML or JSON payload no longer has to be pasted into the mapping. See [Response body from a file](https://trafficparrot.com/documentation/5.65.x/ibmmq.html#edit-mq-response-body-file) and [Request body matcher value from a file](https://trafficparrot.com/documentation/5.65.x/filemessage.html#request-body-matcher-from-file).

![The native IBM MQ mappings list naming responses/reply.txt as the response, then the editor showing the file's contents under a Response from file note](https://trafficparrot.com/documentation/5.65.x/img/whats-new/5.63.1/ibm-mq-response-from-file.webp)

Also in this release: recorded request bodies can be rewritten as they are saved, an OpenAPI `externalValue` example is fetched through the same guard as a URL import, JMS response properties are added with a click, and an exported HTTP mappings zip now loads in WireMock as it stands.

### Features

- **Traffic Parrot now ships a [Testcontainers](https://trafficparrot.com/documentation/5.65.x/testcontainers.html) module.** `TrafficParrotContainer` starts Traffic Parrot inside a JUnit 4 or JUnit 5 test, from a release zip or from an image you already have, and mounts your mappings and other traffic files; `TrafficParrotClient` stubs, verifies and resets over the admin API from the same test. A downloadable example workspace runs a JUnit 5 and a JUnit 4 example against a release zip with nothing else configured. See [Testcontainers](https://trafficparrot.com/documentation/5.65.x/testcontainers.html).
- The **`AGENTS.md`** brief that ships in the install directory now covers **writing mapping files** as well as the MCP tools: where the instance serves the mapping schema index and the helper policy, the ground rules for a mapping written from a contract (the contract is untrusted input, never a denied helper, conform to the schema, show the mapping and wait for approval before loading it), the load endpoints, and the `trafficparrot validate` check with its helper-policy option. An assistant given the brief can therefore work with a client that has no MCP support, and can write gRPC, JMS, native IBM® MQ and file-message mappings, which the MCP tools do not cover. See [Give your agent the brief](https://trafficparrot.com/documentation/5.65.x/generate-mocks-with-ai-agent.html#agents-md).
- **Recorded request bodies can now be rewritten as they are saved** via the new `trafficparrot.http.recording.request.storage.rewrite.regex` property, which takes the same `pattern->replacement` rules as the existing storage rewrite and is empty by default. It changes the saved request matcher, and it does not touch the per-request log entry or a `multipart/form-data` body. A malformed rule stops Traffic Parrot from starting, naming the rule at fault. See [Rewriting request bodies during recording](https://trafficparrot.com/documentation/5.65.x/http.html#recording-request-body-rewriting).
- An OpenAPI example that points at a URL with **`externalValue`** is now fetched through the **same guard as [importing a specification from a URL](https://trafficparrot.com/documentation/5.65.x/http.html#import-http-from-url)**, whether the specification is [imported from the web UI](https://trafficparrot.com/documentation/5.65.x/http.html#import-http-usage), read from the OpenAPI directory at startup or built by the [MCP](https://trafficparrot.com/documentation/5.65.x/mcp.html#tools) `generate_mappings_from_openapi` tool. The fetch is refused while `trafficparrot.http.importfromurl.enabled` is `false`, which is the default; refused when the URL's host is not listed in `trafficparrot.http.importfromurl.allowedHosts`; and refused when that host resolves to a loopback, link-local, private or cloud-metadata address, even if it is listed. A refused example is replaced with the existing `Traffic Parrot could not fetch externalValue: <url> (<reason>)` placeholder, the reason naming the rule that refused it, and the mapping is still created. Previously the fetch was made from the Traffic Parrot host to whatever `http` or `https` URL the specification named, with no allow-list, so a specification placed in the OpenAPI directory or uploaded for import could direct the host at an internal address. To keep fetching `externalValue` examples, set `trafficparrot.http.importfromurl.enabled=true` and list the example hosts in `trafficparrot.http.importfromurl.allowedHosts`; see [Properties](https://trafficparrot.com/documentation/5.65.x/properties.html).
- New Handlebars helpers **`{{hmac}}`** and **`{{hash}}`** compute an HMAC signature or a keyless digest (SHA-256, SHA-1 or MD5) of any value, written as lower case hex, Base64 or Base64url. [Webhook](https://trafficparrot.com/documentation/5.65.x/http.html#add-edit-webhook) headers and bodies are templates, so a mock can now send a callback that carries the signature the receiving code verifies, as a real payment provider, source-control host or chat platform does, something the `HmacSigningTransformer`, which signs responses only, could not do. See [Signatures and digests](https://trafficparrot.com/documentation/5.65.x/dynamic.html#hmac-hash-helpers) and the worked [webhook-signing example](https://trafficparrot.com/documentation/5.65.x/dynamic.html#sign-webhook).
- A signature header can now name the body it signs. A webhook's URL, method and header templates read the rendered callback body as **`{{webhookBody}}`**, and a response's header templates read the rendered response body as **`{{renderedBody}}`**, so `{{hmac webhookBody key='...'}}` in a callback header signs exactly the bytes the receiver will verify, instead of restating the body expression and keeping the two copies in step by hand. Both keys are absent when nothing was rendered: a webhook with no body, or a response that is binary, has no body, is a proxy response, or loads a body file with templating disabled. A mapping that also lists another body-changing transformer should sign with `hmacSigning`, which runs last, rather than with `{{hmac renderedBody}}`. See [Signing a body from a header](https://trafficparrot.com/documentation/5.65.x/dynamic.html#sign-body-from-header).
- New **`{{hmacMatches}}`** helper verifies the signature on an inbound request from a [request matcher script](https://trafficparrot.com/documentation/5.65.x/http.html#add-edit-request-matcher-script), so a mock can accept only the correctly signed callbacks the system under test sends and answer the rest with an error. It compares in constant time and renders `false`, never an error, for a missing or malformed signature. See [Verify an inbound webhook signature](https://trafficparrot.com/documentation/5.65.x/request_matching.html#verify-signed-webhook).
- The **`HmacSigningTransformer`** gains an `encoding` parameter (`base64`, which is the default and the previous behaviour, `hex` or `base64url`) and a `signaturePrefix` parameter (for example `sha256=`), and it is now guaranteed to run last, after every other response transformer on the mapping including a `ResponseTransformerV2` an install adds through `trafficparrot.http.responsetransformers`, so the signature always covers the bytes the client receives; a response that also passes through `external-process`, for example, is signed over the transformed body. The transformers that ship with Traffic Parrot run before the signature is computed, so a mapping that combines `hmacSigning` only with those is unaffected. A mapping that also lists a body-changing `ResponseTransformerV2` of your own after `HmacSigningTransformer` in `trafficparrot.http.responsetransformers` now signs the transformed body; the signature previously covered the body before that transformer ran, so it did not match what the client received. See [HmacSigningTransformer](https://trafficparrot.com/documentation/5.65.x/dynamic.html#hmac-signing).
- A **[native IBM® MQ response body can now be served from a file](https://trafficparrot.com/documentation/5.65.x/ibmmq.html#edit-mq-response-body-file)** in the `__files` directory, as a [JMS](https://trafficparrot.com/documentation/5.65.x/jms.html#edit-jms-response-body-file) or [file message](https://trafficparrot.com/documentation/5.65.x/filemessage.html#add-edit-file-message-mappings) response body can be. Set `bodyFileName` on a mapping's `response`, or on any entry of its `responses` list, in place of an inline `text` value; the two are mutually exclusive, and the path is resolved against the `__files` directory beside the mapping's `ibm-mq-mappings` directory, per scenario for scenario-scoped mappings. The file is read as UTF-8 text and is supported for the `MQFMT_STRING` message format only: a `bodyFileName` on a response in one of the binary formats, a response that sets both `text` and `bodyFileName`, or a file that does not exist, is rejected at load time and the IBM® MQ mappings fail to load until it is corrected, with an error naming the mapping and the file. The file's contents go through the same [Handlebars templating](https://trafficparrot.com/documentation/5.65.x/dynamic.html#extract-data) as an inline body. The mappings list shows the file name in place of the body, the editor shows a read-only **Response from file:** note and loads the file's contents into the response body field, and saving writes the edit back to the file and keeps the reference. The [Static Files](https://trafficparrot.com/documentation/5.65.x/http.html#static-files-browser) page counts the file as in use, and exporting a scenario bundles it. Support for binary (bytes) response bodies read from a file, and for reading an IBM® MQ request body matcher's value from a file, will follow.
- A **file message** mapping's request `bodyMatcher` can now read its expected value from a file under `__files`, by replacing the matcher's inline value with a `bodyFileName` object, as a [JMS](https://trafficparrot.com/documentation/5.65.x/jms.html#edit-jms-request-body-file) mapping's request matcher already could. The file is read when the mapping loads and is contained to `__files`. Only the top-level `bodyMatcher` supports it: a `bodyFileName` nested inside `and`, `or` or `not`, or on `fileNameMatcher`, is refused when the file message mapping loads, as a JMS mapping already refuses one, with an error that names the mapping file, the matcher and the file. The JMS and file message [mapping schemas](https://trafficparrot.com/documentation/5.65.x/generate-mocks-with-ai-agent.html#agents-md) served at `/schemas`, which `trafficparrot validate` and an AI agent writing mappings work from, now describe exactly that: the file form on the top-level `bodyMatcher` only. See [Request body matcher value from a file](https://trafficparrot.com/documentation/5.65.x/filemessage.html#request-body-matcher-from-file).
- **WebSocket service virtualization** is now documented on the new [WebSocket page](https://trafficparrot.com/documentation/5.65.x/websocket.html) and gains a **Record** page. With `trafficparrot.websocket.enabled=true`, clients connect to the virtual service HTTP port with `Connection: Upgrade` and Traffic Parrot answers each text frame from the mappings in `websocket-mappings/`, which follow the selected scenario; a mapping can also push a frame to a client as soon as it connects. The **WebSocket** menu carries **Add/Edit**, **Record** and **Logs** pages, and the `/websocket/management` API creates, lists, updates and deletes mappings and queries the frame journal. The new **Record** page proxies every WebSocket connection to a real backend and saves each client frame together with the backend's reply as a mapping; frames the backend sends before the client has spoken are saved as on-connect mappings, and recording the same frame again replaces the earlier recording rather than duplicating it.

### Documentation

- The [HmacSigningTransformer](https://trafficparrot.com/documentation/5.65.x/dynamic.html#hmac-signing) section now says that the transformer is opt-in and must be listed in the mapping's response `transformers` array, and its example includes the array, which the earlier example omitted; a second example shows a hex signature with a prefix. The new [Signatures and digests](https://trafficparrot.com/documentation/5.65.x/dynamic.html#hmac-hash-helpers) section documents the three helpers and the `renderedBody` and `webhookBody` model keys, [Signing an outbound webhook](https://trafficparrot.com/documentation/5.65.x/dynamic.html#sign-webhook) walks through a complete signed callback, and [Verify an inbound webhook signature](https://trafficparrot.com/documentation/5.65.x/request_matching.html#verify-signed-webhook) shows the matcher-script recipe.
- The **[MCP endpoint](https://trafficparrot.com/documentation/5.65.x/mcp.html)** documentation now carries **[an error-code table](https://trafficparrot.com/documentation/5.65.x/mcp.html#errors)**: every JSON-RPC error code Traffic Parrot answers (`-32700`, `-32600`, `-32601`, `-32602`, `-32603`, `-32000` and `-32001`), when each one is answered, and the HTTP status it arrives under, plus the refusals that deliberately carry no JSON-RPC envelope (the 405, 415 and 406 request-framing refusals, and the login's role-mismatch 403), so a client integrator can tell the layers apart. The [Who can reach it](https://trafficparrot.com/documentation/5.65.x/mcp.html#access) section now also distinguishes all three authentication refusals rather than two of them.
- The gRPC import REST endpoint, `POST /grpc/management/importMappings`, is now documented under [Importing via REST API](https://trafficparrot.com/documentation/5.65.x/grpc.html#import-grpc-rest-api) on the gRPC page and in the [OpenAPI documentation](https://trafficparrot.com/documentation/5.65.x/openapi/index.html), where the `POST /http/management/importMappings` success response is now described as the `{"mappings": [...]}` object the endpoint returns, with the `warnings` member a partial import adds, rather than as a bare array of ids. [Download the specification](https://trafficparrot.com/documentation/5.65.x/downloads/openapi.yaml).
- The JMS page now documents [reading a request body matcher's value from a file](https://trafficparrot.com/documentation/5.65.x/jms.html#edit-jms-request-body-file): the `bodyFileName` form, the matchers that accept it, the top-level-only rule and what a bad reference does at load. Two stale notes on the same page are corrected: the Static Files page counts a file a JMS mapping references as in use, and file message mappings can serve a response body from a file.
- The new [WebSocket page](https://trafficparrot.com/documentation/5.65.x/websocket.html) documents WebSocket service virtualization end to end: [enabling it](https://trafficparrot.com/documentation/5.65.x/websocket.html#configure-enable), the [mapping file format](https://trafficparrot.com/documentation/5.65.x/websocket.html#mapping-file), message and on-connect triggers, how a frame is matched, the Add/Edit, Record and Logs pages, the [`/websocket/management` API](https://trafficparrot.com/documentation/5.65.x/websocket.html#websocket-management-api) and its message journal, [recording](https://trafficparrot.com/documentation/5.65.x/websocket.html#recording-websocket) from a real backend and its [limitations](https://trafficparrot.com/documentation/5.65.x/websocket.html#websocket-limitations). WebSocket support had shipped switched off behind `trafficparrot.websocket.enabled` with a [properties entry](https://trafficparrot.com/documentation/5.65.x/properties.html#websocket-properties) and no page of its own.

### Changes

- The Mac download is now one zip, `trafficparrot-mac-x64-aarch64-jre-<version>.zip`, carrying both an Apple Silicon (aarch64) and an Intel (x64) Java runtime; the launcher picks the one that matches the machine at startup, so one download covers every Mac and an Apple Silicon Mac runs natively rather than through Rosetta 2. It replaces `trafficparrot-mac-x64-jre-<version>.zip`, so a script that downloads the Mac bundle by file name needs the new name. The Linux, Windows and no-JRE bundles are unchanged.
- A malformed rule in `trafficparrot.http.recording.response.rewrite.regex` or `trafficparrot.http.recording.storage.rewrite.regex` now stops Traffic Parrot from starting, naming the rule at fault. Previously such a rule was dropped with a line in the [log](https://trafficparrot.com/documentation/5.65.x/logging.html) and recording carried on without it, so a rule that had not taken effect was discovered only by finding the un-rewritten value in a recording. That includes a rule that looked correct and appeared to work: a comma separates one rule from the next, so a comma inside a pattern, in a quantifier such as `\d{12,19}`, split the rule in two at the comma. The half with no `->` was dropped and the other half was installed as a rule you never wrote, so the value the rule was meant to scrub was recorded as it was, with only that line in the log to say so. Such a rule is now refused at startup like any other, and the message says that a comma cannot appear inside a pattern: write the quantifier without one, for example `\d{12}\d?\d?\d?\d?\d?\d?\d?` in place of `\d{12,19}`. Check both properties before upgrading an installation that sets them.
- The `executeProcess` helper is now supplied by the four helper lists in [`trafficparrot.properties`](https://trafficparrot.com/documentation/5.65.x/properties.html) (`trafficparrot.http.handlebars.helpers`, `trafficparrot.jms.handlebars.helpers`, `trafficparrot.ibmmq.handlebars.helpers` and `trafficparrot.file.handlebars.helpers`) rather than being registered on every list whatever the property says, so it can be switched off by removing `com.trafficparrot.handlebars.script.ExecuteProcess` from them, as `evaluate` already could be. The shipped lists name it, so a stock installation is unchanged. An installation that overrides any of those properties keeps its own list, which does not name the helper, so after the upgrade a template that uses `{{executeProcess ...}}` on that protocol no longer renders, and nothing at start-up says so: add `com.trafficparrot.handlebars.script.ExecuteProcess` to each overridden list to keep the helper. The performance profile, whose four lists are empty, no longer offers it, as it already did not offer `evaluate`.
- Upgraded the Couchbase Java SDK that the [Couchbase data source](https://trafficparrot.com/documentation/5.65.x/dynamic.html#data-source-couchbase) is built against from 3.12.2 to 3.12.3; the `java-client` and `core-io` JARs to place in `lib/external` are linked from that page.

### Fixes

- The [HTTP Request Log](https://trafficparrot.com/documentation/5.65.x/http.html#request-log-overview) shows an unmatched request with the `900` the client received, in the **Status** column and in the row's details alike, where before both showed the `404` that WireMock records internally for a request it did not match, so someone looking into why a client got a `900` found a `404` in the log.
- The **Current configuration files** editor on the **Settings** page no longer offers `trafficparrot.gui.login.properties`, the web user interface's own user store, or the `database-connections.json`, `ibm-mq-connections.json` and `jms-connections.json` files that hold connection passwords. The shipped [`trafficparrot.gui.config.files.notAllowedFilesToEdit`](https://trafficparrot.com/documentation/5.65.x/properties.html) list did not name them, so any user who could open the page could read them with **Load**, and a user allowed to edit could rewrite them with **Save**. The shipped list now names the user store and every file whose path contains `-connections.json`; an installation that overrides that property keeps its own list, so add both entries to it.
- Saving a file in the **Current configuration files** editor on the **Settings** page no longer removes its blank lines. A run of consecutive line breaks was collapsed into one on the way to disk, so a blank line between two sections of a properties file, or an empty row in a CSV data file, was gone after **Save**. Each line break is now written back as one CRLF, blank lines included.
- The **Externalize** page under **Tools** no longer breaks its own round trip when a field value contains a comma or a double quote. Such a value was written to `MappingData.csv` without quoting, so its row gained extra columns, and **Internalize** then failed with an error even on an unedited export. Values are now written and read as standard CSV, so an export edited in a spreadsheet and internalized keeps every value in its own column, and a hand-edited row with the wrong number of columns is refused with an error that names the row.
- Importing a **zip of mappings** no longer fails outright because one entry inside it has a name that cannot be used as a file name. Such a name (one holding a NUL byte, which no platform accepts, or, on Windows, one holding `:` `\` `<` `>` `"` `|` `?` or `*`) previously ended the whole import with `HTTP 500`: the rest of the zip was not read, and for an HTTP or gRPC mapping zip that meant none of its mappings were imported at all. The offending entry is now skipped on its own and everything else in the zip imports as normal, with `Ignoring zip entry <name> (its name is not a usable file name)` written to the [log](https://trafficparrot.com/documentation/5.65.x/logging.html) so that nothing is dropped without a record. The answer to the import is the same as when nothing was skipped: for the HTTP import, `HTTP 200` and the ids of the mappings that were imported, with no warning for the entry that was not. A script that checks only the status code or the answer body therefore does not see the skip; the log line is the only record. This applies to the [HTTP](https://trafficparrot.com/documentation/5.65.x/http.html#import-http-usage), [gRPC](https://trafficparrot.com/documentation/5.65.x/grpc.html#import-grpc-usage), [JMS](https://trafficparrot.com/documentation/5.65.x/jms.html#import-jms-usage), native IBM® MQ and [file message](https://trafficparrot.com/documentation/5.65.x/filemessage.html#import-file-usage) mapping imports alike, and to a `.zip` of proto files uploaded with [Import skeleton](https://trafficparrot.com/documentation/5.65.x/grpc.html#edit-grpc-skeletons). The name that a zip entry may carry is a property of the platform Traffic Parrot runs on, so this most often shows up when a zip written on Linux or macOS, where such a name is legal, is imported into Traffic Parrot running on Windows. An ordinary exported zip is unaffected and imports exactly as before.
- Importing a **zip of mappings** now restores a response body file to the sub-directory it was exported from. A mapping whose response is read from a file below `__files` (a `bodyFileName` such as `grpc/response.json`) exports with the file at that path, but the import wrote the file at the top of `__files` under its bare name, so on an instance that did not already hold the file the imported mapping could not find it: an HTTP mapping answered `HTTP 500` naming the missing file, and a gRPC mapping answered `INTERNAL` with `<bodyFileName> not found`, until the file was moved by hand. The file is now written where the mapping expects it. This applies to the [HTTP](https://trafficparrot.com/documentation/5.65.x/http.html#import-http-usage) and [gRPC](https://trafficparrot.com/documentation/5.65.x/grpc.html#import-grpc-usage) mapping imports; the JMS, native IBM® MQ and file message imports already kept the path. An exported zip whose body files all sit at the top of `__files` is unaffected and imports exactly as before.
- Exporting the HTTP mappings now writes every mapping in the **zip** as a `.json` file, so an exported zip unpacked into a WireMock root directory loads every mapping it holds. A mapping keeps the name it was given, whether it arrived through the admin API or in a mapping file that carries its own `name`, as a stub recorded by WireMock does, and the export previously used that name as the file name as it stood, so a mapping named `Get order 1001` became the entry `mappings/Get order 1001`, with no extension. A mapping file with no `name` of its own is named after the file, and a mapping saved from the [Add/Edit HTTP mappings](https://trafficparrot.com/documentation/5.65.x/http.html#add-edit-http-mappings) editor is always named `<name>.json`, so those already carried the extension. Traffic Parrot imported such a zip either way, but WireMock reads only files with the `.json` extension from its `mappings` directory, so it silently loaded none of the mappings exported without it. Every entry is now written as `mappings/<mapping name>.json`, whether the zip is downloaded with the **Download Mappings** button on the [Export](https://trafficparrot.com/documentation/5.65.x/http.html#export-http-usage) page or through the [Management API](https://trafficparrot.com/documentation/5.65.x/user_guide.html#management-apis). Nothing else in the zip changes: importing it back into Traffic Parrot is unchanged, and a mapping whose name already ends in `.json` is exported exactly as before.
- The gRPC [Add mapping](https://trafficparrot.com/documentation/5.65.x/grpc.html#edit-grpc) form no longer carries an exception mapping's metadata and error details onto a successful mapping saved after it. The form keeps its values after a save, and switching from the **Exception** tab to the **Successful** tab left the exception metadata and error details in place behind it, so the next mapping saved from the Successful tab replied with status `OK` but with the earlier mapping's metadata and a `grpc-status-details-bin` header attached to the reply. Switching to the Successful tab now clears them, and a mapping saved with a successful status never carries error details, whichever tab it was saved from.
- Clearing the HTTP stub mappings no longer fails when one of the mapping files holds more than one mapping. A file in the `mappings` directory may carry several mappings in a single JSON document (`{"mappings": [ ... ]}`) rather than one mapping per file, and Traffic Parrot loads and serves those mappings normally. Clearing them, however, answered `HTTP 500` and removed nothing. It went on answering `HTTP 500` for every attempt that followed until Traffic Parrot was restarted, including after the file itself had been deleted from disk. The mappings are now cleared, the answer is `HTTP 200`, and such a file is deleted whole, exactly as the mapping files holding a single mapping already were. A file holding several mappings that earlier clears left in place is deleted by the next clear, with every mapping it holds, so copy any such file you still need before clearing. This applies to all three endpoints that clear the mappings: `POST /api/http/__admin/mappings/reset`, `DELETE /api/http/__admin/mappings` and `POST /api/http/__admin/reset`. Saving or deleting one individual mapping that was loaded from a file holding several is unchanged and is still refused, because that one mapping cannot be rewritten out of the file it shares with the others; edit the file on disk instead. An installation whose mapping files each hold a single mapping is unaffected and clears exactly as before.
- Editing a **recorded gRPC mapping** in the gRPC [Add/Edit mapping](https://trafficparrot.com/documentation/5.65.x/grpc.html#edit-grpc-usage) form no longer discards the `CallId` and `MessageNumber` values that mapping carries. Traffic Parrot writes these as response headers in the mapping file when it records a streaming call, to group the messages belonging to one RPC call and to order them (see [gRPC streaming modes](https://trafficparrot.com/documentation/5.65.x/grpc.html#streaming-modes)). The form does not offer them for editing, and it previously saved the mapping back without them, so opening a recorded mapping and clicking **Save** dropped both values even when nothing had been changed. A recorded server streaming, client streaming or bidirectional streaming call then stopped replaying in order, or stopped replaying as one call, as soon as any single message of it had been edited in the GUI, and putting the values back meant editing the mapping file by hand or recording the call again. Every response header a mapping already holds is now carried through a save unchanged. A mapping that holds none, such as a unary mapping added by hand, is unaffected and saves exactly as before, and editing exception metadata is unchanged.
- Sending the gRPC management API (`POST /grpc/management/mapping` and `PUT /grpc/management/mapping/{id}`) a body that cannot be read as a mapping now returns `HTTP 400`, carrying the reason in the same `primingResult` field these endpoints already use to report a refusal, instead of `HTTP 500` and a stack trace in the [log](https://trafficparrot.com/documentation/5.65.x/logging.html). For example, a request matcher written as `{"containing": "b"}`, where the key the mapping grammar defines is `contains`, is answered with `{"containing":"b"} is not a valid match operation`; a body that is not JSON at all is answered with the reason it could not be parsed. Nothing is created or updated in either case, as before. The gRPC [Add/Edit mapping](https://trafficparrot.com/documentation/5.65.x/grpc.html#edit-grpc-usage) form is unaffected, because it cannot produce such a body.
- The message shown when a mapping cannot be saved because **another mapping already owns its file name** now quotes the name you typed, and names the file the two mappings land on. In the [Add/Edit HTTP mappings](https://trafficparrot.com/documentation/5.65.x/http.html#add-edit-http-mappings) editor the refusal previously quoted that file name where the mapping name belonged, so a mapping renamed to `orders:new` was refused with `Mapping 'orders_new.json' cannot be saved because its file name clashes with another mapping's.`, naming a string that appears nowhere on the form. It now reads `Mapping 'orders:new' cannot be saved because its file name 'orders_new.json' clashes with another mapping's.` and goes on, as before, to explain how a file name is derived from a mapping name, so you can see both the name to change and the file the two names collapse onto. The [MCP](https://trafficparrot.com/documentation/5.65.x/generate-mocks-with-ai-agent.html#mcp-tools) `create_mapping` and `update_mapping` tools return the same message; there the name was already reported correctly, and the file name is the new part. Which saves are refused is unchanged, and so are the mapping name Traffic Parrot stores and the file it writes.
- **WebSocket mappings** are now loaded from the **selected scenario**. Every scenario directory has always been created with a `websocket-mappings` folder beside its `mappings`, `grpc-mappings`, `jms-mappings`, `ibm-mq-mappings` and `file-mappings` folders, but the WebSocket simulator only ever read the folder at the traffic files root, so a mapping placed in a scenario's folder was silently ignored: it did not appear on the WebSocket **Add/Edit** page, nothing was written to the [log](https://trafficparrot.com/documentation/5.65.x/logging.html), and a client that connected to its channel was accepted and then got no reply. Mappings are now loaded from `websocket-mappings` in the selected scenario, or from the traffic files root when no scenario is selected, as the other protocols' mappings are, and the WebSocket **Add/Edit** page and the `/websocket/management` API follow a scenario switch together with the virtual service. A mapping saved while a scenario is selected is written to that scenario's folder. If you have kept WebSocket mappings at the traffic files root and work with a scenario selected, move them into that scenario's `websocket-mappings` folder, because the root folder now serves only when no scenario is selected. A mapping left at the root while a scenario is selected is not served: it is not listed on the **Add/Edit** page, nothing is written to the [log](https://trafficparrot.com/documentation/5.65.x/logging.html), and a client that connects to its channel is accepted and then gets no reply. The file is not moved or deleted. The traffic files root is the [default scenario](https://trafficparrot.com/documentation/5.65.x/user_guide.html#scenarios-overview), the one that is active when Traffic Parrot starts, so an installation that has never activated another scenario is unaffected. A mapping file written by an earlier version of the WebSocket simulator, whose only top-level property is `webSocket`, is not in the current mapping format: it loads as a catch-all mapping that matches incoming frames and replies nothing, and Traffic Parrot now writes a warning naming the file to the [log](https://trafficparrot.com/documentation/5.65.x/logging.html), once per file, with the instruction to delete it, because such a file carries no id and cannot be edited or deleted from the **Add/Edit** page. See [WebSocket System Simulation Properties](https://trafficparrot.com/documentation/5.65.x/properties.html#websocket-properties).
- A mapping with a `scenarioName` that is **added through the API while Traffic Parrot is running** is now listed once by `GET /api/http/__admin/scenarios`. Previously it appeared twice in that scenario's `mappings` array, so a test or tool that counted a scenario's mappings saw every mapping added at runtime twice. Matching, the scenario's state, its `possibleStates` and its transitions were unaffected, and mappings loaded from the `mappings` directory at startup were always listed once.
- Importing a **zip of mappings** through `POST /http/management/importMappings` or the HTTP [Import](https://trafficparrot.com/documentation/5.65.x/http.html#import-http-usage) page now records the zip's file name on each mapping it registers, as `tp.import.source` in the mapping's metadata, as the HAR, OpenAPI, RAML and Pact imports already did, and importing a zip of the same name again first removes the mappings the previous import registered, so a re-import replaces its earlier import; previously nothing linked a re-imported mapping to its earlier copy, and whether it replaced that copy or was added beside it depended on the file each was written to. A mapping registered any other way is not removed by an import, although an imported mapping whose name ends in `.json` is written to the file of that name, so importing an instance's own export writes over the file of the mapping it was exported from. The response is unchanged: the ids of the imported mappings. See [Importing via REST API](https://trafficparrot.com/documentation/5.65.x/http.html#import-http-rest-api) on the HTTP page.
- A backslash now escapes a `{{...}}` expression that is the **first** one in an HTTP response body. [Disabling {{...}}](https://trafficparrot.com/documentation/5.65.x/dynamic.html#disabling) documents `\{{...}}` as the way to leave one expression as written, but when the escaped expression was the first in the body the backslash was kept in the output and the expression was substituted anyway; an escaped expression anywhere after the first was already left alone. The escape now works in every position, so a body that starts with an escaped expression renders it as written, without the backslash. A body whose first expression has no backslash immediately before it renders exactly as before. Any run of backslashes immediately before the first expression is now read as that escape, whatever it was written for, exactly as one before any later expression already was: a body starting `C:\temp\{{name}}` rendered `C:\temp\VALUE` and now renders `C:\temp{{name}}`, and `C:\temp\\{{name}}` renders `C:\temp\{{name}}`.
- The [MCP endpoint](https://trafficparrot.com/documentation/5.65.x/mcp.html) now refuses a request that carries an `Origin` header naming a web origin that is not listed in [`trafficparrot.mcp.allowedOrigins`](https://trafficparrot.com/documentation/5.65.x/properties.html#mcp-properties), whichever authenticator is in use and whether or not the login is on: `403`, with a JSON-RPC `-32002` error that quotes the origin and names the property, before the body is read. Only a browser sends that header, so an assistant that speaks HTTP directly is unaffected; the list ships empty, so a browser-hosted MCP client is refused until you name its origin. The endpoint also answers the MCP `ping` request, with an empty `result`. See [From a browser](https://trafficparrot.com/documentation/5.65.x/mcp.html#access-origin).
- `{{#each request.pathSegments}}` in a [dynamic response](https://trafficparrot.com/documentation/5.65.x/dynamic.html#request-data-http) no longer renders an empty first item when the mapping's URL is a path template such as `/orders/{orderId}`. Without a path template the list was already correct, so the same request URL produced one list or the other depending only on how the mapping matched it. A template that indexed past the empty item, `{{request.pathSegments.[1]}}` for the first segment, now reads the second; change it to `[0]`.

<a id="version-5-62-1"></a>
## 5.62.1 – 26 Aug 2026

### Features

- The **messaging** Add/Edit mapping editors ([JMS](https://trafficparrot.com/documentation/5.65.x/jms.html#edit-jms), [native IBM® MQ](https://trafficparrot.com/documentation/5.65.x/ibmmq.html#edit-mq) and [file message](https://trafficparrot.com/documentation/5.65.x/filemessage.html#add-edit-file-message-mappings)) now offer the **[NOT (negate a matcher)](https://trafficparrot.com/documentation/5.65.x/request_matching.html#not-in-messaging-editor)** request body matcher, as the HTTP and gRPC editors already do. Choosing it in the *Request body* dropdown replaces the request body field with a **NOT child matcher** sub-editor where you pick the matcher to negate and type its value, so you can stub "everything except this" without hand-editing the mapping JSON. The child matcher dropdown offers the leaf matchers that can be negated (`equalTo`, `contains`, `doesNotContain`, `matches`, `doesNotMatch`, `equalToJson`, `matchesJson`, `matchesJsonPath`, `equalToXml`, `matchesXml` and `matchesXPath`); the SWIFT and FIX field matchers and the JMS-only `binaryEqualTo` matcher are not offered as children and are still negated by writing the matcher in the mapping JSON. The mapping is saved as a nested `"bodyMatcher": {"not": {"contains": "CANCELLED"}}`, reopening it restores the body matcher, child matcher and child value into the sub-editor, and the messaging mappings list now shows a composite matcher as a readable one-line summary such as `not (contains 'CANCELLED')` instead of the raw matcher JSON (matching how the HTTP and gRPC mapping lists and the messaging import preview already render it). The `and` and `or` operators are offered in the same dropdown; see [Authoring `and` and `or` in the messaging editor](https://trafficparrot.com/documentation/5.65.x/request_matching.html#and-or-in-messaging-editor).
- The **messaging** Add/Edit mapping editors ([JMS](https://trafficparrot.com/documentation/5.65.x/jms.html#edit-jms), [native IBM® MQ](https://trafficparrot.com/documentation/5.65.x/ibmmq.html#edit-mq) and [file message](https://trafficparrot.com/documentation/5.65.x/filemessage.html#add-edit-file-message-mappings)) now also offer the **[AND (all sub-matchers match)](https://trafficparrot.com/documentation/5.65.x/request_matching.html#and-or-in-messaging-editor)** and **OR (any sub-matcher matches)** request body matchers, so all three logical operators are now offered in the request body matcher dropdown of every mapping editor that has one (see [Logical operators](https://trafficparrot.com/documentation/5.65.x/request_matching.html#logical-operators)). Choosing `AND` or `OR` in the *Request body* dropdown replaces the request body field with a **Sub-matchers** panel holding two rows, each one a matcher plus the value to match it against. **Add sub-matcher** appends a row and the bin button on a row removes it, down to the two sub-matchers that `and` and `or` need to mean anything. A row's matcher dropdown offers the same leaf matchers as the NOT child matcher dropdown (`equalTo`, `contains`, `doesNotContain`, `matches`, `doesNotMatch`, `equalToJson`, `matchesJson`, `matchesJsonPath`, `equalToXml`, `matchesXml` and `matchesXPath`), and a sub-matcher value is a multi-line field, so a multi-line JSON or XML body can be typed or pasted straight into a sub-matcher row and keeps its line breaks when the mapping is saved and reopened. The mapping is saved as `"bodyMatcher": {"and": [{"contains": "ORDER-"}, {"doesNotContain": "DRAFT"}]}`, reopening it restores one row per sub-matcher in the order it was saved, and the messaging mappings list shows the matcher as a readable one-line summary such as `and (contains 'ORDER-', doesNotContain 'DRAFT')` instead of the raw matcher JSON.
- A **[JMS response body can now be served from a file](https://trafficparrot.com/documentation/5.65.x/jms.html#edit-jms-response-body-file)** in the `__files` directory, the messaging counterpart of an [HTTP file-backed response](https://trafficparrot.com/documentation/5.65.x/http.html#file-backed-responses). Set `bodyFileName` on a JMS mapping's `response` (a path under `__files`, resolved against the `__files` directory beside the mapping's `jms-mappings` directory, per-scenario for scenario-scoped mappings) in place of an inline `text` value; the two are mutually exclusive. Setting both, or referencing a file that does not exist, is rejected at load time and the messaging mappings fail to load until it is corrected (the error names the mapping and the missing file). The file's contents are UTF-8 text and are run through the same [Handlebars templating](https://trafficparrot.com/documentation/5.65.x/dynamic.html#extract-data) as an inline text body, so a body file can reference the incoming request (for example `{{request.body}}`) and use the response [helpers](https://trafficparrot.com/documentation/5.65.x/dynamic.html#extension-functions). In the JMS mapping editor a file-backed response shows a read-only **Response from file:** note and loads the file's contents into the editable response body field; saving writes your edit back to the file and keeps the `bodyFileName` reference, so the body stays in the file rather than being copied inline. Exporting a scenario bundles the referenced body file, so file-backed JMS mappings round-trip through [import and export](https://trafficparrot.com/documentation/5.65.x/jms.html#import-export-jms-mappings). [File message](https://trafficparrot.com/documentation/5.65.x/filemessage.html#add-edit-file-message-mappings) mappings can reference a response body file in exactly the same way. **Native IBM® MQ mappings cannot**: `bodyFileName` is not part of the IBM® MQ response format, so an IBM® MQ response body stays inline. Support for binary (bytes) response bodies read from a file will follow. See [Response body from a file](https://trafficparrot.com/documentation/5.65.x/jms.html#edit-jms-response-body-file) on the JMS page.
- A gRPC [request body matcher](https://trafficparrot.com/documentation/5.65.x/grpc.html#request-body-matchers) can now read the value it matches against from an external `__files` file through a `bodyFileName` reference: the same [file-backed request body matcher](https://trafficparrot.com/documentation/5.65.x/http.html#request-body-file) already available for HTTP. Traffic Parrot resolves the file when the mapping loads and matches against its contents on replay exactly as it would an inline value, and the gRPC mappings list now shows the resolved file content (or, for a binary file, the matcher and the file path) in the **Request message** column instead of the raw `bodyFileName` reference. Editing a file-backed gRPC request matcher from the mapping editor is covered by the [Switch to file and Switch to inline](https://trafficparrot.com/documentation/5.65.x/grpc.html#request-body-matchers) entry below.
- The HTTP and gRPC [mappings list](https://trafficparrot.com/documentation/5.65.x/http.html#add-edit-http-mappings) now shows the matcher together with the `bodyFileName` **path** for a [request body matcher](https://trafficparrot.com/documentation/5.65.x/http.html#request-body-file) whose value is read from a **binary** file (an image, PDF or other non-text file), for example `binaryEqualTo 'payload.png'`, truncated to fit the column with the full path on hover, instead of a fixed placeholder that read the same for every binary file and so identified none of them. This applies to the HTTP *Request body* column, the gRPC [*Request message*](https://trafficparrot.com/documentation/5.65.x/grpc.html#request-body-matchers) column and the rows' hover summaries, and it mirrors what the [response body column](https://trafficparrot.com/documentation/5.65.x/http.html#file-backed-responses-in-list) already shows for a binary file-backed response body. Because the mappings list searches the text it displays, a mapping whose request body matcher is backed by a binary file can now also be found by typing the file name into the list search. A request body matcher backed by a **text** file still shows the file's content inlined, exactly as before.
- A [gRPC request payload](https://trafficparrot.com/documentation/5.65.x/grpc.html#request-body-matchers) can now be moved into, and out of, an external `__files` file from the **mapping editor**, rather than only by hand-editing the mapping JSON on disk. Opening a **saved** gRPC mapping whose request payload is inline shows a **Switch to file** button beneath the payload field; clicking it reveals a file name field pre-filled with a name derived from the mapping, and **Save** writes the payload to that file in `__files` and rewrites the matcher to the `bodyFileName` reference form. Re-opening the mapping shows a **Content from file:** note naming the file, loads the file's contents into the payload field so you can edit them in place, and offers **Switch to inline** to detach the reference and store the payload in the mapping again. A warning is shown when the file is shared with other mappings, because saving changes the request matcher for all of them. This matches what the [HTTP editor](https://trafficparrot.com/documentation/5.65.x/http.html#request-body-file) already did, and the [gRPC response body](https://trafficparrot.com/documentation/5.65.x/grpc.html#edit-grpc-file-backed-response) controls. The controls appear only for a mapping that has already been saved, and only for a single in-scope text matcher: a binary matcher or a request with several body patterns stays read-only in the editor, as on the HTTP form. Note that the file name may include forward-slash subdirectories, which resolve under `__files`, so `requests/example.json` is saved as `__files/requests/example.json` - the same as a response body file. A name that would resolve outside `__files` is rejected.
- The request body **[Switch to file](https://trafficparrot.com/documentation/5.65.x/http.html#request-body-file-in-gui)** and **Switch to inline** controls in the mapping editor now cover three more request body matchers: **matches JSON** (`matchesJson`), **matches GraphQL** (`matchesGraphQL`) and **matches JSON schema** (`matchesJsonSchema`). Traffic Parrot already matched all three against a value read from an external `__files` file, but the editor did not offer to move one out to a file, so a large JSON body, GraphQL query or JSON Schema had to be externalised by hand-editing the mapping JSON on disk. This matters most in the [gRPC editor](https://trafficparrot.com/documentation/5.65.x/grpc.html#request-body-matchers), where **matches JSON representation** (`matchesJson`) is the matcher gRPC mappings most often use for the request payload. Saving keeps the matcher you chose rather than swapping it for `equalToJson`, so what the mapping matches is unchanged.
- The **[Static Files](https://trafficparrot.com/documentation/5.65.x/http.html#static-files-browser)** page is now listed in the **gRPC**, **JMS** and **Files** menus, as it already was in the **HTTP** menu. All four entries open the same page, because `__files` is a single directory shared by every protocol within a scenario, so a file there can back a gRPC request payload, a gRPC response, a [JMS](https://trafficparrot.com/documentation/5.65.x/jms.html#edit-jms-response-body-file) or [file-message](https://trafficparrot.com/documentation/5.65.x/filemessage.html#add-edit-file-message-mappings) response body, or an HTTP response equally. Previously the page could only be reached from the HTTP menu (or from the **Manage files** link in the gRPC response body area), which was easy to miss when working entirely in another protocol. The **WebSocket** and **IBM® MQ** menus deliberately do not carry the entry: those two do not resolve a `bodyFileName`, so the entry would advertise a capability they do not have.
- Traffic Parrot now serves a **[Model Context Protocol (MCP) endpoint](https://trafficparrot.com/documentation/5.65.x/mcp.html)**, so an AI assistant can connect to a running instance and read what it holds instead of working only from files you paste into the conversation. Traffic Parrot serves it itself, so there is nothing extra to install and no separate process to keep running: it listens on the management port (`8080` by default) at `/mcp` and takes JSON-RPC 2.0 over HTTP POST, at the bare endpoint URL MCP clients are configured with rather than under `/api`. A connecting client completes the [`initialize` handshake](https://trafficparrot.com/documentation/5.65.x/mcp.html#handshake), which negotiates the protocol revision and reports the instance's own version and its capabilities: the client is answered the revision it asked for when that is one Traffic Parrot speaks (`2025-11-25`, `2025-06-18`, `2025-03-26`, `2024-11-05` or `2024-10-07`), and the newest, `2025-11-25`, when it asked for an unknown revision or for none at all. The client then lists [twelve tools](https://trafficparrot.com/documentation/5.65.x/mcp.html#tools). Six only read (`list_mappings`, `get_mapping`, `list_received_requests`, `report_coverage`, `list_scenarios` and `verify_mapping_matches`), covering the mappings being served, the request journal, endpoint coverage, the defined scenarios, and whether received traffic still matches the mappings loaded now. The other six change something: `create_mapping`, `update_mapping` and `delete_mapping` change what the **running** instance serves **and write the change through to the selected scenario's mapping files**, so a scenario directory kept in version control will show it as a local change; `select_scenario` switches which scenario is being served, and so decides what every other tool reads and writes; `generate_mappings_from_openapi` builds mappings from a specification file already in the instance's OpenAPI directory, writing them through to the scenario's mapping files in the same way; and `cleanup_mappings` turns a recording into a flexible mock in a **new** scenario, leaving the recording untouched. [Running a tool](https://trafficparrot.com/documentation/5.65.x/mcp.html#running-a-tool) (`tools/call`) returns MCP content blocks, and only the advertised tools can be called. **Every tool that can lose work takes `dryRun`, which defaults to `true`**, so a call that does not say otherwise previews the change and tells the assistant how to commit it. A preview changes nothing in Traffic Parrot, but it is not inert: `generate_mappings_from_openapi` reads the specification file and fetches any `externalValue` example URL in it during a preview exactly as it does when applying. By default the endpoint [accepts requests from the local machine only](https://trafficparrot.com/documentation/5.65.x/mcp.html#access) and needs no token; to reach it from elsewhere (notably Traffic Parrot in a container with a published port), set `trafficparrot.mcp.authenticator=BEARER_TOKEN` and `trafficparrot.mcp.token`, and send `Authorization: Bearer <token>`. Otherwise, anything that can reach the management port can reach this endpoint, so run Traffic Parrot on your own machine or a [trusted network](https://trafficparrot.com/documentation/5.65.x/generate-mocks-with-ai-agent.html#harden-first). Switching on the web UI login (`trafficparrot.gui.security.mode=LOGIN_PROPERTIES`) covers `/mcp` as well, so the client must then also send the HTTP BASIC credentials from `trafficparrot.gui.login.properties`; that refusal is an HTTP 401 whose JSON-RPC error names the login property and the credentials file, as against the HTTP 403 the MCP authenticator returns.
- The HTTP [Mapping cleanup](https://trafficparrot.com/documentation/5.65.x/http.html#http-cleanup) results now name the **mapping directories the cleaned scenario does not carry**. Cleanup copies the source scenario's HTTP mappings and its `__files` directory and nothing else, so any JMS, native IBM® MQ, file message, gRPC or WebSocket mappings the scenario holds stay behind in the source scenario. That has always been the case, and it is deliberate (the cleanup conventions are HTTP conventions and have no meaning for a JMS or a gRPC mapping); what is new is that cleanup now tells you instead of leaving you to notice. A warning panel headed **Mappings the cleaned scenario does not serve** appears above the result counters with one entry per directory, naming it and the number of files that stayed behind, for example `jms-mappings (3 file(s)) - not copied into the cleaned scenario`. Nothing is lost: cleanup never modifies the source scenario, and the warning is there so the cleaned scenario is not mistaken for a complete replacement of the recording it came from and the other mappings dropped at the next promotion. Only a directory that actually holds files is listed, so an HTTP-only scenario shows no panel; the count is of files rather than mappings, because one mapping file can hold several mappings. The same list is returned by [`POST /api/http/cleanup/execute`](https://trafficparrot.com/documentation/5.65.x/http.html#cleanup-api) in a new `droppedMappingDirectories` field, and by the [`cleanup_mappings`](https://trafficparrot.com/documentation/5.65.x/mcp.html#tools) MCP tool, whose `dryRun` preview reports the same entries a real run would. It is a warning rather than an error: the cleanup succeeded and the `errors` field stays empty. See [What the cleaned scenario does not carry](https://trafficparrot.com/documentation/5.65.x/http.html#cleanup-not-copied).
- A [JMS](https://trafficparrot.com/documentation/5.65.x/jms.html#edit-jms) request body matcher can now read the value it matches against from an external `__files` file through a `bodyFileName` reference, the messaging counterpart of the [HTTP](https://trafficparrot.com/documentation/5.65.x/http.html#request-body-file) and [gRPC](https://trafficparrot.com/documentation/5.65.x/grpc.html#request-body-matchers) file-backed request matchers. Traffic Parrot resolves the file when the mapping loads and matches against its contents on replay exactly as it would an inline value, so a large expected payload can live in a file beside the mapping instead of inside it. [Exporting](https://trafficparrot.com/documentation/5.65.x/jms.html#import-export-jms-mappings) a scenario bundles the files referenced by request matchers as well as those referenced by response bodies, so a file-backed matcher round-trips through import and export. A `bodyFileName` is supported only on a matcher at the top level of the request: nesting one inside an `and`, `or` or `not` operator is refused when the mapping loads, with an error naming the mapping and the matcher. Native IBM® MQ and file-message request matchers keep their expected values inline.
- Traffic Parrot now **publishes the JSON Schemas that describe its own mapping formats**, served from the management port (`8080` by default), so a tool (or an AI coding agent) can fetch them from the very instance it is targeting and check a mapping before loading it. `/schemas/index.json` is a machine-readable index with one entry per mapping format ([HTTP](https://trafficparrot.com/documentation/5.65.x/http.html), which also covers [gRPC](https://trafficparrot.com/documentation/5.65.x/grpc.html); [JMS](https://trafficparrot.com/documentation/5.65.x/jms.html); native [IBM® MQ](https://trafficparrot.com/documentation/5.65.x/ibmmq.html); and [file messages](https://trafficparrot.com/documentation/5.65.x/filemessage.html)), each carrying that schema's URL, its version, and the directory the format's mapping files live in; the schemas themselves are served beside it, for example `/schemas/http-mapping.schema.json`. They ship inside Traffic Parrot, so they always describe the version you are actually running. Alongside them, `/helper-policy.json` publishes the **Handlebars helper safety policy**: which response-templating helpers are safe to use, and which are denied because they can run arbitrary code (`executeProcess` and `evaluate`). [`trafficparrot validate`](https://trafficparrot.com/documentation/5.65.x/http.html#validate-cli) can enforce that policy as well as the schemas: set `trafficparrot.validate.helper.policy.check` and validation fails when a mapping uses a denied helper, which is worth switching on for mappings a machine wrote. See [Point the agent at the mapping schema](https://trafficparrot.com/documentation/5.65.x/generate-mocks-with-ai-agent.html#download-schemas).

### Documentation

- Added a **[Generate mocks with your own AI agent](https://trafficparrot.com/documentation/5.65.x/generate-mocks-with-ai-agent.html)** recipe page. It shows how to have your own AI coding agent (Claude Code, Cursor, or any assistant that can fetch a URL and call an HTTP API) write Traffic Parrot mappings for you: ground the agent on the mapping [JSON Schema](https://json-schema.org/) and the helper policy your instance serves, plus your own API contract, have it check the mapping against the schema, then load it through the admin API. The page opens with a Claude Code quick start and a copy-paste starter prompt that runs end to end against the community [Train Travel API](https://github.com/bump-sh-examples/train-travel-api) sample, so you can try it as-is before swapping in your own contract. It also covers running on a trusted network, the Handlebars helper deny-list (`helper-policy.json`) and its opt-in `trafficparrot.validate.helper.policy.check` enforcement in [`trafficparrot validate`](https://trafficparrot.com/documentation/5.65.x/http.html#validate-cli), and why an API contract handed to a language model is untrusted input. The mapping-creation endpoints it uses are documented in the [Management API specification](https://trafficparrot.com/documentation/5.65.x/downloads/openapi.yaml).
- Expanded the **[Management API documentation](https://trafficparrot.com/documentation/5.65.x/openapi/index.html)** to cover ten more management endpoints: priming an HTTP mapping and downloading a file from the scenario's `__files` directory, exporting the HTTP mappings, listing the gRPC mappings, and listing, creating, editing and deleting [JMS](https://trafficparrot.com/documentation/5.65.x/jms.html) and [native IBM® MQ](https://trafficparrot.com/documentation/5.65.x/ibmmq.html) mappings. Each carries its request and response shapes and the status codes it returns, including the `HTTP 409` the JMS and native IBM® MQ endpoints return while the virtual service is running; stop it before adding, editing or deleting a mapping. The WireMock-compatible admin API continues to be covered by reference to [WireMock's own API documentation](https://wiremock.org/docs/api) rather than restated here, and the [raw specification](https://trafficparrot.com/documentation/5.65.x/downloads/openapi.yaml) remains available to download.

### Fixes

- Saving a gRPC mapping with an empty or malformed method name (the `package.Service/Method` value) now reports a clear validation message instead of failing with an internal server error. In the gRPC [Add/Edit mapping](https://trafficparrot.com/documentation/5.65.x/grpc.html#edit-grpc-usage) form an inline message, `Enter a fully-qualified gRPC method as package.Service/Method`, appears beneath the **gRPC method** field and blocks the save; the gRPC management API (`POST /grpc/management/mapping` and `PUT /grpc/management/mapping/{id}`) returns `HTTP 400` with the same message instead of `HTTP 500`. Previously an empty or malformed method produced a raw `HTTP 500` and stack trace. Mappings imported from an exported zip are unchanged.
- The ActiveMQ [internal broker](https://trafficparrot.com/documentation/5.65.x/jms.html) no longer caps the TCP connection handshake allowance at 10 seconds. Traffic Parrot asks for 60 seconds when it connects to the internal broker, but the broker itself had never advertised a matching allowance, and the OpenWire protocol settles on the shorter of the two ends' values, so 10 seconds was always the limit in force, and a connection slow to complete its handshake (a heavily loaded machine, or many connections opening at once) could be dropped with an inactivity error. The broker now advertises the same 60 seconds, so Traffic Parrot's own connections get the allowance they ask for, and an application that configures a longer allowance on its own ActiveMQ client is no longer capped to 10 seconds by the internal broker. An application left on the ActiveMQ client default is unaffected. AMQP connections are unaffected; this applies to the TCP (OpenWire) transport only.
- The target scenario name given to [HTTP mapping cleanup](https://trafficparrot.com/documentation/5.65.x/http.html#http-cleanup) must now be a name inside the instance's `scenarios` directory. Previously a name that resolved somewhere else (one climbing out of that directory with `..`, or an absolute path) was accepted, and the cleaned mappings were written to wherever it pointed. Such a name is now refused: the **Cleanup** page reports `Target scenario '...' must be a name inside the scenarios directory` instead of running, and [`POST /api/http/cleanup/execute`](https://trafficparrot.com/documentation/5.65.x/http.html#cleanup-api) returns `HTTP 400` carrying the same message in its `error` field, instead of `HTTP 200` after writing the mappings. An ordinary scenario name is unaffected and behaves exactly as before.
- A [request body matcher that reads its value from a file](https://trafficparrot.com/documentation/5.65.x/http.html#request-body-file) (a `bodyFileName` reference) must now name a file inside the mapping's `__files` directory. Previously a `bodyFileName` that resolved outside it, whether by climbing out with `..` or by giving an absolute path, was accepted, and Traffic Parrot read that out-of-directory file and matched against its contents. Such a reference is now rejected when the mapping loads. An ordinary `bodyFileName` under `__files` is unaffected and behaves exactly as before.
- Importing a **zip of mappings** now refuses any entry that would be written outside the directory being imported into. Previously an entry whose path climbed out with `..` was extracted to wherever it pointed, so importing a zip from an untrusted source (which the admin GUI allows in a single click) could create or overwrite a file anywhere the Traffic Parrot process could write. Every file written during an import is now checked to be inside the target directory before it is created. An entry that fails the check is skipped on its own, with `Ignoring zip entry <name> (its name resolves outside the <directory> directory)` written to the [log](https://trafficparrot.com/documentation/5.65.x/logging.html), and the rest of the zip imports as normal. An ordinary exported zip is unaffected and imports exactly as before.
- **Renaming a scenario** now requires both the existing and the new name to be names inside the instance's `scenarios` directory. Previously a name that climbed out of that directory with `..`, or gave an absolute path, was accepted and the scenario directory was moved to wherever it pointed. Such a name is now refused, and a rename rejected for this or any other validation reason returns `HTTP 412` carrying the reason instead of `HTTP 500` and a stack trace. An ordinary scenario name is unaffected.
- Importing a **[gRPC](https://trafficparrot.com/documentation/5.65.x/grpc.html) skeleton** now refuses a file name that would resolve outside the scenario's gRPC mappings directory, instead of writing the generated mapping there.
- A path that reads as being inside a permitted directory but points outside it through a **symbolic link** is now refused, where it was previously accepted. This applies wherever Traffic Parrot checks that a path stays inside a directory, including the mapping conflict preview.
- The in-GUI **configuration file editor** now refuses a path that belongs to neither of the directories it manages, rather than falling through and editing it anyway.
- The [Static Files](https://trafficparrot.com/documentation/5.65.x/http.html#static-files-browser) page now takes **messaging mappings** into account when it decides whether a file is still in use. Deleting or renaming a file referenced only by a JMS or file-message mapping was previously allowed without warning, because the check looked at HTTP and gRPC mappings only, and the mapping was left pointing at a file that no longer existed. The **orphan** badge now counts references from every protocol, so a file shown as orphaned really is unreferenced.
- Two mappings can no longer be saved under the same **mapping file name**. A mapping's file is named after the mapping, so saving a second mapping whose name produces a file name already in use previously overwrote the first; such a save is now refused with a message asking you to rename the mapping, on the GUI, the admin API and the [MCP tools](https://trafficparrot.com/documentation/5.65.x/mcp.html#tools) alike. Mappings you already have are unaffected: importing and starting up are unchanged, so a scenario that already holds two mappings sharing a file name keeps loading exactly as before; what changes is that re-saving one of them from the editor now asks you to rename it first. The two shapes to expect are two mapping names that produce the same file name (`orders/new` and `orders:new` both become `orders_new.json`) and, on Linux, two names differing only in case. Relatedly, resetting the admin API while two mappings already shared a file name returned `HTTP 500`; it now completes.
- Three fixes to the **log viewer**: the line-number gutter stays aligned with wrapped lines instead of drifting out of step with them; a log file with CRLF line endings no longer renders a stray carriage return in every line; and querying the configured log appenders returns an answer instead of throwing, so the viewer can report which files it is reading.
- Exporting mappings to **CSV** no longer silently drops a mapping whose request-body matcher reads its expected body from an external file; it is exported with the rest.
- Generating a mapping from a captured `TEXT` message that has no body no longer fails with an internal error.
- Uploading a **protoset** file no longer poisons later gRPC proto scans: a bad upload is contained to that upload, instead of making every subsequent scan fail until Traffic Parrot is restarted.
- **Switch to file** now reports why it cannot externalise a request body it does not support, instead of appearing to work and silently doing nothing.
- A failed specification import now shows the reason the server gave, instead of the literal text `undefined`.
- Importing an [OpenAPI specification](https://trafficparrot.com/documentation/5.65.x/http.html#import-http-usage) whose operation declares a response without content (a `description` but no `content` block, as is usual for a `204 No Content` on a delete) now generates a mapping whose response has no body. Previously the generated response body was the literal text `*/*`, a placeholder that leaked out of the example generator, and the mock then served that text to every matching call. A response that does declare content, including a declared `*/*` media type carrying an example or a schema, is generated exactly as before. Upgrading does not rewrite mappings you already have; the change applies when a specification is imported, so re-importing the same specification regenerates such mappings without the placeholder body.
- The [file messaging](https://trafficparrot.com/documentation/5.65.x/filemessage.html) page now reports a mappings-load failure instead of waiting indefinitely for mappings that will never arrive.
- Property values that look like secrets are now **redacted** in the configuration Traffic Parrot writes to its log at startup, instead of being logged verbatim.

<a id="version-5-61-0"></a>
## 5.61.0 – 20 July 2026

### Features

- Added the ability to **import an [AsyncAPI](https://www.asyncapi.org/) specification** to create messaging mappings automatically (the messaging counterpart of importing an OpenAPI specification for HTTP). Go to **JMS** or **IBM® MQ** in the top navigation bar and click **Import AsyncAPI**, then upload a JSON or YAML **AsyncAPI 2.x or 3.0** document. Traffic Parrot parses the document's channels and operations and shows a preview of one mapping per importable operation (destination, queue/topic type, operation id, the example payload generated from the message schema, and a duplicate-status badge); you select exactly which operations to import with per-row checkboxes and an **Import Selected** count. A malformed, unsupported, or empty document reports a clear error and creates nothing. Each selected operation becomes a mapping (a [JMS mapping](https://trafficparrot.com/documentation/5.65.x/jms.html#import-asyncapi-jms) from the JMS page or a [native IBM® MQ mapping](https://trafficparrot.com/documentation/5.65.x/ibmmq.html#import-asyncapi-mq) from the IBM® MQ page) that serves the generated example payload, ready to refine in the editor. Both AsyncAPI 2.x and AsyncAPI 3.0 documents are supported with the JMS and IBM® MQ channel bindings; for a 3.0 document the destination is taken from the channel's `address` (falling back to the channel name). Both one-way `send`/`receive` operations and request-reply operations (those carrying an AsyncAPI 3.0 `reply` object) are imported: a request-reply operation receives the request on the operation's own channel and publishes the reply message's example on the reply channel's destination, shown in a **Reply destination** column in the preview. Other bindings (AMQP, Kafka, MQTT) and AsyncAPI 4.x are not yet supported, and advanced JSON Schema draft 2020-12 constructs that cannot yet be turned into an example render a placeholder payload.
- The headless **[`trafficparrot validate`](https://trafficparrot.com/documentation/5.65.x/http.html#validate-cli)** command now also checks your **messaging** mappings against your imported [AsyncAPI](https://www.asyncapi.org/) specifications, so a partially-mocked messaging API cannot silently drift from its contract; this is the messaging counterpart of the OpenAPI (HTTP) and proto (gRPC) coverage checks. It enumerates the operations declared in the AsyncAPI specifications under `<files-root>/asyncapi/` and reports any declared operation that has no backing JMS, native IBM® MQ or file-message mapping, for example `No mapping covers AsyncAPI operation: QUEUE:orders`. Operations are matched to mappings by destination identity (`TYPE:name`, where `TYPE` is `QUEUE` or `TOPIC`); for a request-reply operation coverage is measured on the inbound (request) destination only. Messaging drift participates in the same report and the same exit codes as the HTTP and gRPC checks (drift fails the build with exit code `1`). Destinations you deliberately leave unmocked can be excluded with a `messaging-coverage.properties` file (key `exclude.destinations`) in the files-root, and a stale allowlist entry for a destination not present in any AsyncAPI specification is itself reported as drift. See [Messaging coverage check](https://trafficparrot.com/documentation/5.65.x/jms.html#validate-messaging) on the JMS page.
- The add/edit messaging-mapping editor now has a **skeletons dropdown** that pre-fills a messaging mapping form from an operation in an imported [AsyncAPI](https://www.asyncapi.org/) specification (the messaging counterpart of the HTTP and gRPC [skeletons](https://trafficparrot.com/documentation/5.65.x/http.html#http-skeletons) dropdowns). Place AsyncAPI specifications (JSON or YAML, 2.x or 3.0) into the install's `asyncapi/` directory (or use the import button beside the dropdown to upload one), then pick an operation: the form's destination name, destination type (Queue/Topic radio) and request body/payload pre-fill. For a request-reply operation the option is labelled `<operationId> (request-reply)` and pre-fills both the request side and the reply side (a cloned response row); a one-way operation pre-fills the request side only. The dropdown appears in both the JMS and native IBM® MQ messaging editors. See [Messaging skeletons](https://trafficparrot.com/documentation/5.65.x/jms.html#messaging-skeletons-jms) on the JMS page and [on the IBM® MQ page](https://trafficparrot.com/documentation/5.65.x/ibmmq.html#messaging-skeletons-mq).
- Added the ability to **import an async-message [Pact](https://docs.pact.io/) contract** as JMS or native IBM® MQ messaging stubs (the messaging counterpart of [importing a Pact contract's HTTP interactions](https://trafficparrot.com/documentation/5.65.x/http.html#import-http-pact)). Go to **JMS** or **IBM® MQ** in the top navigation bar and click **Import message Pact**, then upload a Pact `.json` file. Both contract shapes are detected automatically: a specification **v3** contract's top-level `messages[]` array and a **v4** contract's `Asynchronous/Messages` `interactions[]` (whose example body is read from the `contents.content` envelope). An HTTP-only contract is rejected with a message pointing you to the HTTP Pact import. Traffic Parrot shows a preview of one mapping per message interaction (destination, queue/topic type, the message `description` as the operation id, the example `contents` payload, and a duplicate-status badge); you select exactly which messages to import with per-row checkboxes and an **Import Selected** count. A file that is not valid JSON or has no message interactions reports a clear error and creates nothing. Each selected message becomes a **one-way publish** mapping (a [JMS mapping](https://trafficparrot.com/documentation/5.65.x/jms.html#import-message-pact-jms) or a [native IBM® MQ mapping](https://trafficparrot.com/documentation/5.65.x/ibmmq.html#import-message-pact-mq)) that publishes the example payload on receipt of any message on its destination; Pact message interactions are fire-and-forget, so these are not request-reply stubs. Because a Pact message carries no destination, it is derived from the message's `metadata` (a `destination`, `queue` or `topic` key, where a `topic` key makes it a TOPIC) or, failing that, from the message's `description`; a description-derived destination raises a warning in the preview so you review it before importing. **Import message Pact** is licence-gated, available on a JMS or IBM® MQ licence respectively (the menu link does not appear without it). See [Import a message Pact contract](https://trafficparrot.com/documentation/5.65.x/jms.html#import-message-pact-jms) on the JMS page and [on the IBM® MQ page](https://trafficparrot.com/documentation/5.65.x/ibmmq.html#import-message-pact-mq).
- You can now **[import a Pact contract](https://trafficparrot.com/documentation/5.65.x/http.html#import-http-pact)** (consumer-driven contract, specification v2, v3 and v4) as HTTP stubs. Upload the Pact `.json` file on the HTTP [Import](https://trafficparrot.com/documentation/5.65.x/http.html#import-http-usage) page exactly as you would any other format; Traffic Parrot detects it automatically (no format to choose) and turns each HTTP interaction into a stub mapping through the same [preview, filter and select](https://trafficparrot.com/documentation/5.65.x/http.html#import-http-preview) flow used for HAR and OpenAPI/Swagger. The request (method, path, query, headers, body) becomes the request matchers and the response (status, headers, body) becomes the stubbed response; JSON request bodies are matched tolerantly. For v4 contracts the `Synchronous/HTTP` interactions are imported (their bodies are read from the v4 `body.content` / `body.contentType` envelope); everything else is imported the same way as for v2 and v3. Pact `matchingRules` are honoured where they map onto Traffic Parrot's request matchers (request header and path `regex`, default JSON-body type matching); other rules fall back to an exact match and the import reports a warning listing them. This HTTP import handles HTTP interactions only; Pact **message** (asynchronous) interactions, including the `Asynchronous/Messages` interactions of a v4 contract, are imported separately as [JMS](https://trafficparrot.com/documentation/5.65.x/jms.html#import-message-pact-jms) or [IBM® MQ](https://trafficparrot.com/documentation/5.65.x/ibmmq.html#import-message-pact-mq) messaging stubs (when a v4 contract mixes the two, the HTTP import brings in the HTTP interactions and skips the message ones with a warning). Response templating and provider verification / Pact Broker pull are not yet supported. See [Importing Pact contracts](https://trafficparrot.com/documentation/5.65.x/http.html#import-http-pact).
- You can now **[import an HTTP specification from a URL](https://trafficparrot.com/documentation/5.65.x/http.html#import-http-from-url)** instead of downloading it to disk first. Paste a specification URL into the URL field on the HTTP [Import](https://trafficparrot.com/documentation/5.65.x/http.html#import-http-usage) page and click **Fetch & preview**; Traffic Parrot fetches the document **server-side** and feeds it into the same content-based import pipeline as an uploaded file, so Swagger/OpenAPI, HAR and Pact specifications can be imported by URL exactly as they are from a file, each shown in the same [preview](https://trafficparrot.com/documentation/5.65.x/http.html#import-http-preview) before importing. RAML and WireMock ZIP specifications cannot yet be imported from a URL and must be imported from disk. The feature is **off by default** and must be enabled by an administrator: set [`trafficparrot.http.importfromurl.enabled`](https://trafficparrot.com/documentation/5.65.x/properties.html#extension-system-properties) to `true` and list the hosts Traffic Parrot may fetch from in [`trafficparrot.http.importfromurl.allowedHosts`](https://trafficparrot.com/documentation/5.65.x/properties.html#extension-system-properties), a **default-deny** allow-list (with the feature enabled but the allow-list empty, every fetch is refused). Because the fetch originates from the Traffic Parrot host, the feature is guarded against server-side request forgery (SSRF): allow-listed or not, a URL that resolves to a loopback, link-local, private or cloud-metadata address is rejected, DNS rebinding is guarded against, the scheme is restricted to `http` and `https`, and the response size and the connect and read timeouts are capped. See [Importing from a URL](https://trafficparrot.com/documentation/5.65.x/http.html#import-http-from-url).
- Added the ability to **[export HTTP mappings as an OpenAPI 3.0 specification](https://trafficparrot.com/documentation/5.65.x/http.html#export-http-openapi)** (the inverse of importing an OpenAPI specification). The active scenario's mappings are translated into OpenAPI paths and operations (grouping by path and method, normalising exact, templated and regular-expression URL matchers into OpenAPI paths, lifting query and header matchers into `parameters`, and emitting each response body as a literal `example` together with an inferred JSON `schema` for JSON bodies) and served off the existing export endpoint via a new `?format=openapi` query parameter (`GET /http/management/exportMappings?format=openapi`), returning a YAML document (`Content-Type: application/yaml`) as `openapi-<timestamp>.yaml`; without the parameter the endpoint still returns the native WireMock ZIP unchanged. The same document can also be exported as **JSON** with `?format=openapi-json` (`Content-Type: application/json`, downloaded as `openapi-<timestamp>.json`); only the serialisation differs. The OpenAPI export can be triggered from the GUI with the **Export as OpenAPI (YAML)** button on the HTTP [Export](https://trafficparrot.com/documentation/5.65.x/http.html#export-http-openapi) page (alongside the existing **Download Mappings** button) as well as programmatically through the endpoint. Matchers with no clean OpenAPI representation (regex/JSONPath/XPath body matchers, proxy responses) are **never silently dropped**: every mapping's disposition (`REPRESENTED`, `APPROXIMATED` or `OMITTED`) is recorded in a coverage report surfaced both as a root-level `x-trafficparrot-export-coverage` extension and as a one-line summary in `info.description`. For each JSON response body Traffic Parrot also infers a JSON `schema` and emits it alongside the example, so generated clients, SDK codegen and documentation portals get real models rather than just a sample value; inference is conservative and based on the single example body (structure followed recursively, integral numbers become `integer` and non-integral `number`, JSON `null` becomes `nullable`, observed keys become `properties` but none is marked `required`, and no `enum` is inferred). A non-JSON response body (XML, plain text, empty) gets no schema; the example is still emitted and the mapping is recorded in the coverage report with reason `no-schema-inferred`. This release is single-scenario and OpenAPI 3.0 (not 3.1), with no multi-example merge or security schemes yet.
- Added the ability to **[export recorded HTTP traffic as a HAR 1.2 file](https://trafficparrot.com/documentation/5.65.x/http.html#export-http-har)**, ready to drive a **load or resilience test** through your own engine. Unlike the native ZIP and OpenAPI exports, which export the deduplicated mappings, the HAR export is taken from the live **request journal** (the ordered, timed stream of inbound requests served during the current session), so the request order and per-request timing a load profile needs are preserved. Each request becomes one HAR `log.entries` entry carrying the method, URL, headers, query string and request body, the response status, headers and body, and `startedDateTime` / `time`. Click the new **Download recorded traffic (HAR)** button on the HTTP [Export](https://trafficparrot.com/documentation/5.65.x/http.html#export-http-har) page (alongside **Download Mappings** and **Export as OpenAPI (YAML)**), or trigger it programmatically off the existing export endpoint with the `?format=har` query parameter (`GET /http/management/exportMappings?format=har`), which returns a HAR 1.2 document (`Content-Type: application/json`) downloaded as `recorded-traffic-<timestamp>.har`; without the parameter the endpoint still returns the native WireMock ZIP unchanged. The exported HAR can be fed into the common HAR-to-load-test converters such as the Gatling HAR Converter or Grafana `har-to-k6` (Traffic Parrot does not run the load itself; you supply the engine). The export reads the in-memory request journal, so only the most recent requests retained by [`trafficparrot.virtualservice.maxRequestJournalEntries`](https://trafficparrot.com/documentation/5.65.x/properties.html#virtualservice-properties) (default `1000`) are exported; if the journal is disabled (`=0`) the export is a valid but empty HAR. This first release exports text bodies for HTTP traffic only.
- [HAR import](https://trafficparrot.com/documentation/5.65.x/http.html#import-http-preview) now offers explicit **conflict resolution** for duplicate entries. When a preview entry matches an existing stub with the same HTTP method and exact URL, an **On duplicate** dropdown on that row (and a single **For duplicates:** control that applies to every duplicate at once) lets you **Skip** it (the default, so imports you do not touch are unchanged), **Overwrite** the existing stub (all stubs matching that method and URL are removed before the imported one is added, so no duplicate is left behind), or **Import as new** (the existing stub is kept and the imported one is added under a disambiguated name such as `<name> (copy)`). A per-row choice overrides the bulk default. Re-importing the same file still replaces the mappings it created last time, so those entries show as New; the actions apply to a clash against a stub from a different import or one created by hand. The same choice is available on the REST import endpoint (`POST /http/management/importSelectedEntries`) through an optional `conflict-strategy` parameter (`skip` | `overwrite` | `importAsNew`, default `skip`) with per-entry `conflictStrategies` overrides; omitting the parameter keeps the previous behaviour. Duplicate detection is an exact method-and-URL match, so an existing stub that matches its URL by pattern or regular expression is not detected as a duplicate. See [Preview and filter before importing](https://trafficparrot.com/documentation/5.65.x/http.html#import-http-preview).
- The HTTP and gRPC [mappings list](https://trafficparrot.com/documentation/5.65.x/http.html#add-edit-http-mappings) now shows the `bodyFileName` **path** for a mapping whose response body is served from a **binary** file (an image, PDF or other non-text file), truncated to fit the column with the full path on hover, instead of an unreadable placeholder, so you can tell at a glance which mapping serves which file. When that binary file is an **image** (PNG, JPEG, GIF, WebP, BMP, ICO, APNG or AVIF), hovering the row pops a small **rendered preview** of the image in place of the file-path tooltip, so you can recognise the picture a mapping serves without opening the editor; the cell still shows the truncated `bodyFileName` path, the preview is loaded on first hover and capped to a thumbnail, and it falls back to the plain path tooltip if the image cannot be read. Non-image binary rows keep the full-path tooltip. Inline, recorded, and text file-backed responses show their body content in the *Response body* / *Response message* column as before. See [File-backed responses in the mappings list](https://trafficparrot.com/documentation/5.65.x/http.html#file-backed-responses-in-list).
- The HTTP [mappings list](https://trafficparrot.com/documentation/5.65.x/http.html#add-edit-http-mappings) now shows a **composite request body matcher** (one built from the logical [`and`, `or` or `not`](https://trafficparrot.com/documentation/5.65.x/request_matching.html#json-only-matchers) operators) as a readable one-line summary in the *Request body* column, for example `and (contains 'A', contains 'B')` or `not (equalTo 'X')`, instead of the raw matcher JSON. The row's request-match hover tooltip (which already summarised the method, URL matcher, URL and query parameters) now also lists each request body matcher on its own `Body:` line. Simple (leaf) matchers such as `equalTo` and `contains` are shown exactly as before; this changes only how existing matchers are displayed: nothing about how requests are matched or how mappings are saved changes.
- The HTTP Add/Edit mapping panel now shows a live, non-blocking **warning** beneath the URL match mode when you combine a full-URL match mode (`equal to` or `matches regex`) with one or more [query parameter](https://trafficparrot.com/documentation/5.65.x/http.html#add-edit-query-parameters) matchers, a combination that is almost always wrong, because those modes match the whole URL (including the query string) and conflict with the separate query parameter matchers. The warning explains the problem and recommends switching to a path-only mode (`path equal to` or `path matches regex`), and it appears and disappears as you change the URL mode or add and remove query parameter rows. Saving is not blocked.
- The HTTP and gRPC **[Add/Edit mapping](https://trafficparrot.com/documentation/5.65.x/http.html#file-backed-responses-gui)** forms gained three improvements for working with a file-backed response. A **Manage files** link in the response body area opens the [Static Files](https://trafficparrot.com/documentation/5.65.x/http.html#static-files-browser) browser in a **new browser tab**, so you can manage the files a response is served from without leaving, or losing, the mapping you are editing; the link is always shown, whether the response is inline or already file-backed (previously the Static Files browser was reachable only from the HTTP menu). When the response is an **image** file (PNG, JPEG, GIF, SVG, WebP, BMP, ICO, APNG or AVIF) the form shows an **inline preview** of it above the *Response from file* note, so you can see at a glance which image a mapping serves without opening the file; the body field stays read-only for binary files as before, non-image binary files keep the read-only field with no preview, and this mirrors the inline image rendering already used in the [Static Files browser](https://trafficparrot.com/documentation/5.65.x/http.html#static-files-browser-preview) preview pane. Clicking **Switch to file** now shows a **Choose an existing file...** dropdown beside the response body file name field, listing the files already in the scenario's `__files` directory (including nested `responses/` files); selecting one fills the file name so you can point a response at an existing body file without typing the path, and typing the name by hand still works as before. See [Editing a file-backed response in the UI](https://trafficparrot.com/documentation/5.65.x/http.html#file-backed-responses-gui).
- The HTTP [Mapping cleanup](https://trafficparrot.com/documentation/5.65.x/http.html#http-cleanup) results now include a collapsible **Per-endpoint detail** view showing, per recorded endpoint, exactly what cleanup did to it (kept, consolidated, headers stripped, body match removed, URL pattern applied, response template added, or removed), plus a consolidation-groups breakdown of which recorded URLs collapsed into each surviving pattern. The [`/api/http/cleanup/execute`](https://trafficparrot.com/documentation/5.65.x/http.html#cleanup-api) response gains matching `endpointDispositions` and `consolidationGroups` fields.
- The HTTP Add/Edit mapping editor's **request body matcher** dropdown now offers **[matches JSON schema](https://trafficparrot.com/documentation/5.65.x/request_matching.html#matchers-reference)**, which was previously only usable by editing the mapping JSON directly; it matches when the request body is JSON that validates against the given JSON Schema. Enter the schema as the matcher value; it round-trips on save. The advanced JSON-only option (the JSON Schema `schemaVersion` dialect selector) remains available by editing the mapping JSON; see the [JSON-only matchers](https://trafficparrot.com/documentation/5.65.x/request_matching.html#json-only-matchers) reference.
- The HTTP Add/Edit mapping editor's ***Request URL* matcher** dropdown now offers **[path template](https://trafficparrot.com/documentation/5.65.x/request_matching.html#matchers-reference)** as a fifth URL match type, alongside `equal to`, `matches regex`, `path equal to` and `path matches regex`. Enter a URL path template with named variables such as `/orders/{orderId}`; a request path matches when it fits the template's shape regardless of the concrete variable values (so `/orders/{orderId}` matches `/orders/123`). It persists as the `urlPathTemplate` request field and round-trips on save. The matcher also appears in the editor's [Available helpers panel](https://trafficparrot.com/documentation/5.65.x/dynamic.html#available-helpers-panel) under **URL match types**.
- The HTTP Add/Edit mapping editor now also lets you edit **request headers** and **response headers** with per-header rows, using the same click-to-add-rows editing already offered for [query parameters](https://trafficparrot.com/documentation/5.65.x/http.html#add-edit-query-parameters). A [request header](https://trafficparrot.com/documentation/5.65.x/http.html#request-headers) row carries a header name, a matcher dropdown (`equal to`, `contains`, `matches regex`, `does not match regex`, `equal to date/time`, `before date/time` and `after date/time`) and a value, because request headers are matched; a response header row has just a **Name** and a **Value** with no matcher dropdown, because response headers are static `Name: value` pairs the mock returns rather than request matchers. In both cases the free-text headers field is kept for bulk, copy-paste-friendly editing, and the rows and text area stay in two-way sync (most recent edit wins); click **Add request header** or **Add response header** to add a row and the trash button to remove one. The saved mapping JSON is unchanged (standard WireMock request and response `headers`), so existing mappings load back into both views and round-trip on save, no header-matching expressiveness is lost, and the gRPC and messaging editors are unchanged.
- A [file-backed request body matcher](https://trafficparrot.com/documentation/5.65.x/http.html#request-body-file) (one whose value is read from a `bodyFileName` file in `__files`) is now **editable** in the HTTP Add/Edit mapping editor, like a [file-backed response](https://trafficparrot.com/documentation/5.65.x/http.html#file-backed-responses-gui): a **Content from file** note names the file, the request body field is pre-filled with its contents, and saving writes your edit back to the file (the matcher keeps its `bodyFileName` reference). A single file-backed text matcher also offers a **Switch to inline** button (mirroring the file-backed response control) that detaches the `bodyFileName` reference and keeps the loaded contents as an inline matcher value; on save the matcher is stored inline, with no `__files` reference and the file on disk left untouched. A `binaryEqualTo` matcher, or a mapping with more than one request body matcher, stays read-only, offers no Switch to inline, and is edited on disk. See [Request body file: In the GUI](https://trafficparrot.com/documentation/5.65.x/http.html#request-body-file-in-gui).
- The [Available helpers panel](https://trafficparrot.com/documentation/5.65.x/dynamic.html#available-helpers-panel) is now also available on the **gRPC mapping editor** (**gRPC » Add/Edit**), as it already is on the HTTP and messaging editors. Expand the collapsible **Available helpers** card to browse, filter and copy the response-templating helpers and the request-body matchers that apply to a gRPC mapping, without leaving the editor.
- [HAR import](https://trafficparrot.com/documentation/5.65.x/http.html#import-http-har) now offers an opt-in **[Preserve full fidelity (all headers)](https://trafficparrot.com/documentation/5.65.x/http.html#import-http-har-full-fidelity)** mode. By default an imported stub stays flexible: it matches on method, URL and the request `Content-Type`, and its response carries only the status, body and `Content-Type`, with all other request and response headers dropped so the stub is not tied to the exact browser, session or environment that produced the recording. Tick the new **Preserve full fidelity (all headers)** checkbox next to **Import Selected** on the HAR import preview (off by default; a whole-import setting, not per-entry) to instead turn every recorded request header, including `Content-Type`, into an exact request matcher and emit every recorded response header (with the exact response `Content-Type` and charset) on the stub response. This produces a faithful reproduction of the recorded exchange but makes stubs strict and often single-use: headers such as `Host`, `Cookie`, `Authorization` and `Content-Length` tie the stub to a specific host, session, token or body, so leave it off for reusable stubs. HTTP/2 pseudo-headers (`:method`, `:authority`, `:scheme`, `:path`, `:status`) are automatically excluded. The same behaviour is available programmatically through an optional `preserveAllHeaders` parameter on the `/http/management/importMappings` and `/http/management/importSelectedEntries` REST endpoints. Request and response bodies import unchanged (base64-encoded bodies are decoded automatically), and the option affects HAR import only; OpenAPI, Swagger, RAML, Pact and WireMock ZIP imports are unaffected. See [Preserve full fidelity (all headers)](https://trafficparrot.com/documentation/5.65.x/http.html#import-http-har-full-fidelity).
- HTTP recording gained two **Advanced parameters** options on the HTTP Record page for how bodies are stored, both off by default so existing recording workflows are unchanged. **[Keep valid-JSON response body inline](https://trafficparrot.com/documentation/5.65.x/http.html#recording-inline-json)** keeps a recorded response body inline in the mapping (as a structured `jsonBody`) when it is valid JSON served with a text content type, instead of writing it to a separate `__files/` body file, so a recorded JSON API produces self-contained mappings with no companion body files; non-JSON text bodies and binary bodies (including a binary content type whose bytes happen to parse as JSON) are still externalised to `__files/` as before, and there is no size limit on inlining, so a very large JSON response is embedded directly in the mapping file. **[Externalise request body to file](https://trafficparrot.com/documentation/5.65.x/http.html#recording-externalise-request)** is the request-side counterpart of the response-side inline option, and the write-time counterpart of a [file-backed request body matcher](https://trafficparrot.com/documentation/5.65.x/http.html#request-body-file): it writes a recorded request body to a separate `__files/` file, with the recorded mapping's request matcher carrying a `bodyFileName` reference (`equalToJson`, `equalToXml`, `binaryEqualTo` or `equalTo` according to the request's content type, a binary body written byte-for-byte) instead of an inline `bodyPatterns` value; empty and multipart request bodies are always kept inline, and an externalised request body loads, matches on replay, and is editable in the Add/Edit mapping editor exactly like a manually file-backed one. With **Externalise request body to file** off, recording produces byte-identical mappings. Set [`trafficparrot.http.recording.response.inlineJson`](https://trafficparrot.com/documentation/5.65.x/properties.html#recording-properties) or [`trafficparrot.http.recording.request.externaliseToFile`](https://trafficparrot.com/documentation/5.65.x/properties.html#recording-properties) in [`trafficparrot.properties`](https://trafficparrot.com/documentation/5.65.x/properties.html) to change the checkboxes' default states. See [Keeping JSON response bodies inline](https://trafficparrot.com/documentation/5.65.x/http.html#recording-inline-json) and [Externalising request bodies to files](https://trafficparrot.com/documentation/5.65.x/http.html#recording-externalise-request).
- The **URL contains** filter on the HTTP [import preview](https://trafficparrot.com/documentation/5.65.x/http.html#import-http-preview) now supports **glob** wildcards (`*` for any sequence of characters and `?` for any single character) in addition to plain substring matching. Plain text still matches any path that contains it; a pattern with a wildcard switches to an anchored, case-insensitive match against the request path (for example `/api/*`, `*.json` or `/users/?`). This filters which entries are shown for selection only and does not change how the imported stubs match at runtime (GitHub issue #68).
- The [admin request-journal endpoint](https://trafficparrot.com/documentation/5.65.x/http.html#verifying-requests-paging) (`GET /api/http/requests`) now accepts two optional query parameters for paging and filtering a large journal: `limit` bounds the response to the first *N* entries in journal order, and `since` returns only the requests recorded **strictly after** a given ISO-8601 timestamp (for example `2026-07-16T10:00:00Z`); a negative `limit` or a malformed `since` is rejected with `HTTP 400`. Both are off by default, so a request with neither parameter still returns the whole journal unchanged, and the `meta.total` field continues to report the full count of everything recorded, independent of either parameter. See [Page or filter the journal](https://trafficparrot.com/documentation/5.65.x/http.html#verifying-requests-paging).

### Documentation

- Added a **[Recording HTTPS via the browser proxy](https://trafficparrot.com/documentation/5.65.x/user_guide.html#recording-https-proxy)** section to the User Guide. It explains that Traffic Parrot records HTTPS by acting as a browser (forward) proxy: point your browser or application's proxy setting at Traffic Parrot, import the Traffic Parrot CA certificate (`certificates/virtualservice-CA-keystore.p12`, password `trafficparrot`, PKCS12) into the client's trust store, and Traffic Parrot mints a per-host certificate on the fly from the TLS SNI so it can decrypt and record traffic to **any** host. The [Recording HTTP](https://trafficparrot.com/documentation/5.65.x/http.html#recording-configuration) section links across to it.

### Changes

- The default in-memory request-journal retention has been lowered from `10000` to `1000` entries. The [`trafficparrot.virtualservice.maxRequestJournalEntries`](https://trafficparrot.com/documentation/5.65.x/properties.html#virtualservice-properties) property bounds **all** request journals (HTTP, gRPC and JMS/IBM® MQ), so by default each now keeps the last 1000 requests (older entries age out as new requests arrive) instead of 10000. This keeps the default `-Xmx128m` install memory-safe under a sustained first-run/evaluation workload, where the oversized journal could otherwise exhaust the heap. If you need a longer request-log history, raise [`maxRequestJournalEntries`](https://trafficparrot.com/documentation/5.65.x/properties.html#virtualservice-properties) in your [`trafficparrot.properties`](https://trafficparrot.com/documentation/5.65.x/properties.html); the JVM heap setting (`-Xmx128m`) is unchanged.
- The HTTP [Mapping cleanup](https://trafficparrot.com/documentation/5.65.x/http.html#http-cleanup) feature is now discoverable from the HTTP navigation menu by default. The [`trafficparrot.http.cleanup.enabled`](https://trafficparrot.com/documentation/5.65.x/properties.html#extension-system-properties) property, which controls whether the **Cleanup** entry appears in the HTTP menu dropdown, now defaults to `true`, so the Cleanup link is shown without any extra configuration. Previously the link was hidden unless you set `-Dtrafficparrot.http.cleanup.enabled=true` as a JVM system property. To hide the Cleanup link, set [`trafficparrot.http.cleanup.enabled`](https://trafficparrot.com/documentation/5.65.x/properties.html#extension-system-properties) to `false` in your [`trafficparrot.properties`](https://trafficparrot.com/documentation/5.65.x/properties.html) or pass `-Dtrafficparrot.http.cleanup.enabled=false`. The cleanup page and its [REST API](https://trafficparrot.com/documentation/5.65.x/http.html#cleanup-api) remain reachable by direct URL regardless of this setting.

<a id="version-5-60-4"></a>
## 5.60.4 – 16 June 2026

### Features

- The HTTP Add/Edit mapping form now lets you **[edit a file-backed response](https://trafficparrot.com/documentation/5.65.x/http.html#file-backed-responses-gui)** (one served from a `bodyFileName` file) directly in the editor: a *Response from file* note above the response body field shows the file name, the body field is **editable in place**, and saving writes the edited content back to the body file in the `__files` directory through the mapping repository (so the in-memory cache stays in sync). When the same body file is shared by other mappings a warning is shown, because saving changes the response for all of them. You can flip a response between inline and file-backed in both directions: *Switch to inline* detaches the file and stores the body on the mapping, and *Switch to file* externalises an inline body to a new file under `responses/` on save. Binary body files stay read-only and are edited on disk. Previously a file-backed response appeared as an empty body field with no indication it was served from a file.
- The same **[file-backed response](https://trafficparrot.com/documentation/5.65.x/grpc.html#edit-grpc-file-backed-response)** handling is now available on the gRPC Add/Edit mapping form: when a gRPC mapping's response is served from a `response.bodyFileName` file, a *Response from file* note shows the file name, the body field is **editable in place** and pre-filled from the `__files` directory, and saving writes the edited content back to the body file through the mapping repository. A warning is shown when the file is shared by other mappings, and you can flip a response between inline and file-backed in both directions (*Switch to inline* / *Switch to file*). Binary body files stay read-only.
- Added support for externalising a [request body matcher](https://trafficparrot.com/documentation/5.65.x/http.html#request-body-file) into a file in the `__files` directory via `bodyFileName`, mirroring the response-side `bodyFileName` convention. Any of the request body matchers (`equalTo`, `equalToJson`, `equalToXml`, `binaryEqualTo`, `contains`, `doesNotContain`, `matches`, `doesNotMatch`, `matchesJsonPath`, `matchesXPath`, `matchesXml`) can load the value it compares against from a file instead of inlining it in the mapping, resolved relative to the mapping's sibling `__files` directory and loaded once at mapping-load time. A file-backed matcher is shown in the HTTP [Add/Edit mappings](https://trafficparrot.com/documentation/5.65.x/http.html#request-body-file-in-gui) GUI with a **Content from file** note, and the mappings-list Request body column renders the matcher content inlined from the file. The externalised form is also accepted through the WireMock admin API (`POST /__admin/mappings`, `PUT /__admin/mappings/{id}` and `POST /__admin/mappings/import`): the file is resolved when the mapping is registered, a reference to a missing file is rejected at registration with `HTTP 422` naming the file, combining `bodyFileName` with any other key in the same matcher entry is rejected, and mappings saved to disk keep the `bodyFileName` reference instead of the file's contents.
- Added a **[Static Files](https://trafficparrot.com/documentation/5.65.x/http.html#static-files-browser)** browser under the HTTP menu that lists the active scenario's `__files` directory, marks each file as *referenced* or *orphaned* by cross-referencing the HTTP mappings, and previews a selected file's content (JSON and XML are pretty-printed; image files are rendered inline and other binary files show their content type and size). The browser also lets you:
  - **Create a new text file** under the `__files` directory directly from the admin UI: a *New file* affordance prompts for a relative file name and content and adds the file to the browser, where it appears with an *orphaned* badge until a mapping references it.
  - **Edit a text file in place**: selecting a non-binary file and clicking *Edit* replaces the preview with an editable text area and *Save*/*Cancel* buttons, and saving overwrites the file's content in the `__files` directory. When the file is referenced by one or more mappings (through `response.bodyFileName`) a warning is shown, because saving changes the response for all of them. Binary files remain read-only and are edited on disk.
  - **Delete a file**: each row has a *Delete* button that reveals an inline *Confirm*/*Cancel* step (no browser pop-up), and confirming the deletion of an unreferenced file removes it from disk and the row disappears. The delete is **reference-safe**: if the file still backs a mapping the deletion is refused, a banner lists the referencing mapping(s) and the file stays listed. The reference check is complete: it covers both a file used as an HTTP response body (`response.bodyFileName`) and a file used as a request body matcher, so a file that the browser's *orphaned* badge reports as unreferenced (the badge inspects only response references) can still be blocked from deletion when it is genuinely in use, protecting you from silently breaking a request matcher. Overriding the refusal is not currently supported; to delete a referenced file, first remove or repoint the mapping(s) that use it.
  - **Rename a file** within the `__files` directory: each row has a *Rename* button that reveals an inline editable target-name field with *Confirm*/*Cancel* (no browser pop-up). Renaming an unreferenced file moves it to the new name, creating any intermediate sub-directories the new name implies. Like delete, the rename is **reference-safe**: if the file still backs a mapping the rename is refused, a banner lists the referencing mapping(s) and the file keeps its old name, because renaming would leave the mapping pointing at a name that no longer exists. The reference check is complete in the same way: it covers both a file used as an HTTP response body (`response.bodyFileName`) and a file used as a request body matcher, so a file that the *orphaned* badge reports as unreferenced (the badge inspects only response references) can still be blocked from renaming when it is genuinely in use. Renaming onto a name that already exists is refused as well, so you never silently overwrite another file. To rename a referenced file, first remove or repoint the mapping(s) that use it; automatically updating the referencing mappings to the new name is not currently supported.
  - **Upload an existing file** into the `__files` directory straight from your browser: an *Upload* button next to *New file* opens a file picker, and the chosen file is uploaded and added to the browser. Both **text and binary** files are accepted: the bytes are stored verbatim, so an uploaded image is listed and rendered inline in the preview pane, and any other uploaded binary file is listed and shown with its content type and size. Uploading a file whose name already exists is refused so you never silently overwrite another file, and unsafe file names (for example an absolute path or one containing `..` that would escape the scenario's `__files` directory) are rejected. The upload has a configurable size limit, set by the new [`trafficparrot.multipart.upload.max.size.mb`](https://trafficparrot.com/documentation/5.65.x/properties.html#virtualservice-properties) property (default `10` MB, shared by all admin-UI file uploads); a file larger than the limit is rejected with HTTP 413 and the message `File exceeds the maximum upload size of N MB` shown in the upload form. The limit applies only to file uploads through the admin UI and does not affect recorded traffic or mapping sizes.
  - **Resize the panes** with a **draggable divider** between the file list and the preview, so you can widen either side to suit the file you are reading. Drag the divider to set the split (it stays between 20% and 80% so neither pane collapses), and double-click it to snap back to the default split. The split you choose is remembered in your browser across page reloads. On narrow screens the panes stack vertically as before.
  - **Browse files as a directory tree**: files in sub-directories of `__files` are now grouped under expandable folder rows instead of being listed by full relative path. Each folder shows a caret you can click to collapse or expand its contents (all folders are expanded by default), and each file is labelled by its own name and indented under its folder. Selecting a file previews it, and the *referenced*/*orphaned* badges and rename, delete, edit and upload actions all work exactly as before.
  - **Preview images and other binary files**: selecting an **image** file (PNG, JPEG, GIF, SVG, WebP, BMP, ICO, APNG or AVIF) now **renders the image inline** in the preview pane instead of the bare *not previewable* note, so you can see at a glance which image a mapping serves. Selecting any other **binary** file shows a `Binary file - <content type>, <size>` note (for example `Binary file - application/octet-stream, 2.3 KB`) instead, so you can tell its type and size without downloading it. Text, JSON and XML files are still pretty-printed and editable in place as before; images and other binary files remain read-only and are edited on disk. Image and binary files are served back for the preview with a `nosniff` content-type guard and as an attachment, so a file whose bytes happen to contain active content (such as a script-bearing SVG) can never run in your browser from the preview.
- Added a [Logging](https://trafficparrot.com/documentation/5.65.x/logging.html) documentation page covering how to enable verbose logging, change the log level, find the log files (`logs/trafficparrot.log`), turn logging down or off, and use the [Request Log near-miss view](https://trafficparrot.com/documentation/5.65.x/http.html#request-log-near-misses) to see why an HTTP request did not match.
- The HTTP mappings list now shows a **Recording active** banner above the table while a recording session is running, as a reminder that [deleting a mapping while recording](https://trafficparrot.com/documentation/5.65.x/http.html#recording-delete-mapping) also stops that endpoint being re-recorded for the rest of the session.
- The HTTP Record page now shows a **[Live coverage](https://trafficparrot.com/documentation/5.65.x/http.html#recording-live-coverage)** panel while a recording session is active, refreshing about once a second. It gives a running tally of the distinct endpoints seen so far (how many now have a mapping, how many were observed but are still unmapped, and how many mappings have not been observed) plus the per-endpoint observed and unmatched request counts, so you can tell during the session whether a recording has captured everything you expected. Endpoints are grouped by HTTP method and normalised path using the same convention as [Mapping cleanup](https://trafficparrot.com/documentation/5.65.x/http.html#http-cleanup), and the panel notes how many requests in the request journal the tally is based on.
- Added a **[Verifying requests](https://trafficparrot.com/documentation/5.65.x/http.html#verifying-requests)** guide for WireMock users, mapping the `verify()` DSL onto Traffic Parrot's request journal: assert a request was made, was made exactly N times, or was **NOT** made via `POST /api/http/requests/count`, inspect captured bodies via `POST /api/http/requests/find`, list unmatched requests and near misses, and reset the journal, with a WireMock-to-Traffic-Parrot translation table and copy-paste `curl` recipes.
- The **[Application logs](https://trafficparrot.com/documentation/5.65.x/user_guide.html#application-log-viewer)** view (HTTP menu → Logs → Application logs) now offers a **structured view** of the server log in addition to the existing raw text view. The raw view remains the default; clicking *Structured view* parses each entry into its timestamp, level, thread and message, with a coloured band and a level badge (the level text is always shown, not signalled by colour alone, so the view stays readable in greyscale and for colour-blind users). Multi-line stack traces fold into a single collapsible entry (with *Expand all* / *Collapse all*), you can filter entries by level and by free text, and any line that does not match the log pattern is shown in full rather than hidden. The existing search, last-10,000-lines truncation and *Download raw* affordances are unchanged.
- Added an **[Available helpers](https://trafficparrot.com/documentation/5.65.x/dynamic.html#available-helpers-panel)** panel at form level (below both the request and response cards) on the HTTP and messaging (JMS, IBM MQ and file-message) Add/Edit mapping forms, so you can discover what Traffic Parrot offers without leaving the product. The collapsible, read-only panel is a sectioned shell with three catalogues: a *Response templating helpers* section listing the helpers grouped by category; a *Request matchers* section listing the available request matchers; and an *Other functionality* section covering Scenarios & state, Response delays, Fault simulation, response proxying, serving a response from a file, webhook callbacks and request-matching scripts. Each entry has a one-line description, a copy-ready snippet (already scaffolded with example parameters) and a docs link, with a filter box that narrows every section as you type (matching name and description) and a per-entry Copy button. It is discovery-only and does not change how mappings are saved or how responses are rendered.
- The HTTP [Add/Edit mapping](https://trafficparrot.com/documentation/5.65.x/http.html#add-edit-http-mappings) form now lets you author the advanced response delay and fault shapes that were previously only configurable in mapping JSON: a **log-normal random delay** (median, sigma and an optional maximum, to model realistic response-time spread), a **chunked dribble delay** (split the response body into a number of chunks sent over a total duration, to simulate a slow trickle), and the **CONNECTION_RESET_BY_PEER** response fault. Because the editor now understands these shapes, opening and saving a WireMock-format JSON mapping in the GUI no longer silently strips them; previously a form open-save dropped a log-normal `delayDistribution`, a `chunkedDribbleDelay` or a `CONNECTION_RESET_BY_PEER` fault, so this also fixes that data loss.
- Added a **[matches GraphQL](https://trafficparrot.com/documentation/5.65.x/http.html#request-graphql-matcher)** request body matcher for stubbing a `POST /graphql` endpoint, where many operations share one URL. Its full-query form matches the request's `query` **semantically**: tolerant of insignificant whitespace, selection-set field order, and argument order, so differently formatted but equivalent queries select the same response (aliases and directives stay significant). Its object form matches on `operationName` alone to disambiguate operations on one URL, with an optional `variables` object to also assert on the request's variables. Select **matches GraphQL** in the *Request body* matcher dropdown on the HTTP [Add/Edit mapping](https://trafficparrot.com/documentation/5.65.x/http.html#add-edit-http-mappings) form to author the full-query form; the operation-name form is authored by importing mapping JSON. A request that is not valid GraphQL simply does not match (it is never an error), and a mapping whose own GraphQL query is invalid is rejected at save/import time.
- Added a **[trafficparrot validate](https://trafficparrot.com/documentation/5.65.x/http.html#validate-cli)** command that checks your mappings against their bound schemas without starting the server, for use as a continuous integration step. For HTTP it reports both *schema drift* (a mapping whose URL path and method are not declared in any OpenAPI specification in `openapi/`) and *under-coverage* (an operation declared in a specification that no mapping covers), so a partially-mocked API cannot silently drift from its contract; gRPC mappings are validated against their proto schema. It prints a labelled report and exits `0` (no drift), `1` (drift detected) or `2` (usage or configuration error, including a files-root with no mappings). Operations you deliberately do not mock can be excluded with an `exclude.operations` list in an `openapi-coverage.properties` file in the files-root; an allowlist entry that matches no operation in the specification is itself reported as drift so the list cannot quietly go stale.
- Added an **[external-process](https://trafficparrot.com/documentation/5.65.x/dynamic.html#external-process-transformer)** HTTP response transformer that passes the response through a user-supplied executable (the "middleware") written in any language, familiar to Hoverfly users. For each matched request on an opted-in mapping, Traffic Parrot serialises a versioned JSON envelope (the matched request plus the response about to be sent) to the executable's stdin and applies the mutated `response` read back from stdout (status, headers, body); request mutation is not supported in this release. The feature is **off by default** ([`trafficparrot.http.externalprocess.enabled`](https://trafficparrot.com/documentation/5.65.x/properties.html#extension-system-properties)) and confined to a single operator-vetted directory (`trafficparrot.http.externalprocess.allowedDir`); the executable runs as the Traffic Parrot OS user with no sandbox, so enable it only on trusted hosts. Each mapping configures the `executable`, optional `args`, a per-invocation `timeoutMs` (default 5000, the process is killed on expiry), and an `onError` fallback (`fail-open` returns the original response, `fail-closed` returns HTTP 500) applied on non-zero exit, timeout, malformed output, or a missing/disallowed executable.
- The **[external-process](https://trafficparrot.com/documentation/5.65.x/dynamic.html#external-process-gui)** transformer can now be enabled and configured directly in the HTTP mapping editor, instead of only by hand-editing the mapping JSON. When an operator has set `trafficparrot.http.externalprocess.enabled=true`, an **ExternalProcessTransformer** toggle appears in the *Response transformers* list under *Advanced parameters*; turning it on reveals an **External Process** tab in the *Transformer parameters* panel with structured fields for the `executable`, `args` (space or newline separated), `timeoutMs`, and `onError` (`fail-open`/`fail-closed`). The option is offered **only** when the feature is enabled, and selecting it does not bypass the `trafficparrot.http.externalprocess.allowedDir` allow-list that still gates which executables may run. Saving writes the same `transformerParameters.external-process` JSON the editor, the mapping file on disk, and the WireMock Admin API all share. See [Configuring it in the editor GUI](https://trafficparrot.com/documentation/5.65.x/dynamic.html#external-process-gui).

### Documentation

- Added an [Environment variables in responses](https://trafficparrot.com/documentation/5.65.x/environment-variables.html) how-to page covering the [`{{systemValue}}`](https://trafficparrot.com/documentation/5.65.x/dynamic.html#extension-functions) Handlebars helper: reading an environment variable (`type='ENVIRONMENT'`) or a JVM system property (`type='PROPERTY'`) into a response body or header, the `default=` fallback, the `wiremock*` allow-list and the `[ERROR: Access to … is denied]` failure mode, and the underscore-vs-dot naming rule for environment variables.
- Added a **[CORS for stub responses](https://trafficparrot.com/documentation/5.65.x/http.html#cors-friendly-stub-responses)** how-to answering the common WireMock “CORS not working” question. It documents that the Traffic Parrot virtual service is CORS-friendly out of the box for every path (the browser CORS preflight (`OPTIONS`) is auto-answered `HTTP 200` with `Access-Control-Allow-Methods`, `Access-Control-Allow-Headers` and `Access-Control-Max-Age`, and the request `Origin` is reflected into `Access-Control-Allow-Origin` on the actual response) with no flag and no per-stub configuration (unlike WireMock's off-by-default `--enable-stub-cors`). It also shows how to pin a specific origin by setting `Access-Control-Allow-Origin` in a stub's `response.headers`, and clarifies that this CORS behaviour is independent of the [`trafficparrot.http.optionsResponse.enabled`](https://trafficparrot.com/documentation/5.65.x/properties.html#extension-system-properties) property (which emits only an `Allow` header).
- Expanded the [JVM arguments](https://trafficparrot.com/documentation/5.65.x/user_guide.html#jvm-arguments) section of the User Guide with a full reference for the `jvm.args` file: where it lives in the install directory, how each non-empty line is passed to the server JVM at startup, a table describing every shipped default (including `-Xmx128m`, the line to raise for large recordings or datasets), and typical adjustments.

### Fixes

- Binary `bodyFileName` responses (images, PDFs, etc.) are now served byte-for-byte unchanged when [HTTP Handlebars](https://trafficparrot.com/documentation/5.65.x/properties.html#extension-system-properties) is enabled (the default, `trafficparrot.http.handlebars.enabled=true`); no per-mapping configuration required (fixes a corruption where binary files served via `bodyFileName` were re-encoded as text). See [Response body files: templating vs byte-for-byte](https://trafficparrot.com/documentation/5.65.x/http.html#response-body-file-templating).
- Whether a `bodyFileName` response is [templated or served byte-for-byte](https://trafficparrot.com/documentation/5.65.x/http.html#response-body-file-templating) is now decided by positive binary evidence (the response `Content-Type` or the file extension): recognised binary types are served byte-for-byte; everything else is run through Handlebars. This also ensures text/template body files with no `Content-Type` are still rendered.
- The **Duplicate** and **Delete** buttons in the gRPC mappings list work again; a regression had stopped them working, so a gRPC mapping could not be duplicated or deleted from the admin UI. Both actions now behave as they do for HTTP mappings.
- A stub configured with the `INCORRECT_SMALL_CONTENT_LENGTH` response fault now injects the fault correctly (it serves the stubbed status with a too-small `Content-Length` header and a body truncated to that length) instead of returning an HTTP 500 error.
- File-message mappings now honour the `priority` field when resolving match precedence. Previously, when two file-message mappings both matched an inbound message, `priority` was ignored and the mapping loaded first always won; HTTP, JMS and IBM MQ mappings already honoured `priority` correctly.
- Library upgrades to fix OWASP issues.

### Changes

- When the [external-process](https://trafficparrot.com/documentation/5.65.x/dynamic.html#external-process-transformer) transformer is enabled, Traffic Parrot now validates the `trafficparrot.http.externalprocess.allowedDir` directory once at startup and logs a warning if it is empty, does not exist, is not a directory, or is non-canonical, so a misconfigured allow-list is surfaced at startup rather than at the first matched request. The check is warn-only: the server still starts.
- The *Import skeleton…* upload on the HTTP and gRPC **Add/Edit mapping** pages (importing an OpenAPI/Swagger [HTTP skeleton](https://trafficparrot.com/documentation/5.65.x/http.html#http-skeletons) or a proto/descriptor-set [gRPC message skeleton](https://trafficparrot.com/documentation/5.65.x/grpc.html#edit-grpc-skeletons)) now has a configurable size limit, set by the [`trafficparrot.multipart.upload.max.size.mb`](https://trafficparrot.com/documentation/5.65.x/properties.html#virtualservice-properties) property (default `10` MB), the same property that caps the **Static Files** browser upload. A file larger than the limit is rejected with HTTP 413 and the message `The uploaded file exceeds the maximum upload size of N MB` shown in the import error area, instead of being buffered unbounded. Previously these imports had no size limit.
- The HTTP [Import mappings](https://trafficparrot.com/documentation/5.65.x/http.html#import-http-rest-api) REST endpoint (`/http/management/importMappings`) now enforces the same [`trafficparrot.multipart.upload.max.size.mb`](https://trafficparrot.com/documentation/5.65.x/properties.html#virtualservice-properties) cap (HTTP 413 on an oversize upload) as the skeleton-import and Static Files uploads. Previously this endpoint had no size limit.
- Externalising an inline response body to a file with **[Switch to file](https://trafficparrot.com/documentation/5.65.x/http.html#file-backed-responses-gui)** on the HTTP and gRPC **Add/Edit mapping** forms now takes a **single click**. The one click makes the response body file-backed straight away (it reveals the (editable) file name field pre-filled with a suggested name, shows the *Response from file* note, and offers *Switch to inline* to revert), and clicking **Save** then writes the body to that file under `__files`. Previously a second click was needed to confirm the file name before saving would externalise. Clearing the file name field keeps the body inline.
- Upgraded bundled JRE from 21.0.7 to 21.0.11

<a id="version-5-59-2"></a>
## 5.59.2 – 31 May 2026

### Features

- Added [matches FIX field](https://trafficparrot.com/documentation/5.65.x/ibmmq.html#request-body-matchers) body matcher for [IBM MQ](https://trafficparrot.com/documentation/5.65.x/ibmmq.html#request-body-matchers), [JMS](https://trafficparrot.com/documentation/5.65.x/jms.html#request-body-matchers), and [File](https://trafficparrot.com/documentation/5.65.x/filemessage.html#request-body-matchers) messaging mappings, enabling tag-level matching on FIX protocol messages by tag number and regex (version-agnostic across FIX 4.2, 4.4, 5.0, and FIXT)
- Added [`{{fixField}}`](https://trafficparrot.com/documentation/5.65.x/dynamic.html#extract-fixfield) Handlebars helper for extracting FIX protocol message field values in dynamic response templates by tag number
- Added [`{{#fixWithChecksum}}` block helper](https://trafficparrot.com/documentation/5.65.x/dynamic.html#fix-with-checksum) with inline `{{fixBodyLength}}` and `{{fixCheckSum}}` placeholders that auto-compute FIX 4.x tag `9` (BodyLength) and tag `10` (CheckSum) for FIX response templates, removing the need to hand-calculate these values
- Added [`{{image}}` Handlebars helper](https://trafficparrot.com/documentation/5.65.x/dynamic.html#image-helper) for generating placeholder PNG images (grey rectangle with dimensions overlay) directly from a mapping body, with configurable `width`, `height`, and overlay `text` arguments; JDK-only, no external dependencies, deterministic within a single JVM
- Added [`base64-decode-body`](https://trafficparrot.com/documentation/5.65.x/dynamic.html#base64-decode-body-transformer) built-in response transformer that Base64-decodes the rendered response body and serves it as raw bytes, enabling binary responses (PNG, PDF, ZIP, etc.) from JSON mappings when paired with helpers such as [`{{image}}`](https://trafficparrot.com/documentation/5.65.x/dynamic.html#image-helper)
- Added a **Transformer parameters** editor under *Advanced parameters* on the HTTP Add/Edit mapping form, so the `response.transformerParameters` JSON block (used by [HmacSigningTransformer](https://trafficparrot.com/documentation/5.65.x/dynamic.html#hmac-signing) and other parameter-driven response transformers) can be authored and edited in the GUI instead of only in the mapping JSON file. The editor auto-formats the JSON on blur (2-space indent) and validates on save (invalid JSON prevents submit with an inline error). Existing mappings round-trip semantically through the form (whitespace is normalised; field order is preserved). See [Editing transformer parameters in the GUI](https://trafficparrot.com/documentation/5.65.x/dynamic.html#transformer-parameters-editor) for details.
- Added a **[Query parameters](https://trafficparrot.com/documentation/5.65.x/http.html#add-edit-query-parameters)** section to the HTTP Add/Edit mapping panel, with per-parameter rows that support `equal to`, `contains`, `matches regex`, and `absent` matchers (see [Request query parameter matchers](https://trafficparrot.com/documentation/5.65.x/http.html#request-query-parameter-matchers)). Saving produces standard WireMock `queryParameters` JSON; loading an existing mapping with a `queryParameters` block populates the rows on the form. This replaces the previous workarounds of putting the full query string in `urlEqualTo` or hand-writing a lookahead regex in `urlMatching`, both of which continue to work for existing mappings.
- Added a **[Convert query string to rows](https://trafficparrot.com/documentation/5.65.x/http.html#add-edit-convert-query-string)** link under the Request URL field on the HTTP Add/Edit mapping panel. Clicking it parses `name=value` pairs out of a pasted URL's query string, appends one `equal to` row per pair to the Query parameters section, and strips the query string from the URL field. URL-encoded values (e.g. `%20`) are decoded automatically. The conversion is staged client-side; you still need to click **Save** to commit the changes.
- JSON and XML request and response bodies are now **[pretty-printed](https://trafficparrot.com/documentation/5.65.x/http.html#request-log-body-formatting)** in the expanded detail of the Request Log. Each body block is collapsible and has a **Copy** button that copies the original, unformatted body. Bodies that are truncated (over 10 KB), malformed, or not JSON/XML continue to be shown raw. The same formatting applies to the gRPC requests page and the JMS, IBM MQ, and file messaging requests pages.
- Added support for [supplying the license](https://trafficparrot.com/documentation/5.65.x/user_guide.html#supplying-the-license) through the `TRAFFICPARROT_LICENSE` environment variable (base64-encoded), so it can be injected at runtime from a Kubernetes Secret, Docker secret, or secrets manager instead of being baked into a Docker image. The system property `-Dtrafficparrot.license.content` takes precedence over the environment variable, which takes precedence over the classpath `trafficparrot.license` file; if neither is set, the classpath file is read as before (no change for existing installations). A set-but-invalid value fails fast with a clear error rather than silently falling back to the file.
- The HTTP Add/Edit mapping form now shows a **[Response from file](https://trafficparrot.com/documentation/5.65.x/http.html#file-backed-responses-gui)** note above the response body field when a mapping's response is served from a `bodyFileName` file, making it clear that the body is loaded from the `__files` directory rather than typed inline.

### Changes

- Removed the unused *SOAP message signer* dropdown from the HTTP Add/Edit mapping form's *Advanced parameters* section. SOAP message signing continues to work via the `SoapMessageSigner` entry in the `trafficparrot.http.responsetransformers` startup property (see [Properties](https://trafficparrot.com/documentation/5.65.x/properties.html)) and the per-mapping *Response transformers* multiselect.
- The tooltip shown when hovering over the **URL Matcher** or **URL** cell in the HTTP mappings list now shows the complete request match for that mapping: the HTTP method, the URL matcher type, the full untruncated URL or pattern, and each query parameter matcher (previously not visible anywhere in the list).
- The tooltip shown when hovering over the **gRPC method** cell in the gRPC mappings list now shows the complete request match for that mapping: the gRPC method, the request message matcher, and each [request metadata matcher](https://trafficparrot.com/documentation/5.65.x/grpc.html#request-metadata) (previously not visible anywhere in the list).
- [Deleting an HTTP mapping while recording](https://trafficparrot.com/documentation/5.65.x/http.html#recording-delete-mapping) now suppresses re-recording of that endpoint (matched by method and normalised URL path) for the rest of the current recording session, instead of immediately re-creating it the next time the same request is proxied. The suppression is session-scoped: it is cleared when recording stops and at the start of each new recording session.

<a id="version-5-58-6"></a>
## 5.58.6 – 12 May 2026

### Features

- Added [near-miss diagnosis](https://trafficparrot.com/documentation/5.65.x/http.html#request-log-near-misses) for unmatched HTTP requests with a per-field comparison table showing match/mismatch indicators, stub name headings, a "View Stub" link to edit the stub directly, and a "Show full stub JSON" toggle
- Added [HTTP Request Log](https://trafficparrot.com/documentation/5.65.x/http.html#request-log) page with auto-refresh, expandable request details, and near-miss display for unmatched requests
- Added [HTTP Passthrough Proxy](https://trafficparrot.com/documentation/5.65.x/http.html#passthrough-proxy) mode that forwards unmatched requests to a real backend, with a blue "Proxied" badge in the request log and one-click [stub creation](https://trafficparrot.com/documentation/5.65.x/http.html#passthrough-proxy-create-stub) from proxied requests
- Added [FTP and SFTP drivers](https://trafficparrot.com/documentation/5.65.x/filemessage.html#configuration) for file mocking, enabling record and replay of file-based integrations over remote FTP and SFTP servers alongside the existing local file system driver
- Added [HAR file import](https://trafficparrot.com/documentation/5.65.x/http.html#import-http-har) support on the HTTP Import page, allowing you to import HTTP Archive files exported from browser DevTools to create stubs from captured traffic
- Added [preview and filter](https://trafficparrot.com/documentation/5.65.x/http.html#import-http-preview) for HAR and OpenAPI imports, with host, method, status, and URL filters plus per-entry selection and duplicate detection before importing
- Added [REST API for importing mappings](https://trafficparrot.com/documentation/5.65.x/http.html#import-http-rest-api) via curl or other HTTP clients, supporting all import formats (HAR, OpenAPI/Swagger, RAML, WireMock ZIP) including [filtered import](https://trafficparrot.com/documentation/5.65.x/http.html#import-http-rest-api) with `hostFilter`, `methodFilter`, `statusFilter`, and `urlFilter` parameters
- Added [matches SWIFT field](https://trafficparrot.com/documentation/5.65.x/ibmmq.html#request-body-matchers) body matcher for [IBM MQ](https://trafficparrot.com/documentation/5.65.x/ibmmq.html#request-body-matchers), [JMS](https://trafficparrot.com/documentation/5.65.x/jms.html#request-body-matchers), and [File](https://trafficparrot.com/documentation/5.65.x/filemessage.html#request-body-matchers) messaging mappings, enabling field-level matching on SWIFT MT messages by tag number and regex
- Added `swiftField` [Handlebars helper](https://trafficparrot.com/documentation/5.65.x/dynamic.html#extract-swiftfield) for extracting SWIFT MT message field values in dynamic response templates
- Added [header matcher types](https://trafficparrot.com/documentation/5.65.x/http.html#request-headers) for HTTP stub creation, supporting `contains`, `matches` (regex), and `doesNotMatch` matchers in addition to the default `equalTo`
- Added [HlsStreamTransformer](https://trafficparrot.com/documentation/5.65.x/dynamic.html#built-in-transformers) for simulating HLS video streaming: serves dynamically generated `.m3u8` playlists and `.ts` video segments from a single wildcard mapping, including multi-variant adaptive-bitrate (ABR) playlists with scenario-state-driven variant switching
- Added [enable/disable toggle](https://trafficparrot.com/documentation/5.65.x/http.html#add-edit-enable-disable) for HTTP mappings: temporarily disable a mapping without deleting it using the eye icon in the mapping list
- Added support for uploading precompiled protobuf file descriptor sets (`.desc` and `.protoset` files) via the [gRPC skeleton import](https://trafficparrot.com/documentation/5.65.x/grpc.html#edit-grpc-skeletons) UI, in addition to `.proto` source files
- Messaging export/import ([JMS](https://trafficparrot.com/documentation/5.65.x/jms.html#import-export-jms-mappings), [File](https://trafficparrot.com/documentation/5.65.x/filemessage.html#import-export-file-mappings)) now includes the `data/` directory in the exported ZIP, so dataSource-backed mappings (CSV lookup, Excel lookup, object store) work correctly when imported on another instance
- Added [strict error handling mode](https://trafficparrot.com/documentation/5.65.x/dynamic.html#error-handling) for Handlebars helpers via [`trafficparrot.virtualservice.handlebars.throwErrors`](https://trafficparrot.com/documentation/5.65.x/properties.html#handlebars-properties), which causes helper errors to throw exceptions (HTTP 500 or messaging failures) instead of embedding inline error strings in responses
- Added `scanConsistency` parameter to the [Couchbase N1QL dataSource helper](https://trafficparrot.com/documentation/5.65.x/dynamic.html#data-source-couchbase), allowing you to choose between `REQUEST_PLUS` (consistent, default) and `NOT_BOUNDED` (faster) query scan consistency, plus improved error handling that returns error messages instead of exceptions
- Added [JMS performance monitoring](https://trafficparrot.com/documentation/5.65.x/jms.html#jms-performance-monitoring-configuration) to log total processing time of JMS messages, matching the existing IBM MQ performance monitoring capability
- Added namespace support to the [`manageState`](https://trafficparrot.com/documentation/5.65.x/dynamic.html#manage-state) Handlebars helper using `namespace/variableName` syntax, allowing state isolation between different test scenarios
- Added namespace support to the [State Management REST API](https://trafficparrot.com/documentation/5.65.x/openapi/index.html), enabling isolated state per scenario or test case:
  - Create or update namespaced state using `PUT /api/state/{namespace}/{name}`
  - Get namespaced state using `GET /api/state/{namespace}/{name}`
  - List all state in a namespace using `GET /api/state/{namespace}`
  - Clear all state in a namespace using `DELETE /api/state/{namespace}`
  - Existing `/api/state/global/{name}` routes remain unchanged for backward compatibility
- Added `PUT /api/configuration/files/{file}` endpoint for creating new configuration files programmatically (returns 201 Created, or 409 Conflict if file already exists)
- OpenAPI import now fetches content from `externalValue` URLs in named examples, using the fetched response body as the mock response instead of a placeholder message
- Added [HMAC response signing](https://trafficparrot.com/documentation/5.65.x/dynamic.html#hmac-signing) built-in response transformer: computes an HMAC signature of the response body and adds it as a Base64-encoded header, enabled by listing `hmacSigning` in `response.transformers` and configured via `transformerParameters.hmacSigning` in the mapping JSON, supporting HmacSHA1, HmacSHA256, and HmacSHA512 algorithms for simulating webhook and API gateway authentication
- Added [OpenAPI schema check](https://trafficparrot.com/documentation/5.65.x/http.html#openapi-schema-check) that validates HTTP mappings against OpenAPI specification files at startup, preventing startup if any mapping references a URL path or method not found in the specifications; enable with [`trafficparrot.virtualservice.openapi.check.mapping.schema.on.startup=true`](https://trafficparrot.com/documentation/5.65.x/properties.html#openapi-properties)
- Added configurable IBM MQ [response headers](https://trafficparrot.com/documentation/5.65.x/ibmmq.html#edit-mq-response-headers) (`replyToQueueManagerName`, `replyToQueueName`) in mapping JSON files with Handlebars template support, allowing dynamic control of response message routing headers
- Added [`trafficparrot.ibmmq.connect.options.accessQueue.input`](https://trafficparrot.com/documentation/5.65.x/properties.html#ibmmq-properties) property to configure how IBM® MQ queues are opened for input (consumer) operations, mirroring the existing `accessQueue.output` property for producers

### Fixes

- Broker configuration panels ([JMS](https://trafficparrot.com/documentation/5.65.x/jms.html), [IBM MQ](https://trafficparrot.com/documentation/5.65.x/ibmmq.html), [File messaging](https://trafficparrot.com/documentation/5.65.x/filemessage.html)) now show empty configuration fields as blank rather than rendering the literal text "null" when no value is configured
- Added path traversal prevention to the `objectStore` Handlebars helper to ensure file access stays within the data directory
- Fixed OpenAPI 3.1 import to correctly handle JsonSchema types, generating proper example responses instead of failing with an error
- Fixed binary schema fields in OpenAPI imports to show a `(binary)` placeholder instead of corrupted text
- Improved error messages for unsupported external `$ref` schema references in OpenAPI imports

### Changes

- Upgraded web UI framework from Bootstrap 3 to Bootstrap 5
- Upgraded from WireMock 2 to WireMock 3
- Simplified the [HTTP Record page](https://trafficparrot.com/documentation/5.65.x/http.html#recording-usage) to show a single Recording URL input by default for the common case of recording one backend; click **Record from multiple URLs** to reveal URL pattern fields and record from [multiple backends](https://trafficparrot.com/documentation/5.65.x/http.html#recording-multiple) in one session
- Added [`trafficparrot.virtualservice.grpc.tls.enabled`](https://trafficparrot.com/documentation/5.65.x/properties.html#grpc-properties) and [`trafficparrot.virtualservice.grpc.non.tls.enabled`](https://trafficparrot.com/documentation/5.65.x/properties.html#grpc-properties) properties to allow independently enabling/disabling each gRPC server port
- New code should use the `TransformedRequest.like(Request)` static factory method in place of the deprecated `TransformedRequest` public constructor; the deprecated constructor remains available for backwards compatibility
- IBM MQ client library updated from `com.ibm.mq.allclient` to `com.ibm.mq.jakarta.client`. If upgrading, replace `com.ibm.mq.allclient.jar` with `com.ibm.mq.jakarta.client.jar` in your `lib/external/` folder; see [JMS](https://trafficparrot.com/documentation/5.65.x/jms.html#ibm-mq-libs) and [IBM MQ](https://trafficparrot.com/documentation/5.65.x/ibmmq.html#ibm-mq-libs) documentation for details. Existing javax.jms plugins continue to work without source changes; support for javax-based plugins will be removed in a future major release.

<a id="version-5-57-3"></a>
## 5.57.3 – 16 Feb 2026

### Features

- Added import/export UI for gRPC, Files and JMS protocols
- Added `parseCsv` [Handlebars helper](https://trafficparrot.com/documentation/5.65.x/dynamic.html#parse-csv) for parsing CSV data in dynamic responses
- Improved OpenAPI validation to correctly resolve `$ref` schema references

### Fixes

- Fixed mapping name not being saved when cache is enabled
- Fixed OpenAPI validation issue with double-slash paths
- Fixed configuration files API path handling on Mac/Linux and Windows
- Library upgrades to fix OWASP issues

### Changes

- Renewed sample SSL certificates

<a id="version-5-56-6"></a>
## 5.56.6 – 21 Nov 2025

### Fixes

- Library upgrades to fix OWASP issues

<a id="version-5-56-5"></a>
## 5.56.5 – 29 Sep 2025

### Features

- Added [ResponseToPdf](https://trafficparrot.com/documentation/5.65.x/dynamic.html#built-in-transformers) transformer for converting HTTP responses to PDF documents

### Fixes

- Fixed cache invalidation issue when modifying active composite scenario
- Fixed an issue with `__files` not being read from the current scenario for some file types
- Fixed transformer multi-select UI behavior in mapping editor
- Mapping files are no longer unnecessarily trimmed on startup
- Prevent comment line being written for scenario property files
- Improved SDK workspace configuration to avoid missing dependency errors
- Library upgrades to fix OWASP issues

### Changes

- Updated sample gRPC SSL certificates
- Upgraded gRPC from 1.67.1 to 1.75.0

<a id="version-5-55-2"></a>
## 5.55.2 – 13 Aug 2025

### Features

- Added keyboard shortcut Ctrl/Cmd+F to focus search in mappings list for improved navigation
- Separated URL matcher from URL in mappings list to enable proper sorting by URL
- Improved UI responsiveness when working with large numbers of mappings

### Fixes

- Refresh scenario dropdown when composite scenario first used

### Changes

- Renamed the HTTP recording [URL rewriting](https://trafficparrot.com/documentation/5.65.x/http.html#recording-url-rewriting) property `trafficparrot.http.recording.rewrite.regex` to `trafficparrot.http.recording.response.rewrite.regex` (it rewrites URLs in recorded response bodies) and added a companion `trafficparrot.http.recording.storage.rewrite.regex` that rewrites URLs as recordings are written to disk

<a id="version-5-54-2"></a>
## 5.54.2 – 19 Jul 2025

### Features

- Added [Composite scenario support](https://trafficparrot.com/documentation/5.65.x/virtual_services.html#composite-scenarios) for HTTP virtual services, allowing you to combine mappings from multiple scenarios into a single active scenario
- Added [URL rewriting support](https://trafficparrot.com/documentation/5.65.x/http.html#recording-url-rewriting) during HTTP recording via the `trafficparrot.http.recording.rewrite.regex` property to automatically transform URLs in response bodies
- Added `RequestToPdf` [response transformer](https://trafficparrot.com/documentation/5.65.x/dynamic.html#built-in-transformers) for generating PDF files from request bodies in test environments
- Added support for Brotli compression decoding during HTTP recording

### Fixes

- Fixed a UI mapping list rendering issue seen on some browsers
- Fixed tooltip display issues in the web interface
- Library upgrades to fix OWASP issues

### Changes

- Upgraded bundled JRE from 21.0.6 to 21.0.7
- Upgraded gRPC from 1.63.0 to 1.67.1

<a id="version-5-53-1"></a>
## 5.53.1 – 19 May 2025

### Features

- Added new properties to performance profile settings:

  ```
  trafficparrot.virtualservice.httpRequestLoggingDisabled=true
  trafficparrot.virtualservice.accessLogsEnabled=false
  trafficparrot.virtualservice.handlebars.maxCacheEntries=10000
  ```

<a id="version-5-53-0"></a>
## 5.53.0 – 22 Apr 2025

### Features

- Added searchable dropdown to scenario selection in the UI for better usability

### Fixes

- Library upgrades to fix OWASP issues

### Changes

- Increased the minimum Java runtime requirement from Java 8 to Java 17. We will continue to support Java 8 for all customers that have not yet upgraded.
- Upgraded Jetty server from v9 to v12

<a id="version-5-52-0"></a>
## 5.52.0 – 24 Feb 2025

### Features

- Import OpenAPI files from the `openapi` configuration directory on startup

- Enable in [`trafficparrot.properties`](https://trafficparrot.com/documentation/5.65.x/properties.html) by setting:

  ```
  trafficparrot.openapi.import.on.startup=true
  ```

### Fixes

- Library upgrades to fix OWASP issues

### Changes

- Upgraded bundled JRE from 8u402 to 21.0.6
- OpenAPI imports performed via the UI will override the previous import rather than duplicating mappings
- Downgraded to WireMock 2 [request matchers](https://wiremock.org/2.x/docs/request-matching/) and Handlebars [response templating helpers](https://wiremock.org/2.x/docs/response-templating/) due to performance issues with WireMock 3

<a id="version-5-51-1"></a>
## 5.51.1 – 11 Jan 2025

### Features

- New [JMS request matching script](https://trafficparrot.com/documentation/5.65.x/jms.html#request-matcher-script) can be used to e.g. match a request body based on a CSV file lookup
- New JMS IBM MQ [passthrough mocks demo video](https://youtu.be/F_2stfDon2M) and [passthrough mocks tutorial](https://github.com/trafficparrot/trafficparrot-demo-applications/tree/master/mobile-network-hardware)

### Changes

- Improved logging when using the [HTTP request matching script](https://trafficparrot.com/documentation/5.65.x/http.html#add-edit-request-matcher-script)

<a id="version-5-50-1"></a>
## 5.50.1 – 06 Nov 2024

### Features

- Added support for WireMock 3 [request matchers](https://wiremock.org/docs/request-matching/) and Handlebars [response templating helpers](https://wiremock.org/docs/response-templating/)

### Fixes

- Library upgrades to fix OWASP issues

<a id="version-5-49-0"></a>
## 5.49.0 – 12 Oct 2024

### Features

- Added support for the [JWT Extension for WireMock](https://github.com/wiremock/wiremock-jwt-extension/tree/main)

- JWT usage examples, typically mocked via an `/oauth/token` endpoint:

  ```
  {{jwt maxAge='12 days'}}
  {{jwt exp=(parseDate '2041-02-23T21:22:23Z')}}
  {{jwt nbf=(parseDate '2019-02-23T21:22:23Z')}}
  {{jwt iss='https://issuer.trafficparrot.com/'}}
  {{jwt aud='https://audience.trafficparrot.com/'}}
  {{jwt sub='subject'}}
  {{jwt alg='RS256'}}
  {{jwt
      customBoolClaim=true
      customIntClaim=23
      customStringClaim='example@x.y.z'
      customDateClaim=(parseDate '2024-01-02T03:04:05Z')
  }}
  ```

- JSON Web Key Set (JWKS) usage example, typically mocked via an `/.well-known/jwks.json` endpoint:

  ```
  {{jwks}}
  ```

- Settings also visible via `http://localhost:8080/api/http/__admin/settings` as

  ```
  {
    "settings" : {
      "extended" : {
        "jwt" : {
          "hs256Secret" : "...",
          "rs256PublicKeyId" : "...",
          "rs256PublicKey" : "-----BEGIN RSA PUBLIC KEY-----\n...\n-----END RSA PUBLIC KEY-----\n",
          "rs256PrivateKey" : "-----BEGIN RSA PRIVATE KEY-----\n...\n-----END RSA PRIVATE KEY-----\n"
        }
      }
    }
  }
  ```

- Enable in [`trafficparrot.properties`](https://trafficparrot.com/documentation/5.65.x/properties.html) by setting:

  ```
  trafficparrot.http.jwt.enabled=true
  ```

### Fixes

- Library upgrades to fix OWASP issues

<a id="version-5-48-4"></a>
## 5.48.4 – 19 Sep 2024

### Fixes

- Library upgrades to fix OWASP issues

### Changes

- This release is compatible with the MQ `com.ibm.mq.allclient` JAR up to version [9.4.0.0](https://mvnrepository.com/artifact/com.ibm.mq/com.ibm.mq.allclient/9.4.0.0)

<a id="version-5-48-3"></a>
## 5.48.3 – 06 Aug 2024

### Fixes

- Fixed issue with HTTPS UI insecurely loading content for some API calls
- Fixed issue with HTTPS webhook certificates
- Fixed support for property lists when sending RabbitMQ JMS messages
- Fixed support for Base64 encoded bytes when [sending JMS messages from other protocols](https://trafficparrot.com/documentation/5.65.x/jms.html#send-jms-message-json")

<a id="version-5-48-0"></a>
## 5.48.0 – 27 Jun 2024

### Features

- New Thrift API to send a request by mapping id:

  ```
  curl -v http://localhost:8080/thrift/management/sendThriftMessage -d send-mapping-id=fc7ee4ad-e247-49a8-8528-af20845adde9 -d send-to-host-port=localhost:5562
  ```

- Thrift message recordings are now in JSON format

- New `{{ executeProcess '/bin/bash' '-c' 'echo hello' }}` helper to execute external processes

### Fixes

- Fixed a Thrift issue when the same method name is defined in super and subclass
- Fixed a Thrift issue with methods that are prefixes/suffixes of other methods

### Changes

- Thrift compiler binary must be version [0.10.0](https://archive.apache.org/dist/thrift/0.10.0/) for backwards compatibility reasons

<a id="version-5-47-1"></a>
## 5.47.1 – 06 Jun 2024

### Features

- Improved support for sending [one or more JMS messages after an HTTP or gRPC response](https://trafficparrot.com/documentation/5.65.x/jms.html#send-jms-message-json)
  - Messages can now be in [proto format](https://trafficparrot.com/documentation/5.65.x/grpc.html#configure-proto)
  - Message delay can now be dynamic

### Fixes

- Fixed an `{{ objectStore }}` bug where a deadlock could occur with multiple usages in the same response
- Fixed an issue with startup logging

<a id="version-5-46-8"></a>
## 5.46.8 – 22 Apr 2024

### Features

- Added support for sending [one or more JMS text messages after an HTTP or gRPC response](https://trafficparrot.com/documentation/5.65.x/jms.html#send-jms-message-json), configured via mapping JSON:

  ```
  "postServeActions" : [ {
      "name" : "send-jms-message",
      "parameters" : {
        "jmsConnectionId" : "(connection id from jms-connections.json)",
        "destination" : {
          "name" : "queue-name",
          "type" : "QUEUE"
        },
        "variables" : {
          "id" : "{{randomValue length=24 type='ALPHANUMERIC'}}"
        },
        "properties" : {
          "id" : "{{variables.id}}"
        },
        "jsonBody" : {
          "id" : "{{variables.id}}",
          "fieldFromRequest" : "{{originalRequest.jsonBody.requestField}}",
          "fieldFromResponse" : "{{originalResponse.jsonBody.responseField}}"
        },
        "delayDistribution" : {
          "type" : "fixed",
          "milliseconds" : 500
        }
      }
  } ]
  ```

- Added additional Okta JWT access token verification

- Added gRPC native transport for Apple ARM based processors

### Fixes

- Fixed desktop issue where the start and stop scripts would steal focus on launch
- Fixed logging issue where HTTP and HTTPS GUI ports would be printed in the logs even if a port is disabled
- Fixed a DNS resolution failure issue on Mac
- Improved OpenAPI parser compatibility
- Improved error message when script runtime is missing

### Changes

- Upgraded bundled JRE from 8u392 to 8u402
- Upgraded gRPC from 1.60.0 to 1.63.0
- This release is compatible with the MQ `com.ibm.mq.allclient` JAR up to version [9.3.4.1](https://mvnrepository.com/artifact/com.ibm.mq/com.ibm.mq.allclient/9.3.4.1)
- When using IBM MQ Advanced for Developers Docker [icr.io/ibm-messaging/mq:9.3.4.0-r1](https://www.ibm.com/docs/en/ibm-mq/9.3?topic=rhmo-release-history-queue-manager-container-images-use-mq-operator) and above, MQ_APP_PASSWORD must be set for the app user, the default lack of password is no longer supported by the container
- IBM MQ username and password are now interpreted as `null` if set to `""` or `"null"` in the connection JSON configuration
  - To configure a `""` value use `"<empty>"`
  - To configure a `"null"` value use `"<null>"`
- Improved JMS message logging for null property values
- Library upgrades to fix OWASP issues

<a id="version-5-45-0"></a>
## 5.45.0 – 14 Mar 2024

### Features

- Added support for default HTTP OPTIONS response based on the current HTTP mappings, enabled by:

  ```
  trafficparrot.http.optionsResponse.enabled=true
  ```

- Added support for accessing HTTP VS using the UI port, enabled by:

  ```
  trafficparrot.gui.forwardToVirtualService.enabled=true
  ```

- Added support for [Okta](https://www.okta.com/) SSO integration, enabled by:

  ```
  trafficparrot.okta.enabled=false
  trafficparrot.okta.clientId=some_client_id
  trafficparrot.okta.clientSecret=some_client_secret
  trafficparrot.okta.oktaAuthorizeUri=https://${yourOktaDomain}/oauth2/default/v1/authorize
  trafficparrot.okta.oktaTokenUri=https://${yourOktaDomain}/oauth2/default/v1/token
  trafficparrot.okta.oktaIssuerUri=https://${yourOktaDomain}/oauth2/default
  trafficparrot.okta.oktaAudience=api://default
  trafficparrot.okta.oktaRedirectUri=https://some-TP-deployment-uri
  ```

### Fixes

- Library upgrades to fix OWASP issues
- Fixed Content-Type of default text/plain OpenAPI validation response
- Fixed an issue with gRPC error responses mappings without a body defined
- Fixed an issue with JNA module not included by default with some Java installations

### Changes

- Upgraded WireMock from 2.35.1 to 2.35.2

<a id="version-5-44-0"></a>
## 5.44.0 – 12 Jan 2024

### Features

- Added support for zero response messages in server streaming record/replay gRPC

### Fixes

- Library upgrades to fix OWASP issues
- Added favicon in ICO format

### Changes

- Reduced default HTTP container threads from 500 to 100:

  ```
  trafficparrot.virtualservice.containerThreads=100
  ```

<a id="version-5-43-2"></a>
## 5.43.2 – 17 Dec 2023

### Features

- Added support for editing gRPC response delays in the UI
- Added support for editing HTTP/gRPC response delays with uniform min/max distribution in the UI
- Added support for connecting to IBM® MQ with an unspecified or null username/password

### Fixes

- Library upgrades to fix OWASP issues
- Timeout shutdown if tray icon takes too long to close

### Changes

- Upgraded protoc from 3.24.4 to 3.25.1
- Upgraded gRPC from 1.58.0 to 1.60.0
- Upgraded bundled JRE from 8u382 to 8u392
- Increased shutdown logging verbosity
- Windows executable metadata was updated
- The default [virtual service CA certificate](https://trafficparrot.com/documentation/files/virtualservice-CA-certificate.pem) was renewed
- Amazon SQS HTTP plugin retired, please contact [support@trafficparrot.com](mailto:support@trafficparrot.com) if you need extended support

<a id="version-5-42-3"></a>
## 5.42.3 – 01 Nov 2023

### Fixes

- Library upgrades to fix OWASP issues

<a id="version-5-42-2"></a>
## 5.42.2 – 19 Oct 2023

### Features

- Added support for [casting](https://trafficparrot.com/documentation/5.65.x/dynamic.html#convert-data-type) to a boolean value

- Added [request matching](https://trafficparrot.com/documentation/5.65.x/request_matching.html#request-matcher-examples) and [response templating](https://trafficparrot.com/documentation/5.65.x/dynamic.html#extract-jsonpath) examples to check for presence of an optional JSON field:

  ```
  {{#if (jsonPath request.body '$.[?(@.field)]') }}field is present{{/if}}
  {{#if (not (jsonPath request.body '$.[?(@.field)]') ) }}field is not present{{/unless}}
  {{#if (jsonPath request.body '$.[?(!(@.field))]') }}field is not present{{/unless}}
  {{#unless (jsonPath request.body '$.[?(@.field)]') }}field is not present{{/unless}}
  ```

- Added new Couchbase configuration options

  - Added support for executing a Couchbase warmup query on startup, which can improve performance of subsequent

  - Added support for setting [Couchbase IO options](https://docs.couchbase.com/java-sdk/current/ref/client-settings.html#io-options) `enableDnsSrv` and `networkResolution`

  - Enable in `database-connections.json` by setting:

    ```
    {
        "connectionId": "couchbase.db",
        "type": "COUCHBASE_CONNECTION",
        "connectionString": "couchbase://localhost:32784",
        "username": "Administrator",
        "password": "password",
        "warmupQuery": "SELECT COUNT(*) FROM bucket_a UNION SELECT COUNT(*) FROM bucket_b",
        "enableDnsSrv": true,
        "networkResolution": "auto"
    }
    ```

- Added support for OpenAPI request schema validation annotations (beta)

  - Enable in [`trafficparrot.properties`](https://trafficparrot.com/documentation/5.65.x/properties.html) by setting:

    ```
    # OFF will turn off validation
    # DEFAULT_VALIDATION will turn on validation and provide default responses when not annotated
    # ONLY_ANNOTATED will turn on validation only for annotated specifications
    trafficparrot.openapi.request.validation.mode=OFF
    ```

  - Place OpenAPI specifications in the `openapi` configuration directory

  - Requests that match the OpenAPI URL will be validated according to the schema of the parameters

  - By default, Traffic Parrot will return an HTTP 400 response with a human-readable plain text validation message of the first validation error encountered

  - You can customize which fields to validate and the error response, by annotating the OpenAPI YAML file with:

    ```
    paths:
      /items:
        get:
          parameters:
            # standard OpenAPI parameters with schema definitions
          responses:
            '400':
              content:
                application/json:
                  schema:
                    # standard OpenAPI response schema definition
              x-traffic-parrot-validation: # array of validations that trigger this response code
    ```

  - To validate the entire request and return a plain text validation message:

    ```
    x-traffic-parrot-validation:
    - type: schema
      response: ${in} parameter ${name} has invalid value ${value} because ${reason}
    ```

  - To validate the entire request and return a specific response object:

    ```
    x-traffic-parrot-validation:
    - type: schema
      response:
        code: INVALID_REQUEST
        message: ${in} parameter ${name} has invalid value ${value} because ${reason}
    ```

  - To validate particular query/path/header parameters and return a specific response object:

    ```
    x-traffic-parrot-validation:
    - type: schema
      parameters:
      - name: style
        in: query
      - name: limit
        in: query
      - name: id
        in: path
      - name: X-Request-Label
        in: header
      response:
        code: INVALID_REQUEST_PARAMETER
        message: ${in} parameter ${name} has invalid value ${value} because ${reason}
    ```

  - To validate the request body:

    ```
    x-traffic-parrot-validation:
    - type: schema
      parameters:
      - name: *
        in: requestBody
      response:
        code: REQUEST_BODY_INVALID
        message: Request body has invalid value ${value} because ${reason}
    ```

  - To perform a specific validation and fall back on a catch-all validation:

    ```
    x-traffic-parrot-validation:
    - type: schema
      parameters:
      - name: style
        in: query
      response:
        code: INVALID_QUERY
        message: query parameter ${name} has invalid value ${value} because ${reason}
    - type: schema
      response:
        code: INVALID_REQUEST
        message: ${in} parameter ${name} has invalid value ${value} because ${reason}
    ```

  - Multiple response codes can be annotated, but only one response code per OpenAPI path should have a catch-all validation

  - The template parameters `${name}` and `${value}` will be populated with the name and value of the field that failed validation

  - The template parameter `${in}` will be populated with query/path/header/requestBody

  - The template parameter `${reason}` will be populated with a human-readable description of why the validation failed

### Fixes

- Library upgrades to fix OWASP issues
- Upgrade script now migrates any previous logback configuration
- Fixed an issue where `{{ dataSource }}` errors would shadow all other context variables
- Improved internal error reporting when an expected Handlebars variable is not found or of the wrong type
- Validate that mapping queue name is not empty when saving a mapping and when starting replay mode
- Improved performance when using custom request matchers for requests that do not match the standard matcher checks

### Changes

- Upgraded WireMock from 2.35.0 to 2.35.1
- Upgraded protoc from 3.23.4 to 3.24.4
- Upgraded gRPC from 1.56.1 to 1.58.0
- Upgraded bundled JRE from 8u372 to 8u382

<a id="version-5-41-7"></a>
## 5.41.7 – 26 Aug 2023

### Fixes

- Fixed support for modifying more than one header in a Handlebars script:

  ```
  {{ modifyResponse 'headerValue' 'header-name-1' 'header-value-1' }}
  {{ modifyResponse 'headerValue' 'header-name-2' 'header-value-2' }}
  ```

- Improved system tray [OS compatibility](https://github.com/dorkbox/SystemTray#autodetect-compatibility-list)

- Fixed a bug in the `stop.sh` script impacting Apple ARM based M1/M2 processors

- The UI log file viewer now supports viewing `.gz` and `.zip` log files

### Changes

- [Logback](https://logback.qos.ch/) can now be specified as a logging provider in `jvm.args`:

  ```
  trafficparrotserver.logging.properties.filename=trafficparrotserver.logback.xml
  ```

- For organizations that have parted ways with all versions of Log4j, we now offer a distribution with those JAR files removed entirely

<a id="version-5-41-0"></a>
## 5.41.0 – 10 Aug 2023

### Features

- Random mixed case strings of a fixed length can now be generated using

  ```
  {{ randomValue length=10 type='ALPHANUMERIC' mixedcase=true }}
  ```

- Header values can now be set in Handlebars scripts using

  ```
  {{ modifyResponse 'headerValue' 'header-name' 'header-value' }}
  ```

- New simplified [OpenAPI mock import](https://trafficparrot.com/documentation/5.65.x/http.html#import-http-matching-response-code)

  - Enable in [`trafficparrot.properties`](https://trafficparrot.com/documentation/5.65.x/properties.html) by setting:

    ```
    trafficparrot.openapi.import.mode=SELECT_RESPONSE_STATUS
    trafficparrot.openapi.skeletons.mode=SELECT_RESPONSE_STATUS
    ```

  - When OpenAPI response examples are present, they are used directly as mock responses

  - Otherwise, OpenAPI schema data types and field structures are used to generate a valid mock response

  - The request header `x-traffic-parrot-select-response-status` can be set to a numeric response code to select which response to return

  - The default response returned is the success response

  - The request body is not included in matching, to simplify the response selection

  - The request URL is used for matching, including checking for mandatory path and query parameters

- Role based [UI access](https://trafficparrot.com/documentation/5.65.x/user_guide.html#role-based-access) to allow defining some read only UI users that are allowed view permissions but not edit permissions

  - Enable in [`trafficparrot.properties`](https://trafficparrot.com/documentation/5.65.x/properties.html) by setting:

    ```
    trafficparrot.gui.security.mode=LOGIN_PROPERTIES
    ```

  - Define users in `trafficparrot.gui.login.properties` by setting:

    ```
    admin=password,traffic-parrot-gui-role,traffic-parrot-gui-edit-role
    readonly=password,traffic-parrot-gui-role
    ```

  - HTTP basic authentication popup prompts users to specify a username and password

- Allow loading gRPC existing [proto set files](https://trafficparrot.com/documentation/5.65.x/grpc.html#configure-proto-bin) in `proto-bin` with `.set.bin` extension (e.g. as output by [gRPCurl](https://github.com/fullstorydev/grpcurl#describing-elements))

- Added a UI page with instructions on how to provide the required JAR files when working with IBM® MQ

### Fixes

- Library upgrades to fix OWASP issues
- `{{ evaluate 'variable' }}` now recognizes a variable that was set using `{{#assign 'variable'}}value{{/assign}}`
- Fixed an issue with the default permissions of the `lib/external` folder on Linux
- Fixed an issue with saving very large XML body mappings in the UI

### Changes

- Upgraded protoc from 3.21.9 to 3.23.4
- Upgraded gRPC from 1.51.0 to 1.56.1

<a id="version-5-40-2"></a>
## 5.40.2 – 01 Jun 2023

### Features

- Added Couchbase [data source support](https://trafficparrot.com/documentation/5.65.x/dynamic.html#data-source-couchbase):

  ```
  {{ dataSource 'couchbase.db' 'INSERT INTO PERSON(KEY, VALUE) VALUES ("$id", {"id" : $id,"name" : $name})' id=1000 name='some-name' syntax='N1QL' }}
  {{ dataSource 'couchbase.db' 'SELECT name FROM PERSON USE KEYS "$id"' id=1000 single=true syntax='N1QL' }}
  {{ dataSource 'couchbase.db' 'INSERT INTO PERSON(KEY, VALUE) VALUES ("$id", $object)' id=1000 object=example syntax='N1QL' }}
  ```

- New helper to iterate a certain number of times:

  ```
  {{#times 10}}{{@index}}{{#unless @last}},{{/unless}}{{/times}}
  ```

- New HTTP mapping bulk delete API:

  ```
  DELETE http://localhost:8080/api/http/mappings/bulk/UUID1,UUID2,UUID3
  ```

- New gRPC mapping bulk delete API:

  ```
  DELETE http://localhost:8080/api/grpc/mappings/bulk/UUID1,UUID2,UUID3
  ```

### Fixes

- Library upgrades to fix OWASP issues

### Changes

- Upgraded bundled JRE from 8u362 to 8u372
- Helper `{{#equal a b }}true{{else}}false{{/equal}` can now be written inline as `{{ equal a b }}`
- When using Handlebars partial files, it is now possible to use a different file extension than `.hbs` for example `{{>example.txt}}` will read from file `example.txt`

<a id="version-5-39-5"></a>
## 5.39.5 – 05 May 2023

### Features

- Multiple gRPC servers can now be recorded at the same time, for example:

  ```
  com.example.Service/method -> host1:port1
  com.example.packageA.* -> host2:port2
  com.example.packageB.* -> host3:port3
  ```

- Added support for [Java object Serializable Proto messages](https://protobuf.dev/reference/java/api-docs/com/google/protobuf/GeneratedMessageLite) sent over JMS connections e.g. RabbitMQ RPCs

- Added support for sending multiple types of request/response message (e.g. two different Java Proto request/response pairs) on a single request/response queue pair

- Added support for RabbitMQ `contentType` header

- Added PostgreSQL example connection to `database-connections.json`

- JSON request/response field data in mappings can now be externalized to/from `MappingData.csv` for an alternative way to edit field data across multiple mappings in a table format

- Tools UI menu with links to simple file editor and mapping field data externalization

### Fixes

- JMS advanced request and response types are now retained in the UI form when starting/stopping recording
- Improved HTTP recording UI error message when there is a problem fetching recording status in the UI
- Increase HTTP recording UI status timeout to cope better with slow browser connections
- If there is a problem decoding a recorded JMS message, fall back on a raw bytes recording representation
- Mention which actual connection ids were present when a JMS connection id is not found
- Removed deprecated "matches script" option from the request body matcher dropdown (replaced by dedicated fields)

### Changes

- Upgraded bundled JRE from 8u352 to 8u362
- When matching JMS requests, mappings for Java object Serializable requests now must have the `bodyType` specified
- The default UI HTTPS certificate `user-interface-https.jks` was renewed

<a id="version-5-38-1"></a>
## 5.38.1 – 09 Apr 2023

### Features

- Add request/response recording Protobuf type fields to JMS UI

<a id="version-5-38-0"></a>
## 5.38.0 – 03 Apr 2023

### Features

- RabbitMQ JMS now supports record/replay of Protobuf messages using their JSON representation
- Added new dedicated endpoints that can be used for Docker and OpenShift health check probes:
  - `http://localhost:8080/api/health`
  - `http://localhost:8081/__admin/health`
- The `trafficparrot.license` comment line is now printed in the logs to help clarify which license is being used

### Fixes

- If we can't import an OpenAPI YAML file example due to a schema mismatch exception, skip that one example and log why it was not imported
- Library upgrades to fix OWASP issues

<a id="version-5-37-8"></a>
## 5.37.8 – 27 Mar 2023

### Fixes

- Added support for protoc on Apple ARM based M1/M2 processors running inside of Docker

<a id="version-5-37-7"></a>
## 5.37.7 – 20 Mar 2023

### Features

- New [HTTP request matching script](https://trafficparrot.com/documentation/5.65.x/http.html#add-edit-request-matcher-script) can be used to e.g. match a request header using a regular expression
- New `{{evaluate}}` helper to [evaluate a JavaScript command](https://trafficparrot.com/documentation/5.65.x/dynamic.html#evaluate)
- JMS recording now supports requests that use JMSReplyTo
- JMS IBM MQ new toggle in connection to enable copying request JMSMessageID to response JMSMessageID
- RabbitMQ JMS improvements including:
  - RabbitMQ [RPC](https://www.rabbitmq.com/direct-reply-to.html) support
  - RabbitMQ [replyTo](https://subscription.packtpub.com/book/application-development/9781783984565/2/ch02lvl1sec16/request-reply-communication) support
  - RabbitMQ [virtual host](https://www.rabbitmq.com/vhosts.html) support
  - Declare queue if it does not already exist in the broker on record/replay start using the arguments specified in the connection e.g. `x-max-length`
- Object store improvements including:
  - All operations are now thread safe within a single Traffic Parrot instance
  - A default value can be specified to return if an object is not found
- `trafficparrot.virtualservice.handlebars.select.indexAndCacheCsvFiles` property is now also taken into account for `{{ dataSource }}` CSV file access

### Fixes

- Allow API requests to set the `Accept` header with multiple content types, so long as the first one listed is `application/json`
- Fixed an issue with the scenario dropdown when no default port specified
- If there is an exception when starting, e.g. due to a missing property, startup fails immediately instead of waiting the full timeout duration to fail
- If the `trafficparrot.license` does not exist on startup, a relevant message is now displayed in the UI
- Improved compatibility with OpenShift 4 when using a TLS passthrough route to the license server

### Changes

- gRPC matching now returns the closest match if multiple candidate responses match and warns in the logs about multiple matches
- Bundle `third-party-licenses.zip` instead of many small license text files, which were slow to extract on Windows

<a id="version-5-36-4"></a>
## 5.36.4 – 30 Jan 2023

### Features

- New [upgrade script](https://trafficparrot.com/documentation/5.65.x/user_guide.html#upgrade) supporting Linux/Mac/Windows
- The tray icon now displays the installation location and has a link to the latest Traffic Parrot documentation
- The default implementation of `{{now}}` can be toggled using [`trafficparrot.properties`](https://trafficparrot.com/documentation/5.65.x/properties.html)
  - To use the Handlebars.java `{{now}}` helper:

    ```
    trafficparrot.virtualservice.handlebars.now.provider=HANDLEBARS
    ```

  - To use the WireMock `{{now}}` helper:

    ```
    trafficparrot.virtualservice.handlebars.now.provider=WIREMOCK
    ```
- Alternatively, you can add the `provider` parameter per call to dynamically switch between them, otherwise the default implementation specified in [`trafficparrot.properties`](https://trafficparrot.com/documentation/5.65.x/properties.html) will be used
  - To enable this set in [`trafficparrot.properties`](https://trafficparrot.com/documentation/5.65.x/properties.html):

    ```
    trafficparrot.virtualservice.handlebars.now.dynamic=true
    ```

  - To use the WireMock implementation:

    ```
    {{now offset='2 years' format='epoch' provider='WIREMOCK'}}
    ```

  - To use the Handlebars.java implementation:

    ```
    {{now format='short' provider='HANDLEBARS'}}
    ```

### Fixes

- Fixed a bug when parsing single quotes in OpenAPI specifications

### Changes

- Upgraded bundled JRE from 8u345 to 8u352
- This release is compatible with the MQ `com.ibm.mq.allclient` JAR up to version [9.3.1.0](https://mvnrepository.com/artifact/com.ibm.mq/com.ibm.mq.allclient/9.3.1.0)
- Mention both `tp.out` and `trafficparrot.log` when there is a problem starting

<a id="version-5-35-8"></a>
## 5.35.8 – 19 Dec 2022

### Features

- Added new "does not contain" request matcher support to the UI

### Fixes

- API now allows cross-origin requests
- Trim whitespace from JSONPath request matcher to avoid confusing not matched issues
- Fixed an issue exporting/importing HTTP mappings ZIP between different scenarios
- Fixed a UI issue where gRPC mappings were saved with empty webhooks
- Library upgrades to fix OWASP issues

### Changes

- UI now makes it clear that HTTP record/proxy/passthrough is not supported in a non default scenario yet
- Upgraded gRPC from 1.50.2 to 1.51.0

<a id="version-5-35-6"></a>
## 5.35.6 – 07 Dec 2022

### Fixes

- Library upgrades to fix OWASP issues

### Changes

- HTTP mapping ZIP export now includes data directory

<a id="version-5-35-5"></a>
## 5.35.5 – 10 Nov 2022

### Features

- Added support for Apache [Thrift](https://trafficparrot.com/documentation/5.65.x/thrift.html) service simulation, see a [demo video](https://www.youtube.com/watch?v=pJTdDH20o3c)
- Added ability to configure HTTP basic authentication for the Traffic Parrot user interface
  - Enable in the [`trafficparrot.properties`](https://trafficparrot.com/documentation/5.65.x/properties.html) file by setting:

    ```
    trafficparrot.gui.security.mode=LOGIN_PROPERTIES
    ```

  - Configure users in the `trafficparrot.gui.login.properties` file, in Jetty [HashLoginService](https://wiki.eclipse.org/Jetty/Tutorial/Realms#HashLoginService) format:

    ```
    admin=password,traffic-parrot-gui-role
    ```

### Fixes

- Fixed a UI issue with mappings edited multiple times during the same UI session
- Added support for protoc on Apple ARM based M1/M2 processors
- Library upgrades to fix OWASP issues

### Changes

- Upgraded bundled JRE from 8u332 to 8u345
- Upgraded WireMock from 2.33.2 to 2.35.0
- Upgraded gRPC from 1.46.0 to 1.50.2
- Upgraded protoc from 3.20.1 to 3.21.9

<a id="version-5-34-7"></a>
## 5.34.7 – 14 Oct 2022

### Fixes

- Fixed an issue with the enabled script for HTTP webhook callbacks
- Fixed an issue with XLS data stores when storing and retrieving values with leading zeros
- Library upgrades to fix OWASP issues

<a id="version-5-34-3"></a>
## 5.34.3 – 16 Sep 2022

### Features

- Added example of GCP Dialogflow gRPC [bidirectional streaming mocks](https://github.com/trafficparrot/trafficparrot-examples-dialogflow)

### Fixes

- Library upgrades to fix OWASP issues

<a id="version-5-34-0"></a>
## 5.34.0 – 02 Aug 2022

### Features

- Added support for [gRPC bidirectional streaming](https://trafficparrot.com/documentation/5.65.x/grpc.html#streaming-modes-bidirectional-streaming)
- Added support for a comment line in the `trafficparrot.license` file

### Fixes

- Library upgrades to fix OWASP issues

### Changes

- The HTTP passthrough will be removed in a future release. Please use the [proxy response](https://trafficparrot.com/documentation/5.65.x/http.html#add-edit-proxy) feature instead.

<a id="version-5-33-11"></a>
## 5.33.11 – 03 Jun 2022

### Features

- Added access logging for UI interactions, written to `logs/http-ui-access/http-ui-access-yyyy_mm_dd.log`

### Changes

- Upgraded bundled JRE from 8u282 to 8u332
- Upgraded gRPC from 1.43.1 to 1.46.0
- Upgraded protoc from 3.19.1 to 3.20.1
- Upgraded WireMock from 2.31.0 to 2.33.2
- HTTP VS access logs are now written to `logs/http-vs-access/http-vs-access-yyyy_mm_dd.log`
- Upgraded Gradle version in examples project from 4.10.1 to 7.4.2
- Logs file listing in UI is now ordered by last modified date

### Fixes

- Library upgrades to fix OWASP issues

<a id="version-5-33-5"></a>
## 5.33.5 – 09 May 2022

### Features

- Added new [`trafficparrot.properties`](https://trafficparrot.com/documentation/5.65.x/properties.html) to allow sending custom headers to the on premise license server: `trafficparrot.license.usage.custom.headers=ExampleA:ValueA,ExampleB:ValueB`

### Changes

- Pressing the Cancel button on the Add mapping form now clears the form fields

### Fixes

- Library upgrades to fix OWASP issues

<a id="version-5-33-2"></a>
## 5.33.2 – 14 Mar 2022

### Features

- Native IBM® MQ mapping [multiple response messages](https://trafficparrot.com/documentation/5.65.x/ibmmq.html#zero-response-messages) now support zero response messages. This allows for consuming request messages without sending any response message.
- Added new [`trafficparrot.properties`](https://trafficparrot.com/documentation/5.65.x/properties.html) to allow starting JMS queue replay on startup:
  - `trafficparrot.jms.start.queue.replay.on.startup=false`
  - `trafficparrot.jms.start.queue.replay.on.startup.consumeRequestsFromConnectionId=1`
  - `trafficparrot.jms.start.queue.replay.on.startup.replayResponsesToConnectionId=1`
- Extended virtual service support for using multiple JMS [virtual services](https://trafficparrot.com/documentation/5.65.x/virtual_services.html) linked to separate mappings:
  - The `scenarios/VirtualServiceName/service.properties` now allows for [configuring](https://trafficparrot.com/documentation/5.65.x/virtual_services.html#virtual-service-properties):
    - `jms.queue.replay.on.startup=true`
    - `jms.queue.replay.request.connection.id=1`
    - `jms.queue.replay.response.connection.id=1`
  - The `scenarios/VirtualServiceName/jms-connections.json` file is used to specify the queue manager connections per virtual service
  - The `scenarios/VirtualServiceName/jms-mappings` directory contains the mappings files per virtual service
  - The UI allows starting JMS replay for multiple virtual services at a time
- RabbitMQ JMS queue declare arguments can now be specified in the [mapping JSON](https://trafficparrot.com/documentation/5.65.x/jms.html#edit-jms-mapping-json). Please note that the UI does not yet support this feature.
- RabbitMQ JMS queue names may now be specified in the format `exchange/routingKey` instead of a direct queue name

### Changes

- Upgraded bundled JRE from 8u292 to 8u322
- RabbitMQ JMS with AMQP compatibility mode enabled does not support topics and will now fail with an error message

### Fixes

- Fix for too long error message with `{{ dataSource }}` when template parameters values incorrectly contain further template parameter keys
- Fix to support using RabbitMQ AMQP replyTo to send a message to a temporary response queue as indicated in the request message replyTo property
- Library upgrades to fix OWASP issues

<a id="version-5-32-0"></a>
## 5.32.0 – 17 Feb 2022

### Features

- Added support for using a proxy server with path based routing between Traffic Parrot and the license server

<a id="version-5-31-2"></a>
## 5.31.2 – 30 Jan 2022

### Features

- Added ability to import and export IBM MQ mappings in ZIP file format
- JMS response messages now populate the response JMSCorrelationID using the JMSCorrelationID from the request message if it is present or else the JMSMessageID from the request
- JMS response messages are now sent to the JMSReplyTo destination if present or else the mapping destination is used

### Changes

- Updated VS HTTPS certificates with new 3 year validity period

<a id="version-5-30-1"></a>
## 5.30.1 – 07 Jan 2022

### Features

- Added support for connecting to an internal or external ActiveMQ broker via JMS AMQP 1.0
- Added support for username/password when connecting to external ActiveMQ broker

### Changes

- Include ActiveMQ sample JMS AMQP 1.0 connection

### Fixes

- Library upgrades to fix OWASP issues
- Fixed an issue with the `{{ regex }}` helper when using an `{{ xPath }}` result as a parameter

<a id="version-5-29-7"></a>
## 5.29.7 – 31 Dec 2021

### Features

- Added new [`trafficparrot.properties`](https://trafficparrot.com/documentation/5.65.x/properties.html) to allow configuring separate HTTP and HTTPS ports for the UI:
  - `trafficparrot.gui.http.port=8080`
  - `trafficparrot.gui.http.port.enabled=true`
  - `trafficparrot.gui.https.port=8079`
  - `trafficparrot.gui.https.port.enabled=true`
  - `trafficparrot.gui.https.jks.resource=certificates/user-interface-https.jks`
  - `trafficparrot.gui.https.jks.password=trafficparrot`
- Added support for connecting to an external RabbitMQ 3 broker via JMS
- Added support for HTTP webhooks including:
  - UI to configure callback on the HTTP Add/Edit mapping page
  - Send request callback after a fixed delay
  - Use data from the original request and response body in the callback request template
  - Enable callback to be sent or not based on script
- Added support for uploading data directory when uploading an HTTP mappings zip file
- Added support for `DOTALL` option in `{{ regexExtract }}` helper

### Changes

- Upgraded WireMock from 2.29.1 to 2.31.0
  - WireMock [removed support](https://github.com/wiremock/wiremock/commit/a16b92e39628395548d7a215c113a0a7414e8cd8) for parameter normalizing in response templates
  - To restore parameter normalizing behaviour, please set: `trafficparrot.virtualservice.handlebars.normalizeHelperParameters=true`
- Upgraded gRPC from 1.39.0 to 1.43.1
- Upgraded protoc from 3.17.3 to 3.19.1
- Include RabbitMQ sample JMS connection

### Fixes

- Fixed a bug with indexed `{{ dataSource }}` parameters
- Fixed a bug with mixed type XLS columns
- Fixed a bug with the tray icon on Windows
- Library upgrades to fix OWASP issues

<a id="version-5-28-2"></a>
## 5.28.2 – 09 Sep 2021

### Features

- Added a new property that allows to skip starting the web user interface `trafficparrot.gui.enabled`. By default, the user interface is enabled, but it can be disabled for example in CI/CD builds or pipelines to allow TP to use less resources.
- Added a new property to allow skipping MQ RFH headers when matching the body of an MQ request message `trafficparrot.ibmmq.skipHeadersInRequestMessageBodyWhenMatching=true`
- Added UI for viewing archived log files. Note that this currently supports only plain text archived log files without compression, as used in the default `trafficparrotserver.log4j.properties` configuration
- Improve list of gRPC skeletons when multiple `oneof` or `optional` fields used in response

### Changes

- Upgraded WireMock from 2.29.0 to 2.29.1

<a id="version-5-27-3"></a>
## 5.27.3 – 22 Jul 2021

### Features

- Added a new helper to [convert](https://trafficparrot.com/documentation/5.65.x/dynamic.html#convert-data-type) between data types in responses, which can be useful when combining helpers that require specific data types e.g. `{{ randomInteger 0 (cast (xPath request.body '/Node/Max/text()') type='int') }}`
- Added a new helper to use an existing XLS/CSV/JDBC as a [data source](https://trafficparrot.com/documentation/5.65.x/dynamic.html#data-source) in responses, which can be used to lookup or update data e.g. `{{ dataSource 'name.db' 'SELECT name FROM person WHERE id = :id' id=(cast (xPath request '//data/id/text()') type='string') single=true }}`
- Added a new helper to allow [modifying](https://trafficparrot.com/documentation/5.65.x/dynamic.html#modify-response) the HTTP response code e.g. `{{ modifyResponse 'statusCode' 404 }}`
- Added negate and round operations to the [arithmetic operations](https://trafficparrot.com/documentation/5.65.x/dynamic.html#math) helper
- Added a new helper to manage a simple JSON [object store](https://trafficparrot.com/documentation/5.65.x/dynamic.html#object-store) that can be used to help implement simple stateful mocks (beta)
- Line breaks are now supported in helper string arguments
- Added a minimal configuration file editor to the configuration page to allow files that do not have dedicated UI elements to be edited via the UI as plain text files

### Fixes

- Fixed a bug where directory structure was not properly created when importing a zip of proto files
- Fixed a UI memory leak that occurred when the Add/Edit page was left open for too long
- Fixed support for HTTP state machine transitions

### Changes

- Change [SDK workspace](https://trafficparrot.com/documentation/5.65.x/downloads/trafficparrot-sdk-workspace-5.65.x.zip) examples to use non-deprecated SDK methods
- Upgraded bundled JRE from 8u282 to 8u292
- Upgraded WireMock from 2.27.2 to 2.29.0
- Upgraded gRPC from 1.36.0 to 1.39.0
- Upgraded protoc from 3.15.5 to 3.17.3

<a id="version-5-26-3"></a>
## 5.26.3 – 14 Jun 2021

### Features

- Added a new helper to allow calculating and formatting [date offsets](https://trafficparrot.com/documentation/5.65.x/dynamic.html#date-offset) in responses e.g. `{{ dateOffset (jsonPath request.body '$.date_field') add=true format='yyyy-MM-dd' days=1 }}`
- Added support for accessing a standard set of [runtime properties](https://trafficparrot.com/documentation/5.65.x/dynamic.html#custom-extensions-runtime-properties) in plugins so that e.g. plugins can be supplied with configuration files at runtime that are placed in virtual service specific or global shared directories

### Fixes

- Improved support for [handlebars partial template files](https://handlebarsjs.com/guide/partials.html):
  - The root for partials now takes into account the directory specified in `trafficparrot.virtualservice.trafficFilesRootUrl=file:.`
  - The root for partials when using virtual services is the named directory `scenarios/ScenarioName/*.hbs`

<a id="version-5-25-0"></a>
## 5.25.0 – 10 May 2021

### Features

- Traffic Parrot now allows defining [multiple response messages per one Native IBM® MQ mapping](https://trafficparrot.com/documentation/5.65.x/ibmmq.html#multiple-response-messages). This enables sending multiple response messages for one request message.

<a id="version-5-24-11"></a>
## 5.24.11 – 16 Apr 2021

### Features

- Properties not defined in [`trafficparrot.properties`](https://trafficparrot.com/documentation/5.65.x/properties.html) will now fall back on default values. The settings UI page and log file will display which properties are using default values not taken from the properties file.

### Fixes

- Improved diagnostic logging when ports are already in use at startup time
- Maven MQ [examples project](https://trafficparrot.com/documentation/5.65.x/downloads/trafficparrot-examples-5.65.x.zip) now includes MQCSP parameter

### Changes

- This release is compatible with the MQ `com.ibm.mq.allclient` JAR up to version [9.2.2.0](https://mvnrepository.com/artifact/com.ibm.mq/com.ibm.mq.allclient/9.2.2.0)

<a id="version-5-24-9"></a>
## 5.24.9 – 25 Mar 2021

### Features

- Extended virtual service support for using multiple native IBM® MQ [virtual services (beta)](https://trafficparrot.com/documentation/5.65.x/virtual_services.html) linked to separate mappings:
  - The `scenarios/VirtualServiceName/service.properties` now allows for [configuring](https://trafficparrot.com/documentation/5.65.x/virtual_services.html#virtual-service-properties):
    - `ibm.mq.queue.replay.on.startup=false`
    - `ibm.mq.queue.replay.request.queue.manager=REQ.QM`
    - `ibm.mq.queue.replay.response.queue.manager=RSP.QM`
  - The `scenarios/VirtualServiceName/ibm-mq-connections.json` file is used to specify the queue manager connections per virtual service
  - The `scenarios/VirtualServiceName/ibm-mq-mappings` directory contains the mappings files per virtual service
  - The UI allows starting MQ replay for multiple virtual services at a time
- The configuration points `database-connections.json`, `data` and `ibm-mq-connections.json` are now configured per virtual service relative to the virtual service directory rather than globally
- The `service.properties` file is now sorted by key when changes are made via the UI
- The logs now contain the virtual service name to help determine which log lines correspond to which virtual services

### Fixes

- Improved OpenAPI import examples compatibility
- Fixed an issue where the total number of MQ `writeConnectionsToOpen` specified in `ibm-mq-connections.json` was incorrectly being read from the `readConnectionsToOpen` field
- Fixed a race condition where a scenario change could result in HTTP mapping file bodies being momentarily loaded from the incorrect directory
- Fixed an issue where some temporary directories were not being cleaned up properly on shutdown
- Fixed an issue where refreshing the page after stopping replay mode would result in attempting a form resubmission
- Fixed an issue where the UI log pages would sometimes be incorrectly detected as binary files by the browser and downloaded instead of displayed

### Changes

- The [xPath](https://trafficparrot.com/documentation/5.65.x/dynamic.html#extract-xpath) helper now allows iteration over specific extracted nodes as an alternative to using the [xPathList](https://trafficparrot.com/documentation/5.65.x/dynamic.html#extract-xpath) helper, which iterates over all of the child nodes
- The [equal](https://trafficparrot.com/documentation/5.65.x/dynamic.html#conditionals) helper now additionally considers the arguments to be equal if they convert to the same string representation when rendered (e.g. XML nodes)
- Upgraded bundled JRE from 8u262 to 8u282
- Upgraded WireMock from 2.27.1 to 2.27.2
- Upgraded gRPC from 1.31.1 to 1.36.0
- Upgraded protoc from 3.12.0 to 3.15.5
- This release is compatible with the MQ `com.ibm.mq.allclient` JAR up to version [9.2.1.0](https://mvnrepository.com/artifact/com.ibm.mq/com.ibm.mq.allclient/9.2.1.0)

<a id="version-5-23-0"></a>
## 5.23.0 – 01 Feb 2021

### Features

- Initial release of Traffic Parrot workstation client (beta):
  - The [workstation (beta)](https://trafficparrot.com/documentation/5.65.x/workstation.html) is part of a new client-server product offering for customers
  - Traffic Parrot workstation clients create virtual services and save configuration files
  - Traffic Parrot servers run virtual services using the configuration files created by the clients
  - Configuration files can be stored and retrieved from version control systems or artifact repositories
- Initial support for using multiple HTTP/HTTPS ports linked to separate mappings (beta):
  - New [virtual services (beta)](https://trafficparrot.com/documentation/5.65.x/virtual_services.html) page to view/add/edit/delete virtual services
  - A distinct HTTP/HTTPS port may be assigned per virtual service
  - Only one virtual service can be edited at a time by selecting from the dropdown
  - The home page now lists all virtual service names and ports
  - Configuration is currently stored in `scenarios/VirtualServiceName/service.properties` directory structure
  - Increasing the number of virtual services will have a direct impact on memory usage of the server
  - Consider increasing your `jvm.args` configuration heap size `-Xmx128m` if you plan to use multiple virtual services per Traffic Parrot instance
- New [arithmetic operations](https://trafficparrot.com/documentation/5.65.x/dynamic.html#math) in dynamic responses

### Fixes

- Fixed an issue where the navigation bar overlapped the main content on some smaller screen sizes
- Fixed an issue where transformer names would be duplicated in mapping files on save

<a id="version-5-22-3"></a>
## 5.22.3 – 11 Nov 2020

### Fixes

- Minor fixes to UI text
- Ensure mapping name when edited via the UI ends in .json

<a id="version-5-22-0"></a>
## 5.22.0 – 19 Oct 2020

### Features

- Made mapping name editable in the UI for all mapping types

### Fixes

- Ensure internal server errors log the full stack trace

### Changes

- Native IBM® MQ connections will now warn once in the logs the first time that a connection is shared between multiple threads, which can degrade performance. The mapping fields `receiveThreads` and `sendThreads` control the number of threads per queue. The `ibm-mq-connections.json` configuration controls the total `readConnectionsToOpen` and `writeConnectionsToOpen` per queue manager.

<a id="version-5-21-6"></a>
## 5.21.6 – 12 Oct 2020

### Features

- New property `trafficparrot.virtualservice.http.monitorPerformance` can be used to enable HTTP response timings in the logs:

  ```
  2020-10-07 20:09:32,330 INFO  Request to 'GET /test123' was received on '2020-10-07T19:09:32.326Z' from '127.0.0.1'. Response was sent on '2020-10-07T19:09:32.397Z' to '127.0.0.1'. Total processing time 71ms
  ```

- Added new PassthroughMessage MQ proxy example to the [SDK workspace](https://trafficparrot.com/documentation/5.65.x/downloads/trafficparrot-sdk-workspace-5.65.x.zip)

### Fixes

- Fixed support for OpenAPI array examples specified as a comma separated string
- Ensure startup error causes are recorded in the logs

### Changes

- Upgraded bundled JRE from 8u262 to 8u265
- Display system tray in a background thread to improve startup times on some systems
- Valid JSON bodies in mapping files will be persisted as inline JSON rather than an escaped string

<a id="version-5-20-2"></a>
## 5.20.2 – 25 Sep 2020

### Features

- Mappings list user interface improvements for all protocols:
  - Added support for customizing which columns are displayed in the mappings list in the UI. The selected settings are stored in the browser to allow different Traffic Parrot users to set different preferences.
  - Display mapping file name when editing a mapping
- Mappings list user interface improvements for HTTP protocol:
  - Edit mapping tags that can be used to organize and search mappings
  - Added new tags column which is hidden by default
- Added mapping file name to the logs when reporting request match status for MQ/JMS/Files mappings

### Fixes

- Switching scenario with mappings caches enabled now resets the caches
- Traffic Parrot now shuts down gracefully on Windows when the stop script is run
- Fixed an issue where the HTTP virtual service would not respond if a mapping file was deleted while the request was being served

<a id="version-5-19-4"></a>
## 5.19.4 – 14 Sep 2020

### Features

- Added support for configuring gRPC delays via `fixedDelayMilliseconds` or `distributionDelay` in the mapping files
- Exposed new properties for tuning gRPC performance:
  - `trafficparrot.virtualservice.grpc.server.receiveThreads=DOUBLE_NUMBER_OF_PROCESSORS`
  - `trafficparrot.virtualservice.grpc.server.sendThreads=DOUBLE_NUMBER_OF_PROCESSORS`
  - `trafficparrot.virtualservice.grpc.server.replay.maxMessagesWaitingToBeSent=1000`

### Fixes

- Traffic Parrot now shuts down gracefully when the launcher process is killed (e.g. during a docker stop)

### Changes

- Only consider TCP ports when printing diagnostic information when there is a port clash on startup

<a id="version-5-18-0"></a>
## 5.18.0 – 05 Sep 2020

### Features

- Added support for Log4j version 2.
- Added logging [that allows for monitoring Native IBM MQ performance](https://trafficparrot.com/documentation/5.65.x/ibmmq.html#performance-monitoring-configuration).

### Fixes

- Fixes to the gRPC mappings list editing and search mechanism
- Fixed a bug where the edit modal would incorrectly close automatically if closed and reopened too quickly
- Fixed a bug where the edit modal would show the previous flash message if closed and reopened too quickly
- Fixes for JMS `java.io.Serializable` object support
- Fixes for port in use diagnostic message when multiple PIDs are involved

### Changes

- The property `trafficparrotserver.log4j.properties.filename` has been replaced by `trafficparrotserver.logging.properties.filename`.
- Logging properties file names indicate which type of logging configuration to use:
  - Names like \*.log4j.\* are assumed to be Log4j version 1 configuration
  - Names like \*.log4j2.\* are assumed to be Log4j version 2 configuration
- The MQ message putDateTime log line now has a millisecond (instead of second) resolution to help investigate performance issues when working with Native IBM MQ

<a id="version-5-17-0"></a>
## 5.17.0 – 25 Aug 2020

### Features

- Internal release that was used for training purposes

<a id="version-5-16-0"></a>
## 5.16.0 – 10 Aug 2020

### Features

- Select handlebars helper CSV file caching. When you set

  ```
  trafficparrot.virtualservice.handlebars.select.indexAndCacheCsvFiles=true
  ```

  the CSV file loading performance will be significantly improved.

- Supporting large number of CPU cores. When you run Traffic Parrot on many cores (40 or more) it would fail to start and report an error

  ```
  javax.servlet.ServletException: java.lang.IllegalStateException: Insufficient configured threads: required=212 < max=200 for QueuedThreadPool[qtp318353283]@12f9af83{STARTED,8<=168<=200,i=0,r=20,q=0}[ReservedThreadExecutor@71b3bc45{s=0/20,p=0}]
  ```

  The fix is to increase the number of threads Jetty can spin up. This was done by exposing two properties to configure HTTP Jetty server thread queues:

  ```
  trafficparrot.gui.http.queuedThreadPool.maxThreads=200
  trafficparrot.gui.http.queuedThreadPool.minThreads=8
  ```

### Changes

- Performance improvements to dynamic responses
- Upgraded bundled JRE from 8u222 to 8u262
- Upgraded WireMock from 2.25.1 to 2.27.1

<a id="version-5-15-0"></a>
## 5.15.0 – 16 Jul 2020

### Features

- Traffic Parrot can now connect to IBM MQ queue managers via SSL channels. You can do this via Native IBM MQ. We have added two new ibm-mq-connections.json properties to support Native IBM MQ SSL connections:

  ```
  "sslCipherSuite": "TLS_RSA_WITH_AES_128_CBC_SHA",
  "sslPeerName": "OU=TP IBM MQ"
  ```

  To provide the server and client certificates you can add the following config to jvm.args:

  ```
  -Djavax.net.ssl.trustStore=certificates/ca-chain.jks
  -Djavax.net.ssl.trustStorePassword=trafficparrot
  -Djavax.net.ssl.keyStore=certificates/mq-client.jks
  -Djavax.net.ssl.keyStorePassword=trafficparrot
  -Dcom.ibm.mq.cfg.useIBMCipherMappings=false
  ```

  For more details see [Connect to the queue manager via SSL/TLS channels](https://trafficparrot.com/documentation/5.65.x/ibmmq.html#ssl-tls-configuration)

<a id="version-5-14-1"></a>
## 5.14.1 – 10 Jul 2020

### Features

- A new property that allows to force logging Native IBM MQ message bodys as printable characters instead of UTF8

  ```
  trafficparrot.ibmmq.logger.logMessageBodyAsPrintableCharacters=false
  ```

### Fixes

- The Native IBM MQ messages can now contain UTF-8 characters, for example Arabic text
- The Native IBM MQ logs are now correctly displaying UTF-8 characters, for example Arabic text
- The JMS IBM MQ tutorial example fruit ordering system now supports UTF8 characters, for example Arabic text

<a id="version-5-13-0"></a>
## 5.13.0 – 07 Jul 2020

### Features

- New environment variable that allows configuring how long the startup scripts will wait for TP to start up use `TP_STARTUP_WAIT_MILLIS`, for example:

  ```
  test@test-pcs:~/Downloads/trafficparrot-no-jre-5.x.y$ export TP_STARTUP_WAIT_MILLIS=180000
  test@test-pcs:~/Downloads/trafficparrot-no-jre-5.x.y$ ./start.sh
  /optf/programs/jdk1.8.0_181/bin/java
  Picked up environment startup timeout in milliseconds 180000
  ```

- A new property that allows to specify a replay Native IBM MQ script that will be run on startup

  ```
  trafficparrot.ibmmq.start.queue.replay.on.startup.script=classpath:start-ibmmq-queue-replay-on-startup.txt
  ```

### Changes

- The SDK Workspace allows now for Native IBM MQ message transformers to specify an MQMessage directly. This allows for creating transforming proxies of messages. A sample has been provided in the SDK workspace.

### Fixes

- Users were unable to update Native IBM MQ mappings in renamed files.

<a id="version-5-12-0"></a>
## 5.12.0 – 26 May 2020

### Features

- New property that allows configuring how IBM® MQ queues will be accessed

  ```
  trafficparrot.ibmmq.connect.options.accessQueue.output=MQOO_OUTPUT|MQOO_FAIL_IF_QUIESCING
  ```

- New property that allows to skip logging message body for native IBM® MQ

  ```
  trafficparrot.ibmmq.logger.logMessageBody=true
  ```

- Native IBM® MQ now respects the existing properties that allow for caching mappings in memory

  ```
  trafficparrot.virtualservice.mapping.cache.milliseconds=0
  trafficparrot.virtualservice.mapping.cache.populate.on.startup=false
  ```

- You can now configure per connection to an IBM® MQ broker how many read and how many write connections to open. You do it in the `ibm-mq-connections.json`. For example:

  ```
  "readConnectionsToOpen": 5,
  "writeConnectionsToOpen": 5
  ```

- The Native IBM® MQ mapping allows for configuring how many threads should be used to access the queue, for example:

  ```
  "receiveThreads" : 5,
  "sendThreads" : 1
  ```

- You can define in the mapping how many messages the Native IBM® MQ connector will be keeping in memory at once, which will be relevant for scenarios when sending delayd messages, for example:

  ```
  "maxMessagesInProgress": 1000000
  ```

- You can start the Native IBM® MQ replay with a script, for example:

  ```
  #
  # This is a sample comment 1
  #
  RequestQueueManager:'Request QM1'
  ResponseQueueManager:'Response QM1'
  RequestQueueNames:'REQ_1_A','REQ_1_B'

  #
  # This is a sample comment 2
  #
  RequestQueueManager:'Request QM2'
  ResponseQueueManager:'Response QM2'
  RequestQueueNames:'REQ_2_A','REQ_2_B'
  ```

- Handlebar templates are cached allowing for better performance

### Changes

- There has been performance improvements made to the Native IBM® MQ connector. See the [performance benchmarks](https://trafficparrot.com/documentation/5.65.x/performance_testing.html#example-performance-native-mq) for more details.
- Native IBM® MQ response messages during a replay have the replyToQueueEmpty and replyToQueueManager set to the connected queue manager if they did not have any of these attributes set on the request message
- Native IBM® MQ sends the queue manager name along with queue name when sending a message. This is applicable in scenarios with multiple queue managers set up in a cluster without the cluster sender and cluster receiver channels
- Logging more runtime information on startup
- Additional logging when connections to IBM® MQ fail

<a id="version-5-11-1"></a>
## 5.11.1 – 06 Apr 2020

### Changes

- Updated VS HTTPS certificates with new 3 year validity period

<a id="version-5-10-0"></a>
## 5.10.0 – 17 Jan 2020

### Features

- Added support for IBM®MQ [message delays](https://trafficparrot.com/documentation/5.65.x/ibmmq.html#edit-mq-delay) in replay mode

- Added support for specifying multiple IBM®MQ queues, using queue manager names from `ibm-mq-connections.json` to record using syntax in script tab in the UI:

  ```
  #
  # This is a sample comment
  #
  QueueManager:'Local Docker MQ 9'
  ProxyRequestQueue:'PROXY_PROCESS_PAYMENT'
  LiveRequestQueue:'PROCESS_PAYMENT'
  LiveResponseQueue:'PAYMENT_PROCESSESED'
  ProxyResponseQueue:'PROXY_PAYMENT_PROCESSESED'


  #
  # This is a sample comment
  #
  QueueManager:'Local Docker MQ 9'
  ProxyRequestQueue:'PROXY_CREATE_ORDER'
  LiveRequestQueue:'CREATE_ORDER'
  LiveResponseQueue:'ORDER_CREATED'
  ProxyResponseQueue:'PROXY_ORDER_CREATED'
  ```

### Fixes

- Ensure IBM®MQ channel connections are always released after use

<a id="version-5-9-0"></a>
## 5.9.0 – 16 Dec 2019

### Features

- Improvements to gRPC mappings list user interface:
  - Edit mapping tags that can be used to organize and search mappings
  - Added new tags column which is hidden by default

### Fixes

- WireMock compatible HTTP APIs are now hosted on both:

  - `http://localhost:8080/api/http/__admin/*`
  - `http://localhost:8080/api/http/*`

  This means that the standard WireMock client libraries can be used when connecting to the API port e.g. when using `WireMock.configureFor("localhost", 8080, "/api/http");`

  Custom HTTP clients or a browser may continue to drop the `/__admin` section of the path so that API calls such as `http://localhost:8080/api/http/mappings` can be made

<a id="version-5-8-0"></a>
## 5.8.0 – 02 Dec 2019

### Features

- Improvements to gRPC mappings list user interface:
  - Added sorting to columns
  - Added a button to pause auto reload
  - Added a button to select which columns to display
  - Added two new columns which are hidden by default: id and name

### Fixes

- Pause gRPC mappings list auto reload when highlighting text so that it is possible to highlight and copy text without the auto reload clearing the highlight
- Allow spaces in gRPC mapping file name template

<a id="version-5-7-3"></a>
## 5.7.3 – 25 Nov 2019

### Features

- gRPC mapping file name templates when saving mappings via the UI can now be customized with the following properties:

  ```
  #
  # Template used for gRPC mapping file names
  #
  # Available properties:
  # {{ mapping.id }}
  # {{ mapping.package }}
  # {{ mapping.service }}
  # {{ mapping.method }}
  # {{ mapping.isSuccess }}
  # {{ mapping.status.name }}
  # {{ mapping.status.code }}
  #
  # Available commands:
  # {{ countGrpcMappings package=mapping.package service=mapping.service method=mapping.method success=true offset=1 format='%02d' }}
  trafficparrot.virtualservice.grpc.saved.mapping.file.name.template={{ mapping.package }}.{{ countGrpcMappings package=mapping.package offset=1 format='%02d' }}.{{ mapping.service }}-{{ mapping.method }}[{{ mapping.status.name }}]
  trafficparrot.virtualservice.grpc.saved.mapping.file.name.collision.suffix.template=-{{ mapping.id }}
                                          
  ```

- When editing a gRPC mapping in the UI you can now choose whether to keep the existing file name or generate a new one according to the template properties when the mapping is saved

<a id="version-5-6-0"></a>
## 5.6.0 – 11 Nov 2019

### Features

- gRPC unmatched requests now display the closest match in both the logs and error response description. For example:

  ```
  UNKNOWN: Traffic Parrot Virtual Service: No responses matched the given request. See the Traffic Parrot logs for more details.
                                                 Request was not matched
                                                 =======================

  -----------------------------------------------------------------------------------------------------------------------
  | Closest stub                                             | Request                                                  |
  -----------------------------------------------------------------------------------------------------------------------
                                                             |
  helloworldgreetersayhello-38d8ac56-38fe-4a57-89b3-5af8368  |
  874a5.json                                                 |
                                                             |
  ANY                                                        | ANY
  helloworld.Greeter/SayHello                                | helloworld.Greeter/SayHello
                                                             |
  Protocol: GRPC                                             | Protocol: GRPC
                                                             |
  {                                                          | {                                                   <<<<< Body does not match [equalToJson]
    "inputName" : "example"                                  |   "inputName" : "not matching"
  }                                                          | }
                                                             |
  -----------------------------------------------------------------------------------------------------------------------
  ```

- Upgraded WireMock to 2.25.0

- Upgraded Proto compiler to 3.10.1

### Fixes

- Fixed support for `reserved` fields in gRPC proto files
- Errors when compiling proto files are now reported in the logs
- Swagger/OpenAPI example dates are now considered when performing an import

### Changes

- New toggle `trafficparrot.virtualservice.grpc.check.mapping.schema.allow.missing.fields` that can be set to `true` to allow gRPC mapping files to have fields missing when compared to the proto schema. This is to allow for usages where there are fields that are intentionally omitted to pick up on the default.

<a id="version-5-5-3"></a>
## 5.5.3 – 25 Oct 2019

### Fixes

- Fixed support for gRPC error mappings in the new static analysis check
- Fixed support for gRPC dynamic response mappings in the new static analysis check
- Fixed support for gRPC mappings with repeated fields in the new static analysis check
- More consistent error reporting format for errors in dynamic responses, to make it clear which helper had a problem
- Always print log file in the Maven/Gradle plugin console if Traffic Parrot fails to start

### Features

- New state management examples added to [the examples](https://trafficparrot.com/documentation/5.65.x/downloads/trafficparrot-examples-5.65.x.zip) project

<a id="version-5-5-1"></a>
## 5.5.1 – 14 Oct 2019

### Features

- Traffic Parrot can now check that gRPC mapping files match proto schema on startup. You can enable this check to prevent startup if mapping files are out of date when compared to the proto schema.
  - The following property enables the feature: `trafficparrot.virtualservice.grpc.check.mapping.schema.on.startup=true`
  - Currently supports checking gRPC mapping `equalToJson` request matchers
  - Currently supports checking gRPC mapping response
  - This feature is currently in public beta and is subject to change
  - Please let us know your feedback [feedback@trafficparrot.com](mailto:feedback@trafficparrot.com) and help us improve this feature

### Changes

- Traffic Parrot now only requires a single port for the UI:

  - `trafficparrot.gui.http.port=8080`

  The following ports are no longer used by the UI:

  - `trafficparrot.virtualservice.http.management.port=8083`
  - `trafficparrot.virtualservice.jms.management.port=9093`
  - `trafficparrot.virtualservice.http.port=8081`

  Please note that these ports are still required by the Traffic Parrot backend.

<a id="version-5-4-5"></a>
## 5.4.5 – 07 Oct 2019

### Fixes

- gRPC mapping files will now be written with the [correct status code](https://github.com/grpc/grpc/blob/master/doc/statuscodes.md) of 0 to represent a successful response status. gRPC mapping files with status code 200 will continue to be interpreted as status code 0 to preserve backwards compatibility.

<a id="version-5-4-4"></a>
## 5.4.4 – 09 Sep 2019

### Changes

- The HTTPS client used for making outbound HTTPS connections now trusts all server certificates by default. This means that it is no longer necessary to specify a `javax.net.ssl.trustStore` when connecting to HTTPS servers that are not already trusted by the system during recording or proxying.

### Fixes

- Using the `javax.net.ssl.keyStore` system property will now completely override the HTTPS client key store used for making [outbound HTTPS connections](https://trafficparrot.com/documentation/5.65.x/user_guide.html#outbound-https-certificates) for mutual authentication scenarios during recording or proxying.

<a id="version-5-4-0"></a>
## 5.4.0 – 16 Aug 2019

### Features

- Added JMS REST API to count the number of requests made that match the given criteria using `POST /api/jms/requests/count` and reset the count using `DELETE /api/jms/requests`
- See the [OpenAPI documentation](https://trafficparrot.com/documentation/5.65.x/openapi/index.html) or import the [Postman workspace](https://documenter.getpostman.com/view/8460952/2sBYB1M8Eg?version=latest) for more information.

### Fixes

- Fixed usage of `{{ anyNumber }}` to match numbers within JSON string fields

<a id="version-5-3-2"></a>
## 5.3.2 – 07 Aug 2019

### Fixes

- Fixed a memory leak in the user interface

<a id="version-5-3-1"></a>
## 5.3.1 – 05 Aug 2019

### Features

- New operating system specific release with bundled JRE:
  - Any operating system with no bundled JRE: `trafficparrot-no-jre-5.3.1.zip`
  - 64-bit Linux with bundled JRE: `trafficparrot-linux-x64-jre-5.3.1.zip`
  - 64-bit Mac with bundled JRE: `trafficparrot-mac-x64-jre-5.3.1.zip`
  - 64-bit Windows with bundled JRE: `trafficparrot-windows-x64-jre-5.3.1.zip`
  - 32-bit Windows with bundled JRE: `trafficparrot-windows-x86-32-jre-5.3.1.zip`
- New state management REST API for global state:
  - Create or update state using `PUT /api/state/global/{name}`
  - Get state using `GET /api/state/global/{name}`
  - Reset all state using `DELETE /api/state`
  - See the [OpenAPI documentation](https://trafficparrot.com/documentation/5.65.x/openapi/index.html) or import the [Postman workspace](https://documenter.getpostman.com/view/8460952/2sBYB1M8Eg?version=latest) for more information on the API usage
  - `{{ manageState 'example' 'set' 1234 }}` to set a variable in a response template
  - `{{ manageState 'example' 'get' }}` to get a variable in a response template

<a id="version-5-2-0"></a>
## 5.2.0 – 19 Jul 2019

### Features

- WireMock 2.10.1 compatible REST API is now mounted on `/api/http/*` on the Traffic Parrot UI/API port (default 8080) for example `POST /api/http/requests/count` can be used to [count requests](http://wiremock.org/docs/api/#tag/Requests/paths/~1__admin~1requests~1count/post)
- Added gRPC REST API to count the number of requests made that match the given criteria using `POST /api/grpc/requests/count` and reset the count using `DELETE /api/grpc/requests`
- See the [OpenAPI documentation](https://trafficparrot.com/documentation/5.65.x/openapi/index.html) or import the [Postman workspace](https://documenter.getpostman.com/view/8460952/2sBYB1M8Eg?version=latest) for more information.

### Fixes

- Fix scenarios dropdown UI on Windows browsers

### Changes

- Rename "request body" to "request message payload" in the gRPC UI

<a id="version-5-1-1"></a>
## 5.1.1 – 15 Jul 2019

### Fixes

- Fixed support gRPC status details. We now support using both the status key and proto key header conventions.
- Fixed support for [well known](https://github.com/googleapis/common-protos-java/blob/master/proto-google-common-protos/src/main/proto/google/rpc/error_details.proto) gRPC error details types

### Changes

- Additional logging when a gRPC request fails to match any mappings
- Specify text representation of month in license logs to make it more clear when the start date is

<a id="version-5-1-0"></a>
## 5.1.0 – 08 Jul 2019

### Features

- gRPC improvements
  - Import gRPC proto files using the import button on the gRPC Add/Edit page
  - Convert OpenAPI files to gRPC proto files with [openapi2proto](https://github.com/nytimes/openapi2proto) using the import button on the gRPC Add/Edit page
  - Use the `trafficparrot.virtualservice.grpc.openapi2proto.plugin.location` property to configure the `openapi2proto` binary location, which can be either `AUTO_DETECT` (which searches the system environment path, go/bin directory and Traffic Parrot plugins directory) or a specific location
- Configure HTTP proxy mappings on the HTTP Add/Edit page to allow routing some calls to the virtual service and some calls to real services
- Added support for database queries in responses
  - New `{{ databaseQuery }}` helper
  - Configure JDBC connections in the `database-connections.json` file
  - Provide the JDBC driver JAR files for your database in the `lib/external` folder
- Added support for default value when using `{{ select }}` to look up values in CSV files
- Added support for the IBM®MQ Message ID as Correlation ID pattern

### Fixes

- When a property is missing from [`trafficparrot.properties`](https://trafficparrot.com/documentation/5.65.x/properties.html) we now report which key is missing in the logs
- PDF files can now be correctly recorded and replayed as HTTP `multipart/related` attachments

### Changes

- Removed equal to matcher from gRPC edit mapping form (equal to JSON always makes more sense to use than equal to)
- New toggle `trafficparrot.virtualservice.grpc.message.field.naming` to choose whether to define gRPC mappings using `CAMEL_CASE` field names or using the `ORIGINAL` field name case used in the proto files
- Binary (non plain text) HTTP responses are now recorded in `.bin` files

<a id="version-5-0-3"></a>
## 5.0.3 – 17 Jun 2019

### Fixes

- Added support for `google.protobuf.Any` fields when working with gRPC skeletons. For more details on how this field is serialized [see here](https://developers.google.com/protocol-buffers/docs/reference/java/com/google/protobuf/Any).

<a id="version-5-0-2"></a>
## 5.0.2 – 14 Jun 2019

### Fixes

- Correct links to latest documentation pages

<a id="version-5-0-1"></a>
## 5.0.1 – 12 Jun 2019

### Changes

- Added a new property `trafficparrot.openapi.import.mode` that acts as a toggle for the different ways Traffic Parrot supports for importing OpenAPI files. The default `MATCHING_RESPONSE_CODE` will use the response status in request matchers convention and `SKELETON` will template the mapping with the request and response structure.

<a id="version-5-0-0"></a>
## 5.0.0 – 10 Jun 2019

### Features

- New HTTP skeletons feature:
  - [OpenAPI specifications](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.2.md) are used to generate a list of [HTTP skeletons](https://trafficparrot.com/documentation/5.65.x/http.html#http-skeletons) that can be used to help design HTTP mappings in the Traffic Parrot user interface
  - Place OpenAPI specifications in the `openapi` configuration directory to populate the dropdown menu or use the upload button on the HTTP Add/Edit page next to the dropdown
  - This replaces the old `scenarios.js` dropdown, which has been removed (see changes section below for migration instructions)
- Maven plugin improvements:
  - New `trafficparrot:check-environment` goal to run in the `pre-clean` phase to check nothing is preventing a successful start of Traffic Parrot
  - Check that there is not an existing Traffic Parrot instance running
  - Check for locked files or directories that are unable to be cleaned on Windows (typically this is because a file is open in a text editor or command prompt)
  - Improved speed when `cacheDownload` is enabled by also caching the extracted zip file
  - Accept either `file:///` or `file://` syntax when specifying file URLs
  - Remember to upgrade your plugin version to 5.0.0

### Fixes

- The `randomInteger` and `randomDouble` helpers now return a number type instead of a string, so that they can be combined with other helpers that require a number. For example when combined with the `stringFormat` helper: `{{stringFormat '%02d:%02d' (randomInteger 0 59) (randomInteger 0 59)}}`

### Changes

- <a id="remove-scenarios"></a>
  The `scenarios.js` HTTP dropdown has been removed.
  - We recommend migrating to an OpenAPI specification file which can be used to produce a similar dropdown via the new HTTP skeletons functionality
  - Please email [support@trafficparrot.com](mailto:support@trafficparrot.com) with your `scenarios.js` file and we will translate it to an OpenAPI file for you
  - Removed unused property `trafficparrot.gui.scenarios.resource.name`
- Improved reporting of port clashes and how to change ports in [`trafficparrot.properties`](https://trafficparrot.com/documentation/5.65.x/properties.html)

<a id="version-4-7-2"></a>
## 4.7.2 – 13 May 2019

### Features

- gRPC improvements
  - Support specifying a status details object in exception responses
  - Support for matching by simple `key: value` request headers. The property `trafficparrot.virtualservice.grpc.exclude.request.headers.from.matching=content-type,user-agent,grpc-accept-encoding` can be used to choose which headers are considered for matching during replay.
  - New properties for performance tuning:
    - `trafficparrot.virtualservice.grpc.server.replay.proto.cache.populate.on.startup` will populate the proto cache when starting up
    - `trafficparrot.virtualservice.grpc.server.warmup.on.startup` will warm up the JVM to improve gRPC performance when starting up
    - `trafficparrot.virtualservice.mapping.cache.milliseconds` will cache mapping files for both gRPC and HTTP for the specified duration
    - `trafficparrot.virtualservice.mapping.cache.populate.on.startup` will populate the mapping file cache for both gRPC and HTTP when starting up
    - New constant `NUMBER_OF_PROCESSORS` can be used in the existing `trafficparrot.virtualservice.grpc.server.boss.threads` and `trafficparrot.virtualservice.grpc.server.worker.threads` properties
  - Use proto cache settings when loading gRPC skeletons
- Amazon SQS virtualization improvements:
  - Added support for the `PurgeQueue` command
  - Added a user interface to view outstanding messages and receipt handles

### Fixes

- gRPC performance improved by approximately 80%
- Trim extra empty lines from `jvm.args` file to avoid a start issue
- Amazon SQS `ReceiveMessage` now correctly only peeks a message rather than deleting it; deleting is done via the receipt handle to `DeleteMessage`

### Changes

- Amazon SQS virtualization changes:
  - Support is now enabled via the `trafficparrot.virtualservice.amazon.sqs.enabled=true` property instead of the `trafficparrot.http.responsetransformers` property
  - The virtual service is now hosted under the URL path `/aws/sqs` instead of directly under the root path
- Removed unused property `trafficparrot.virtualservice.inMemoryFileSystemBackedStubMappings`

<a id="version-4-6-1"></a>
## 4.6.1 – 07 May 2019

### Fixes

- Search `%PATH%` and `%JAVA_HOME%` on Windows as possible locations to find a Java installation. This is in addition to checking the standard registry entries that are populated when using the official Java installer. The standard registry entries take precedence over other locations.

<a id="version-4-6-0"></a>
## 4.6.0 – 19 Apr 2019

### Features

- Added support for mapping priority to distinguish between many matching mappings. The default priority is 5 and 1 is the highest.

<a id="version-4-5-4"></a>
## 4.5.4 – 16 Apr 2019

### Features

- New tray icon is displayed when running in a non-headless environment (e.g. on your laptop)
- New `jvm.args` file allows setting JVM arguments for the main Traffic Parrot process (e.g. to tune memory options)
- New configuration property `trafficparrot.virtualservice.http.no.mapping.found.code` to allow changing the no mappping found HTTP response code
- New `start.exe` and `stop.exe` launchers for Windows users
- Support JMS connections to an external Azure AMQP Service Bus broker in `jms-connections.json`
- Support Amazon SQS queue simulation and verification over the SQS HTTP REST APIs via the `com.trafficparrot.virtualservice.extensions.responsetransformer.AmazonSQSTransformer` which can be enabled via the `trafficparrot.http.responsetransformers` property
- Additional diagnostic information is printed when starting up and shutting down
- Maven and Gradle plugin improvements:
  - Allow specifying a [`trafficparrot.properties`](https://trafficparrot.com/documentation/5.65.x/properties.html) file location in the `propertiesFile` plugin property; this file is combined with the default properties file and any plugin overrides
  - Store a copy of the traffic files root in the build directory so that mappings imported dynamically e.g. from OpenAPI specifications do not pollute the source traffic files root
  - Print the startup and shutdown logs inline to make the build output easier to navigate
  - Remember to upgrade your plugin version to 4.5.4

### Fixes

- The default gRPC ports have changed to `trafficparrot.virtualservice.grpc.tls.port=5551` and `trafficparrot.virtualservice.grpc.non.tls.port=5552` so that they no longer overlap with the typical Windows ephemeral port range

### Changes

- When starting and stopping, the console output is appended to the `tp.out` file
- When running in the background, only file appenders in `trafficparrotserver.log4j.properties` are used; any console appenders are switched off
- When running in the foreground, both file and console appenders are used

<a id="version-4-4-2"></a>
## 4.4.2 – 24 Mar 2019

### Fixes

- New [`trafficparrot.properties`](https://trafficparrot.com/documentation/5.65.x/properties.html) properties to help with gRPC server performance tuning:
  - Configure how long to cache the proto files during replay using the `trafficparrot.virtualservice.grpc.server.replay.proto.cache.milliseconds` property.

    A value of `0` means do not cache at all.

  - Configure the number of boss and worker threads of the gRPC server using the `trafficparrot.virtualservice.grpc.server.boss.threads` and `trafficparrot.virtualservice.grpc.server.worker.threads` properties.

    The special value `DOUBLE_NUMBER_OF_PROCESSORS` means use double the number of processors.

<a id="version-4-4-1"></a>
## 4.4.1 – 08 Mar 2019

### Fixes

- Added [gRPC message skeleton](https://trafficparrot.com/documentation/5.65.x/grpc.html#edit-grpc-skeletons) support for:
  - Self referential types e.g. `google.protobuf.Struct`
  - Messages that use the `oneof` feature

<a id="version-4-4-0"></a>
## 4.4.0 – 25 Jan 2019

### Features

- Support adding a [delay to replay of JMS messages](https://trafficparrot.com/documentation/5.65.x/jms.html#edit-jms-delay) for ActiveMQ 5.4+ and IBM®MQ 8+
- Added a dropdown to generate a [gRPC message skeleton](https://trafficparrot.com/documentation/5.65.x/grpc.html#edit-grpc-skeletons) when adding a mapping without recording first
- Switch between [test scenarios](https://trafficparrot.com/documentation/5.65.x/user_guide.html#scenarios) to group together related mappings that form a virtual service

### Fixes

- Adding a new JMS mapping now correctly saves the properties

### Changes

- Always use `DeliveryMode.PERSISTENT` when sending JMS messages
- The Maven/Gradle plugin properties `printLogs` and `deleteAfterStop` are now also respected if Traffic Parrot fails to start up
- The `jms-mappings`, `ibm-mq-mappings` and `file-mappings` directories will be created on start up if they do not exist

<a id="version-4-3-3"></a>
## 4.3.3 – 15 Jan 2019

### Features

- Support for importing a ZIP file of HTTP mappings
- More verbose logging when there are port binding issues
- More verbose logging of start up configuration
- Pretty print JSON responses when importing Swagger/OpenAPI

### Fixes

- Take into account `basePath` when importing Swagger/OpenAPI

### Changes

- Consider only the name of the mapping file when setting the HTTP mapping name, not the entire path

<a id="version-4-2-10"></a>
## 4.2.10 – 23 Sep 2018

### Features

- Added support for [gRPC](https://trafficparrot.com/documentation/5.65.x/grpc.html) [StatusRuntimeException](https://grpc.io/grpc-java/javadoc/io/grpc/StatusRuntimeException.html)
- New page to download HTTP mappings
- New Gradle plugin for teams that prefer to use Gradle over Maven
- New [examples added](https://trafficparrot.com/documentation/5.65.x/downloads/trafficparrot-examples-5.65.x.zip) including Gradle examples
- New [Postman](https://www.getpostman.com) workspace [file](https://documenter.getpostman.com/view/8460952/2sBYB1M8Eg?version=latest) that you can [import](https://learning.getpostman.com/docs/postman/collections/data_formats/#data-dumps) to demonstrate some of the common Traffic Parrot management APIs
- Import mappings using Swagger/OpenAPI definitions using the Maven or Gradle plugin
- Better diagnostic logging if Traffic Parrot fails to start up due to e.g. an existing port already in use
- New `{{randomInteger min max}}` helper to generate random numbers in a range

### Fixes

- Fix various unclosed file handles
- Stopping Traffic Parrot now properly waits for gRPC proxy server shutdown
- Cache busting strategy implemented to cope with browsers that like to e.g. cache JavaScript files forever
- The `data` directory is now considered to be under the `trafficparrot.virtualservice.trafficFilesRootUrl`

<a id="version-4-1-6"></a>
## 4.1.6 – 07 Sep 2018

### Features

- New `matchesJson` matcher
- Import mappings using Swagger/OpenAPI definitions
- Record multiple HTTP URLs at the same time
- Enable redirect handling during HTTP recording using property `trafficparrot.virtualservice.enableRedirectHandling=true`
- Initial support for Java 9 and 10 in the start scripts

### Changes

- HTTP mappings are now sorted by last modified date in the UI

### Fixes

- Improve file extension detection for recorded HTTP body files
- Windows start script now correctly passes on system properties

<a id="version-4-0-7"></a>
## 4.0.7 – 09 Jul 2018

### Features

- Support for mocking and virtualizing [gRPC](https://trafficparrot.com/documentation/5.65.x/grpc.html) APIs and services
- Visual XML editor
- Extended support for SOAP - matching on request body SOAP values
- New `matchesXml` matcher
- HTTP(S) stateful scenarios available via the Web UI
- Signing SOAP messages
- Duplicate mapping button for HTTP

### Changes

- Traffic Parrot 4.x now requires Java 8 (Java 7 is supported by 3.13.x)
- gRPC support requires a 64bit JVM
- Virtual service runs in the same process at the Web UI
- These properties have been removed:
  - `trafficparrot.gui.virtualservice.classpath`
  - `trafficparrot.virtualservice.jvm.Xmx`
  - `trafficparrot.virtualservice.virtualServerLog4jPropertiesFilename`

### Fixes

- Configuration files now have Windows style line endings

<a id="version-3-13-0"></a>
## 3.13.0 – 23 Apr 2018

### Features

- Support native IBM®MQ ReplyToQMgr during recording
- Importing RAML v0.8 into HTTP mappings
- The Maven plugin has a new `cacheDownload` property which can be used to choose whether to cache the download in the `java.io.tmpdir` or not
- New [HTTP Management API](https://trafficparrot.com/documentation/5.65.x/openapi/index.html) that can be used to remotely start/stop the record/replay of IBM®MQ, JMS and File Message protocols

<a id="version-3-12-6"></a>
## 3.12.6 – 12 Feb 2018

### Features

- Recording and replaying native IBM®MQ RFH headers with message format `MQFMT_RF_HEADER_1` or `MQFMT_RF_HEADER_2`
- Support `MQFMT_NONE` MQ message format
- Recording and replaying native IBM®MQ responses using dynamic MQ model queues
- Support native IBM®MQ ReplyToQ during record and replay
- Support configuring the IBM®MQ [MQCSP authentication mode](https://www.ibm.com/support/knowledgecenter/en/SSFKSJ_8.0.0/com.ibm.mq.sec.doc/q118680_.htm)

### Fixes

- When you connect to a wrong IBM MQ channel or with wrong IBM MQ username/password you do not see it in the logs
- Spaces in the path to the Traffic Parrot installation directory are now supported

<a id="version-3-11-3"></a>
## 3.11.3 – 26 Jan 2018

### Features

- Recording and editing JMS Properties
- During File mocking, request files are now deleted after processing
- More user friendly (easier to read and follow) logs for JMS and File stubbing

### Fixes

- Windows start script start.cmd now works even if system32 directory is not on the %PATH%
- The dynamic HTTPS Proxy does not spin up so many threads any more and does not consume so much RAM
- Better error messages in failure scenarios when using several Handlebars
- More rigid stopping

### Changes

- Default selection on replay page is now based on the type of mappings that are present (e.g. Queue will be ticked if there are any Queue mappings)

<a id="version-3-10-0"></a>
## 3.10.0 – 10 Dec 2017

### Features

- Support for virtualizing services that [read and write files](https://trafficparrot.com/documentation/5.65.x/filemessage.html) (currently in beta)
- Support JMS byte messages (any bytes message, with [special support](https://trafficparrot.com/documentation/5.65.x/jms.html#edit-jms-java-objects) for `java.io.Serializable` objects)
- Upgraded WireMock to 2.10.1
- New [handlebar helpers](https://trafficparrot.com/documentation/5.65.x/dynamic.html#extension-functions) xPath, xPathList, jsonPath, jsonPathList, regex, equal, ifEven, size
- JMS is not in beta any more
- IBM®MQ native MQ support is not in alpha any more
- New [Maven plugin](https://trafficparrot.com/documentation/5.65.x/user_guide.html#maven-plugin) for replaying HTTP/JMS/MQ traffic during integration tests

### Fixes

- Fixed missing pages in community edition
- Fixed links on help page

### Changes

- Do not escape characters ``< > " ' ` &`` if they are produced by handlebars helpers
- Handlebars each helper now only iterates over iterable arguments
- Recorded cookies format has changed
- `com.trafficparrot.sdk.jms.Equal` moved to `com.trafficparrot.sdk.handlebars.Equal`
- `com.trafficparrot.sdk.jms.MissingHelper` moved to `com.trafficparrot.sdk.handlebars.MissingHelper`

<a id="version-3-9-1"></a>
## 3.9.1 – 11 Nov 2017

### Features

- Configuring [recording HTTP headers](https://trafficparrot.com/documentation/5.65.x/http.html#custom-headers) in the Web UI
- IBM®MQ [native MQ support](https://trafficparrot.com/documentation/5.65.x/ibmmq.html)
- Matching on [CorrelationId](https://trafficparrot.com/documentation/5.65.x/ibmmq.html#recording-mq-message-matching) while recording messages

<a id="earlier"></a>
## Earlier versions

Available on request.
