Request Matching#

An endpoint matches a request when all specified conditions are met:

FieldBehavior
methodMust equal the request method. Empty matches any method.
path / path_glob / path_regexExactly one path matcher — exact, glob, or regex.
headersAll listed headers must be present with the exact values.
queryAll listed query params must be present with the exact values.
payload / payload_containsThe request body must match exactly, or contain the JSON subset.

Request matching is AND logic: every condition you specify must hold. Conditions you don’t specify are ignored.

Defaults and Special Values#

ValueMeaning
method omittedMatches any HTTP method.
headers omittedNo header constraints — any headers match.
query omittedNo query constraints — any query matches.
payload omittedNo body constraint — any body (including empty) matches.

When Several Stubs Match#

A request can match more than one stub. Simuhook picks the most specific match, deterministically:

  1. Path class — exact path beats path_glob, which beats path_regex.
  2. Glob weight — among globs, fewer wildcards win: /users/*/orders beats /users/**.
  3. Load order — identical specificity falls back to the order stubs were loaded (stable across reloads).

A stub that fails any condition is never a candidate — constraints are evaluated before specificity comparison.

Worked Example#

Consider these two stubs:

# stub A — matches any GET ending in /users (exact)
id: users-exact
method: GET
path: /users
response:
  status_code: 200
  body: '{"matched":"exact"}'
# stub B — matches any GET under /users (glob)
id: users-glob
method: GET
path_glob: /users/**
response:
  status_code: 200
  body: '{"matched":"glob"}'
RequestResultWhy
GET /usersA ({"matched":"exact"})Both match on path, but exact path outranks path_glob.
GET /users/123B ({"matched":"glob"})Stub A’s exact path doesn’t match; only the glob does.
POST /users/123404Stub B requires method: GET, so it’s not a candidate.

No Match#

If no endpoint matches, the server responds:

{
  "error": "no matching endpoint"
}

with status 404 and Content-Type: application/json. Unmatched requests are still logged — to logs/_unmatched.log — with matched: false.