Skip to content

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 the server's --host, or all interfaces dual-stack (::) when none was given Address to bind the imposter to. Omitted, the imposter binds the server's --host, or with none listens dual-stack, as in Mountebank, falling back to 0.0.0.0 on a host without IPv6; an explicit 0.0.0.0 is IPv4 only

Optional Fields

Field Type Description
name string Human-readable identifier
stubs array Request/response mappings
defaultResponse object Response when no stub matches; also supplies the statusCode, headers, body and _mode that an is or inject response omits (headers is replaced whole; a proxy key in it is ignored, use defaultForward)
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 any When JavaScript-truthy, answer a CORS preflight (an OPTIONS with Origin, Access-Control-Request-Method and Access-Control-Request-Headers) by echoing those values as Access-Control-Allow-Origin/-Methods/-Headers, on the stub's or default response. Other requests get no CORS headers. Printed back in every view as configured
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 base URL an unmatched request is forwarded to (takes precedence over defaultResponse). Its path prefixes the request's; a trailing / on it is not doubled, and a query or fragment on it is ignored
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. Unlike Mountebank, a lookup in an imposter posted over the admin API reads its CSV file only under --scripts-dir, with data.csv above meaning <scripts-dir>/data.csv (see CSV Lookup).

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