Skip to content

Request Matching

Request matching determines which mock responds to an incoming HTTP request. mockd evaluates matchers in order and returns the first matching response.

Match specific HTTP methods:

{
"matcher": {
"method": "GET"
}
}

Supported methods: GET, POST, PUT, PATCH, DELETE, HEAD, OPTIONS

Exact path match:

{
"matcher": {
"path": "/api/users"
}
}

Capture dynamic path segments using curly braces:

{
"matcher": {
"path": "/api/users/{id}"
}
}

This matches:

  • /api/users/1
  • /api/users/abc
  • /api/users/123-456

Access captured values in responses:

{
"response": {
"body": {
"userId": "{{request.pathParam.id}}"
}
}
}
{
"matcher": {
"path": "/api/{resource}/{id}/comments/{commentId}"
}
}

Matches /api/posts/5/comments/12 with:

  • resource = "posts"
  • id = "5"
  • commentId = "12"

Match remaining path segments with .*:

{
"matcher": {
"path": "/api/files/{filepath:.*}"
}
}

Matches /api/files/documents/2024/report.pdf

Use full regex patterns for advanced path matching with pathPattern:

{
"matcher": {
"pathPattern": "^/api/users/\\d+$"
}
}

This matches /api/users/123 but not /api/users/abc.

Extract path segments into named variables:

{
"matcher": {
"pathPattern": "^/api/(?P<resource>\\w+)/(?P<id>\\d+)$"
}
}

Matches /api/users/456 with captures:

  • resource = "users"
  • id = "456"
PatternDescription
^/api/users/\\d+$Numeric ID only
^/api/(users|products)/\\d+$Multiple resource types
^/api/orders/[0-9a-f-]{36}$UUID format
^/api/items/[\\w-]+$Slugs with alphanumeric and dashes

Match requests with specific query parameters:

{
"matcher": {
"path": "/api/users",
"query": {
"page": "1",
"limit": "10"
}
}
}

Only specified parameters are required. Additional parameters are ignored:

{
"matcher": {
"path": "/api/search",
"query": {
"q": "test"
}
}
}

Matches both:

  • /api/search?q=test
  • /api/search?q=test&page=1&extra=value

Match requests with specific headers:

{
"matcher": {
"headers": {
"Content-Type": "application/json",
"X-API-Key": "secret123"
}
}
}

Use * wildcards for flexible header matching:

{
"matcher": {
"headers": {
"Authorization": "Bearer *",
"Accept": "application/*"
}
}
}

Supported patterns:

  • prefix* - matches values starting with prefix
  • *suffix - matches values ending with suffix
  • *contains* - matches values containing the substring

Header names are case-insensitive (per HTTP spec), but values are case-sensitive:

{
"matcher": {
"headers": {
"content-type": "application/json"
}
}
}

Matches Content-Type: application/json and CONTENT-TYPE: application/json

Match requests with specific body content.

Match exact JSON structure:

{
"matcher": {
"body": {
"username": "alice",
"action": "login"
}
}
}

Use bodyContains for partial matching:

{
"matcher": {
"bodyContains": {
"username": "alice"
}
}
}

Matches any request body that contains "username": "alice", ignoring other fields.

Match specific paths in JSON:

{
"matcher": {
"bodyMatch": {
"$.user.email": ".*@example\\.com",
"$.items[0].quantity": "[1-9][0-9]*"
}
}
}

Match raw body content:

{
"matcher": {
"bodyString": "<xml>.*</xml>"
}
}

Use full regex patterns for body matching with bodyPattern:

{
"matcher": {
"bodyPattern": "\"email\":\\s*\"[^\"]+@example\\.com\""
}
}

This matches any JSON body containing an email field ending with @example.com.

PatternDescription
"status":\\s*"(pending|approved)"Match status values
[0-9a-f]{8}-[0-9a-f]{4}-Contains UUID
(?i)errorContains “error” (case-insensitive)
(?s)start.*endMultiline matching

Match specific JSON fields using JSONPath expressions:

{
"matcher": {
"bodyJsonPath": {
"$.user.name": "John",
"$.items[0].quantity": 5,
"$.status": "active"
}
}
}

This matches requests where:

  • $.user.name equals “John”
  • $.items[0].quantity equals 5
  • $.status equals “active”
ExpressionDescription
$.fieldRoot-level field
$.user.nameNested field
$.items[0]Array index
$.items[*].idAny array element
$..nameRecursive descent

Check if a field exists (or doesn’t exist):

{
"matcher": {
"bodyJsonPath": {
"$.token": {"exists": true},
"$.deleted": {"exists": false}
}
}
}

JSONPath matching supports:

  • Strings: "$.name": "John"
  • Numbers: "$.age": 30
  • Booleans: "$.active": true
  • Null: "$.deleted": null

Combine multiple matchers for precise matching:

{
"matcher": {
"method": "POST",
"path": "/api/users/{id}/comments",
"headers": {
"Content-Type": "application/json",
"Authorization": "Bearer .*"
},
"query": {
"notify": "true"
},
"bodyContains": {
"text": ".*"
}
}
}

All conditions must match for the mock to respond.

When multiple mocks could match, mockd uses this priority:

More specific matches win:

// This wins for /api/users/1
{ "path": "/api/users/1" }
// This wins for /api/users/2, /api/users/abc, etc.
{ "path": "/api/users/{id}" }

Mocks with more conditions win:

// Less specific (matches any GET /api/users)
{ "method": "GET", "path": "/api/users" }
// More specific (matches only with Authorization header)
{ "method": "GET", "path": "/api/users", "headers": { "Authorization": ".*" } }

When priority is equal, earlier mocks in the config file win.

{
"matcher": {
"path": "/api/.*",
"headers": {
"X-API-Key": "valid-key-123"
}
},
"response": { "statusCode": 200 }
}
[
{
"matcher": {
"path": "/api/data",
"headers": { "Accept": "application/xml" }
},
"response": {
"headers": { "Content-Type": "application/xml" },
"body": "<data>...</data>"
}
},
{
"matcher": {
"path": "/api/data",
"headers": { "Accept": "application/json" }
},
"response": {
"headers": { "Content-Type": "application/json" },
"body": { "data": "..." }
}
}
]