Request
With request matching you have to describe all the conditions the incoming http requests have to match in order for your
stub response to be served. Most of the time, you will opt in for a conservative approach where you will have exhaustive
and strict conditions. That's when you want to assess the http caller behaves the right way. Other times you do not care
about request matching at all e.g. you use stubr to benchmark a reverse proxy: in that
case request { "method": "ANY" }
is enough. Just write the request matching you need.
Method
Expects the request method. Use ANY
when you do not care which method it will be.
Available verbs are GET
, HEAD
, POST
, PUT
, DELETE
, CONNECT
, OPTIONS
, TRACE
, PATCH
Note: method
is optional and defaults to ANY
{
"request": {
"method": "GET"
}
}
URI
To match request's URI (and maybe its query parameters). Only one of the following matcher is allowed. If more than one
are present, it does not fail but chooses one matcher according to the descending
priority url
> urlPath
> urlPattern
> urlPathPattern
{
"request": {
"url": "/api/uri?age=young",
"urlPath": "/api/exact-uri",
"urlPattern": "/api/regex-uri/([a-z]{4})\\?and=([a-z]{4})",
"urlPathPattern": "/api/regex-uri/([a-z]{4})"
}
}
url
: Matches by equality the URI and query parameters.urlPath
: Matches by equality just the URI without query parameters.urlPattern
: Matches URI and query parameters. Path segments and query parameters value can contain regexes.urlPathPattern
: Matches just the URI without query parameters. Path segments can contain regexes.
Query parameters
Allows matching query parameters. Prefer this instead of URI matching just because it is clearer. Multivalued query parameters are not supported yet.
{
"request": {
"queryParameters": {
"firstname": { "equalTo": "beltram" },
"lastname": { "equalTo": "maldant", "caseInsensitive": true },
"age": { "absent": true },
"birthdate": { "absent": false },
"city": { "contains": "at" },
"title": { "matches": "([A-Za-z]+)" },
"job": { "doesNotMatch": "([A-Za-z]+)" }
}
}
}
equalTo
by equality matcher. Can be a string, a boolean, a number, null etc... Can be turned case-insensitive withcaseInsensitive
.absent
specified query parameter key must be absent/present.contains
value must contain the supplied string in a case-insensitive waymatches
/doesNotMatch
value must match the supplied regex (or not)
Headers
Header matcher are exactly the same as query parameter matcher above.
{
"request": {
"headers": {
"content-type": { "equalTo": "application/json" }
}
}
}
Authorization
Those matcher are exclusive to stubr and not available in Wiremock. They allow crafting more relaxed request matchers when it comes to authorization. You could for example have stubs specialized for a specific user (we sometimes persona).
You can have matchers for Basic authentication (RFC 7617). For example,
for matching Authorization: Basic am9obi5kb2U6Y2hhbmdlbWU=
you would have:
{
"request": {
"basicAuth": {
"username": "john.doe",
"password": "changeme"
}
}
}
You can also match a JWT token in the Authorization
header as
per RFC 7519
{
"request": {
"jwtAuth": {
"equalTo": "eyJhbGciOiJSUzI1NiJ9.e30.MBkQ...",
"alg": {
"equalTo": "RS256",
"oneOf": [ "RS256", "HS256" ]
},
"payloadPatterns": [
{ "equalToJson": { "iss": "john.doe" } },
{ "equalToJson": { "exp": 1300819380 } },
{
"expression": "$.address",
"equalToJson": { "street": "rue de Rivoli", "city": "Paris" }
}
]
}
}
}
equalTo
by equality matcher. Equivalent to"headers":{"authorization":{"equalTo": "..."}}
. If you have this matcher, all the other ones will be ignoredalg.equalTo
by equality matcher. JWT algorithm has to be exactly thisalg.oneOf
JWT algorithm has to be one of the supplied values. Here are all the supported JWT algorithms:HS256
,HS384
,HS512
,ES256
,ES384
,RS256
,RS384
,RS512
,PS256
,PS384
,PS512
,EdDSA
payloadPatterns
for matching the JWT body. Exactly the same matcher as body ones.
Body
{
"request": {
"bodyPatterns": [
{ "equalToJson": { "name": "bob" } },
{
"equalToJson": {"names": ["alice", "bob"]},
"ignoreExtraElements": true,
"ignoreArrayOrder": true
},
{ "matchesJsonPath": "$.name" },
{ "matchesJsonPath": "$.consoles[?(@.name == 'xbox')]" },
{ "matchesJsonPath": "$.consoles[?(@.price > 200)]" },
{ "expression": "$.name", "contains": "at" },
{ "expression": "$.user", "equalToJson": { "name": "bob" } },
{ "expression": "$.age", "equalToJson": 42 },
{ "binaryEqualTo": "AQID" }
]
}
}
equalToJson
strict equality matcher. Request body has to be exactly equal to this. If it is not used withexpression
, all other matchers will be ignored. However, it can be relaxed with:ignoreExtraElements
to ignore json fields in the http request not present in the matcherignoreArrayOrder
to match json arrays regardless the order of their items
expression
a JSONPath matcher used to narrow the matching. The matched expression has then to be verified by either:equalToJson
for strict equality (can be another json object, a string, number etc..)contains
; if json matched byexpression
is a string it must contain the supplied string
matchesJsonPath
json request body has to contain the supplied key identified by a JSONPath. You can also use JSONPath expression to also filter and match the json valuesbinaryEqualTo
byte equality matcher. Has to be base 64 encoded
Priority
Sometimes, you can have 2 different stubs that could both match a given http request. This happens most of the time when you start writing stubs for your application errors. You basically should have:
- one relaxed stub for your nominal case matching for example
"urlPathPattern": "/users/([0-9]{4})"
- one stub for each error with hardcoded value e.g.
"urlPath": "/users/1234"
for a404
response
The issue here is that if your stub server receives a GET /users/1234
request, both stubs will match. You want your
error stub to have a higher than the nominal e.g. error stub will have a priority of 1 whereas the nominal one will have
a priority of 2.
{
"priority": 1
}
priority
a u8. 1 is the highest priority, 255 the lowest, 5 the default value when absent. It is optional.