Mountebank Configuration Format
The Mountebank JSON format is the recommended way to configure Rift for service virtualization and API mocking.
Configuration File Structure
{
"imposters": [
{
"port": 4545,
"protocol": "http",
"name": "Service Name",
"stubs": [...],
"defaultResponse": {...}
}
]
}
Imposter Configuration
Core Fields
No field is strictly required.
| Field | Type | Default | Description |
|---|---|---|---|
port | number | auto-assigned | Port to listen on. Omitted or 0 means “pick a free port”; imposters that name a port are created first. A --datadir file must name one |
protocol | string | http | http or https; anything else (tcp, smtp) is rejected |
host | string | 0.0.0.0 | Address to bind the imposter to |
Optional Fields
| Field | Type | Description |
|---|---|---|
name | string | Human-readable identifier |
stubs | array | Request/response mappings |
defaultResponse | object | Response when no stub matches |
recordRequests | boolean | Store requests for verification |
recordMatches | boolean | Accepted, no effect: per-stub matches are not recorded. true is reported as config_key_ignored in _rift.warnings and by rift-lint W017; use recordRequests |
allowCORS | boolean | Add CORS headers to responses |
key | string | PEM private key (HTTPS) |
cert | string | PEM certificate (HTTPS) |
mutualAuth | boolean | Request and require a client certificate (https only) |
rejectUnauthorized | boolean | Validate the client certificate against ca; requires ca |
ca | string or array | PEM trust anchor(s) client certificates must chain to |
defaultForward | string | Rift extension. Upstream URL an unmatched request is forwarded to (takes precedence over defaultResponse) |
strictBehaviors | boolean | Rift extension. Turn a failing behavior into a 500 — see Strict Behaviors |
enabled | boolean | Whether the imposter serves traffic (default true); toggled by POST /imposters/{port}/disable and /enable |
A request that matches no stub gets the defaultResponse when there is one, and otherwise a 200 with an empty body — as in Mountebank, never a 404.
TLS fields (key, cert, mutualAuth, rejectUnauthorized, ca) are covered in TLS/HTTPS.
Rift-Specific Metadata Fields
| Field | Type | Description |
|---|---|---|
serviceName | string | Service name for documentation (alias: service_name) |
serviceInfo | object | Arbitrary metadata (JSON object) |
_rift | object | Rift extensions (flow state, faults, scripting) |
Example with metadata:
{
"port": 4545,
"protocol": "http",
"name": "User Service",
"serviceName": "user-api",
"serviceInfo": {
"team": "platform",
"version": "1.2.3",
"documentation": "https://docs.example.com/user-api"
},
"stubs": [...]
}
Stub Configuration
{
"stubs": [
{
"predicates": [...],
"responses": [...]
}
]
}
Predicates Array
Each predicate object can contain:
{
"predicates": [
{
"equals": { "method": "GET", "path": "/api" },
"caseSensitive": false,
"except": ""
}
]
}
Responses Array
{
"responses": [
{
"is": {
"statusCode": 200,
"headers": {},
"body": ""
},
"_behaviors": {}
}
]
}
Predicate Types Reference
equals
{ "equals": { "method": "GET", "path": "/users", "query": { "id": "1" } } }
deepEquals
{ "deepEquals": { "body": { "exact": "match" } } }
contains
{ "contains": { "body": "substring" } }
startsWith
{ "startsWith": { "path": "/api" } }
endsWith
{ "endsWith": { "path": ".json" } }
matches
{ "matches": { "path": "/users/\\d+" } }
exists
{ "exists": { "headers": { "Authorization": true } } }
jsonpath
jsonpath is a parameter of another predicate, not a predicate of its own: the selector narrows the body, and the operator beside it tests what was selected.
{ "equals": { "body": 1 }, "jsonpath": { "selector": "$.user.id" } }
xpath
{ "equals": { "body": "1" }, "xpath": { "selector": "//user/id" } }
Logical Operators
{ "and": [ { "equals": {...} }, { "contains": {...} } ] }
{ "or": [ { "equals": {...} }, { "equals": {...} } ] }
{ "not": { "equals": {...} } }
Response Types Reference
is (Static)
{
"is": {
"statusCode": 200,
"headers": { "Content-Type": "application/json" },
"body": { "key": "value" }
}
}
proxy
{
"proxy": {
"to": "https://api.example.com",
"mode": "proxyOnce",
"predicateGenerators": [{ "matches": { "path": true } }]
}
}
inject
{
"inject": "function(request, state, logger) { return { statusCode: 200, body: 'Hello' }; }"
}
Behaviors Reference
wait
{ "_behaviors": { "wait": 1000 } }
decorate
{ "_behaviors": { "decorate": "function(request, response) { return response; }" } }
copy
from is "path", "method" or "body", or {"query": "<name>"} / {"headers": "<name>"}. A regex selector yields its first capture group (or the whole match when it has none); jsonpath and xpath selectors apply to the value from picked.
{
"_behaviors": {
"copy": {
"from": "path",
"into": "${id}",
"using": { "method": "regex", "selector": "/users/(\\d+)" }
}
}
}
lookup
{
"_behaviors": {
"lookup": {
"key": { "from": { "query": "id" }, "using": { "method": "regex", "selector": ".*" } },
"fromDataSource": { "csv": { "path": "data.csv", "keyColumn": "id" } },
"into": "${row}"
}
}
}
copy and lookup each accept a single object or an array of them. See Behaviors for shellTransform, repeat and the error semantics.
Behaviors run on is, inject and proxy responses, and repeat on every response. A block setting anything else on a fault or _rift-only response is kept and returned, and reported as config_key_ignored in _rift.warnings and by rift-lint W017 — see Behaviors.
HTTPS Configuration
{
"port": 4545,
"protocol": "https",
"key": "-----BEGIN RSA PRIVATE KEY-----\nMIIE...\n-----END RSA PRIVATE KEY-----",
"cert": "-----BEGIN CERTIFICATE-----\nMIID...\n-----END CERTIFICATE-----",
"mutualAuth": false,
"stubs": [...]
}
Using File Paths
{
"port": 4545,
"protocol": "https",
"key": "<%- stringify('/path/to/key.pem') %>",
"cert": "<%- stringify('/path/to/cert.pem') %>",
"stubs": [...]
}
Complete Example
{
"imposters": [
{
"port": 4545,
"protocol": "http",
"name": "User Service",
"recordRequests": true,
"defaultResponse": {
"statusCode": 404,
"body": { "error": "Not Found" }
},
"stubs": [
{
"predicates": [
{ "equals": { "method": "GET", "path": "/health" } }
],
"responses": [
{ "is": { "statusCode": 200, "body": "OK" } }
]
},
{
"predicates": [
{
"and": [
{ "equals": { "method": "GET" } },
{ "matches": { "path": "/users/\\d+" } }
]
}
],
"responses": [
{
"is": {
"statusCode": 200,
"headers": { "Content-Type": "application/json" },
"body": { "id": "${id}", "name": "User" }
},
"_behaviors": {
"copy": {
"from": "path",
"into": "${id}",
"using": { "method": "regex", "selector": "/users/(\\d+)" }
}
}
}
]
},
{
"predicates": [
{ "equals": { "method": "POST", "path": "/users" } },
{ "exists": { "body": true }, "jsonpath": { "selector": "$.name" } }
],
"responses": [
{
"is": {
"statusCode": 201,
"body": { "id": 999, "message": "Created" }
},
"_behaviors": { "wait": 100 }
}
]
}
]
}
]
}
Loading Configuration
From File at Startup
# Docker
docker run -p 2525:2525 -p 4545:4545 -v $(pwd)/imposters.json:/imposters.json \
zainalpour/rift-proxy:latest --configfile /imposters.json
# Binary
rift --configfile imposters.json
The file may also be YAML (a sequence of imposters) or a single imposter object, and may use the Mountebank EJS tags — see Document shapes and formats.
Via REST API
# Create single imposter
curl -X POST http://localhost:2525/imposters \
-H "Content-Type: application/json" \
-d @imposter.json
# Replace the whole set (imposters absent from the payload are deleted)
curl -X PUT http://localhost:2525/imposters \
-H "Content-Type: application/json" \
-d @imposters.json