Reaction Examples AI-generated
Every example below is a real, currently-running reaction pulled from the public Examples environment on demo.mockmotor.com (Services list, no login needed) - not invented for this page. Click through and open any of them yourself to see the full reaction editor around these fields.
Basic use: the same mock in JSON and XML
The REST+JSON Find a Post Office and REST+XML Find a Post Office services both mock the identical scenario - look up a post office's details by ID - one in JSON/JavaScript, the other in XML/XQuery. Both match GET rs/postoffice/{urlOfficeId}/detail, pull the ID out of the path via the {urlOfficeId} placeholder, normalize it through a Script Library function (the request sends 102978, the account is stored as 0000102978), and use it as the Account Selection script - see Variables for the path-parameter mechanics and Script Library & JWT for shared functions.
JSON / JavaScript version
Account Selection:
account.officeId==formatOfficeId(rest.parameters.urlOfficeId)
Response Payload - builds the hours-list array by iterating the account's multi-valued workHours property, then assigns the whole result to output:
hoursList = [];
for(var i=0; i<account.workHours.length; i++ ) {
hoursList.push({"day":i+1,"hours":account.workHours[i]});
}
output =
{
"post-office-detail": {
"address": {
"city": account.city,
"latitude": account.latitude,
"longitude": account.longitude,
"postal-code": account.postalCode,
"province": account.province,
"office-address": account.officeAddress
},
"location": "BUCKINGHAM PO",
"name": "DÉPANNEUR MAUZEROLL",
"office-id": account.officeId,
"bilingual-designation": true,
"hours-list": hoursList
}
}
Status 200, Content-Type application/json, Delay 300ms (±10%, see Reactions).
XML / XQuery version
Account Selection - the same idea, but calling the Script Library function with its local: prefix (see Script Library & JWT) against the full-form $rest path (this reaction predates Simplified Variables, so it spells out $rest//*:parameter[@name='urlOfficeId']/text() rather than the shorter $urlOfficeId - either works):
account.officeId==local:formatOfficeId($rest//*:parameter[@name='urlOfficeId']/text())
Response Payload - a FLWOR for...let...return loop over the same multi-valued workHours property (stored as "09:00-17:00"-style strings, split with tokenize()), with a fallback branch for an account that has no workHours at all:
<post-office-detail>
<address>
<city>{$account/*:city/text()}</city>
<latitude>{$account/*:latitude/text()}</latitude>
<longitude>{$account/*:longitude/text()}</longitude>
<postal-code>{$account/*:postalCode/text()}</postal-code>
<province>{$account/*:province/text()}</province>
<office-address>{$account/*:officeAddress/text()}</office-address>
</address>
<location>BUCKINGHAM PO</location>
<name>DÉPANNEUR MAUZEROLL</name>
<office-id>{$account//*:officeId/text()}</office-id>
<bilingual-designation>true</bilingual-designation>
{
for $wh at $day in $account/*:workHours/text()
let $hours := tokenize($wh,'-')
return
<hours-list>
<day>{$day}</day>
<time>{$hours[1]}</time>
<time>{$hours[2]}</time>
</hours-list>
}
{
if( not($account/*:workHours) ) then
<hours-list>
<day>7</day>
<time>09:00</time>
<time>17:00</time>
</hours-list>
else ()
}
</post-office-detail>
Status 200, Delay 30ms.
Script matching
The Retries service exists purely to test how a client handles a flaky backend, using nothing but Match Options scripts.
Simplest form: a flat failure rate
Match script, no account involved at all:
mockmeta.random < 0.25
Status 500 - roughly one in four calls fails, using the fresh per-request random value from mockmeta (see Variables). A second reaction with an empty match (matches everything else) handles the normal case.
A time-boxed outage cycle, driven by account state
A more elaborate version of the same idea uses one mock account's own properties as a state machine, checked directly in each reaction's match script (referencing account. in a match script is enough to trigger that reaction's own Account Selection first):
| Reaction | Match script | What it does |
|---|---|---|
| Down Time | mockmeta.epochMs > account.downTime && mockmeta.epochMs < account.upTime | Status 500 - inside the outage window. |
| Init Cycle | mockmeta.epochMs > account.upTime | Status 503; resets the cycle by setting account.downTime = mockmeta.epochMs + 300000 and account.upTime = mockmeta.epochMs + 360000 (a new 5-minute-out, 6-minute-out window). |
| Regular GET | (none) | Normal response, once neither of the above matched. |
All three select the same fixed account (account.ID=="1d1dc03c9b33") and are ordered so the most specific state check runs first - the same "first match wins, in list order" rule as any other service (see Reactions).
Matching on header presence (XQuery)
The Basic HTTP Auth service's whole job is one match script:
not($http//*:header[@name='Authorization'])
Status 401 with a scripted WWW-Authenticate: Basic realm="accounting" response header (see CORS & Auth Basics) when the header is missing; a second, unconditional reaction answers requests that do carry one.
Account selection and updates: a full stateful lifecycle
The Rackspace Queue (Stateful, JSON) service mocks a message queue - post a message, list messages, delete one - entirely through mock accounts, one account per message. It's a compact tour of Account Selection, If Account(s) Not Found: Create, and Update Accounts together (see Mock Accounts and Reactions).
Post message (create)
Account Selection deliberately can't match an existing account - a fresh random ID guarantees a miss every time - so Create always fires:
account.messageId==mockmeta.randomUUID
Update Accounts then stamps the newly-created account with everything the message needs:
| Property | Set to |
|---|---|
body | JSON.stringify(input[0].body) |
messageCreated | Math.floor(mockmeta.epochMs / 1000) |
messageStatus | "OK" |
messageTtl | input[0].ttl? input[0].ttl:60 (default 60s if the request didn't specify one) |
projectId / queueId | projectId / queueName - the Simplified-form path parameters (see Variables) |
The payload returns the generated ID back to the caller: {"partial":false,"resources":["/v1/queues/"+queueName+"/messages/"+mockmeta.randomUUID]}.
Get messages (multi-condition selection)
Two conditions ANDed together, with a bare Ignore instead of Fail when nothing's queued yet:
account.projectId==projectId && account.queueId==queueName
Delete message (conditional status, single-property update)
A soft delete - the account isn't removed, just marked:
account.messageId==messageId
Status is scripted against the very account that selection just found, distinguishing "already gone" from "found and now removed":
account && account.messageStatus!="DELETED"?200:204
Update Accounts sets messageStatus to "DELETED".
Bulk conditional delete (housekeeping)
Not part of the real Rackspace API - a maintenance reaction for MockMotor's own load tests, to clean up messages a test run forgot to delete. Account Selection picks every message for one project (account.projectId=="MyProject", Ignore if none), and Delete Accounts is itself a script evaluated per selected account, deleting only the ones it returns true for:
var now = Math.floor(mockmeta.epochMs / 1000); var old = account.messageCreated? parseInt(account.messageCreated):now; output = now - old > 30;
This is the same Update/Delete Mock Account(s) section described in Reactions - deleting is just a script that decides, per account, whether it goes.