Imposters
An imposter is a mock server that listens on a specific port and responds to requests based on configured stubs.
Creating an Imposter
Basic HTTP Imposter
curl -X POST http://localhost:2525/imposters \
-H "Content-Type: application/json" \
-d '{
"port": 4545,
"protocol": "http",
"name": "My Service Mock",
"stubs": [{
"responses": [{
"is": { "statusCode": 200, "body": "Hello" }
}]
}]
}'
HTTPS Imposter
curl -X POST http://localhost:2525/imposters \
-H "Content-Type: application/json" \
-d '{
"port": 4546,
"protocol": "https",
"name": "Secure Service Mock",
"key": "-----BEGIN RSA PRIVATE KEY-----\n...\n-----END RSA PRIVATE KEY-----",
"cert": "-----BEGIN CERTIFICATE-----\n...\n-----END CERTIFICATE-----",
"stubs": [{
"responses": [{
"is": { "statusCode": 200, "body": "Secure Hello" }
}]
}]
}'
Imposter Configuration
| Field | Type | Required | Description |
|---|---|---|---|
port | number | No | Port to listen on (auto-assigned if omitted) |
protocol | string | No | http or https (default: http) |
name | string | No | Human-readable name |
stubs | array | No | Request/response mappings |
defaultResponse | object | No | Response when no stub matches |
recordRequests | boolean | No | Store requests for verification |
allowCORS | boolean | No | Enable CORS headers and handle preflight requests |
service_name | string | No | Service identifier for documentation |
service_info | object | No | Additional service metadata |
key | string | HTTPS only | PEM-encoded private key |
cert | string | HTTPS only | PEM-encoded certificate |
mutualAuth | boolean | No | Require client certificate |
Auto-Port Assignment
If you omit the port field, Rift will automatically assign an available port from the dynamic range (49152-65535):
curl -X POST http://localhost:2525/imposters \
-H "Content-Type: application/json" \
-d '{
"protocol": "http",
"stubs": [{
"responses": [{ "is": { "statusCode": 200 } }]
}]
}'
# Response includes the assigned port:
{
"port": 49152,
"protocol": "http",
...
}
Stubs
Each stub contains predicates (matching rules) and responses:
{
"stubs": [
{
"predicates": [
{ "equals": { "method": "GET", "path": "/api/users" } }
],
"responses": [
{ "is": { "statusCode": 200, "body": "[]" } }
]
}
]
}
Stub Configuration
| Field | Type | Required | Description |
|---|---|---|---|
id | string | No | Unique identifier (Rift extension) |
predicates | array | No | Conditions to match requests |
responses | array | Yes | Responses to return |
scenarioName | string | No | Identifier for test scenarios |
The id field is a Rift extension that allows you to identify stubs by name rather than index:
{
"stubs": [{
"id": "get-user-success",
"predicates": [{ "equals": { "path": "/users/123" } }],
"responses": [{ "is": { "statusCode": 200, "body": "{\"id\": 123}" } }]
}]
}
The scenarioName field is useful for organizing stubs into logical groups for testing:
{
"stubs": [{
"scenarioName": "UserService-GetUser-Success",
"predicates": [{ "equals": { "path": "/users/123" } }],
"responses": [{ "is": { "statusCode": 200, "body": "{\"id\": 123}" } }]
}]
}
Multiple Responses (Round-Robin)
When a stub has multiple responses, they cycle through:
{
"stubs": [{
"predicates": [{ "equals": { "path": "/flip" } }],
"responses": [
{ "is": { "body": "heads" } },
{ "is": { "body": "tails" } }
]
}]
}
First request returns “heads”, second returns “tails”, third returns “heads”, etc.
Default Response
Configure a fallback response when no stub matches:
{
"port": 4545,
"protocol": "http",
"defaultResponse": {
"statusCode": 404,
"headers": { "Content-Type": "application/json" },
"body": { "error": "Not Found" }
},
"stubs": [...]
}
Recording Requests
Enable request recording for verification in tests:
{
"port": 4545,
"protocol": "http",
"recordRequests": true,
"stubs": [...]
}
Retrieve recorded requests:
curl http://localhost:2525/imposters/4545
# Response includes:
{
"requests": [
{
"method": "GET",
"path": "/api/users",
"headers": {...},
"body": "",
"timestamp": "2024-01-15T10:30:00.000Z"
}
]
}
Managing Imposters
List All Imposters
curl http://localhost:2525/imposters
# Response:
{
"imposters": [
{ "port": 4545, "protocol": "http", "name": "User Service" },
{ "port": 4546, "protocol": "https", "name": "Payment Service" }
]
}
Get Imposter Details
curl http://localhost:2525/imposters/4545
# Response includes full configuration and recorded requests
Delete Single Imposter
curl -X DELETE http://localhost:2525/imposters/4545
Delete All Imposters
curl -X DELETE http://localhost:2525/imposters
Loading from Configuration File
JSON Format
Create imposters.json:
{
"imposters": [
{
"port": 4545,
"protocol": "http",
"stubs": [...]
},
{
"port": 4546,
"protocol": "http",
"stubs": [...]
}
]
}
Load on startup:
docker run -v $(pwd)/imposters.json:/imposters.json \
zainalpour/rift-proxy:latest --configfile /imposters.json
EJS Templates
Use EJS for dynamic configuration:
{
"imposters": [
{
"port": "<%= port || 4545 %>",
"protocol": "http",
"stubs": [...]
}
]
}
Stub Matching Behavior
First-Match-Wins
Stubs are evaluated in order. The first stub whose predicates match is used:
{
"stubs": [
{
"predicates": [{ "startsWith": { "path": "/api" } }],
"responses": [{ "is": { "body": "general" } }]
},
{
"predicates": [{ "equals": { "path": "/api/users" } }],
"responses": [{ "is": { "body": "specific" } }]
}
]
}
In this example, /api/users returns “general” because the first stub matches. To get “specific”, swap the stub order.
Empty Predicates (Catch-All)
A stub with empty predicates matches all requests:
{
"stubs": [
{ "predicates": [], "responses": [{ "is": { "body": "catch all" } }] }
]
}
Warning: A catch-all stub shadows all subsequent stubs. Place catch-all stubs last.
Index-Based Operations
Stub indexes shift when stubs are added or removed:
Before: [Stub0, Stub1, Stub2] (indexes 0, 1, 2)
Delete index 0:
After: [Stub1, Stub2] (indexes 0, 1)
Rift Stub Analysis (Rift Extension)
Rift provides optional warnings for common stub configuration issues. These warnings appear in the API response under _rift.warnings:
curl http://localhost:2525/imposters/4545
# Response includes:
{
"port": 4545,
"stubs": [...],
"_rift": {
"warnings": [
{
"warningType": "catch_all_not_last",
"message": "Catch-all stub at index 0 will shadow 2 stub(s) after it",
"stubIndex": 0
}
]
}
}
Warning Types
| Type | Description |
|---|---|
duplicate_id | Multiple stubs have the same ID |
exact_duplicate | Stub predicates are identical to another stub |
potentially_shadowed | Stub may be unreachable due to earlier stub |
catch_all | Stub with empty predicates matches all requests |
catch_all_not_last | Catch-all stub is not at the end of the list |
Note: Mountebank does NOT provide overlap detection. These warnings are a Rift extension.
Best Practices
- Use meaningful names - Makes debugging easier
- Order stubs specifically - More specific predicates first
- Enable recording in tests - Verify expected requests
- Use default responses - Clear error messages for unmatched requests
- Separate imposters by service - One imposter per external dependency
- Place catch-all stubs last - Avoid accidentally shadowing specific stubs
- Use stub IDs (Rift) - Easier to track and manage stubs by name