0
# Request Matching
1
2
Advanced pattern matching capabilities for precise request identification including URL patterns, string matching, JSON/XML processing, date/time comparisons, and custom matchers for sophisticated request matching scenarios.
3
4
## Capabilities
5
6
### URL Pattern Matching
7
8
URL and path pattern matching with support for exact matching, regex patterns, and path templates.
9
10
```java { .api }
11
/**
12
* URL pattern matching methods
13
*/
14
// Exact URL matching
15
static UrlPattern urlEqualTo(String testUrl);
16
17
// Regex URL matching
18
static UrlPattern urlMatching(String urlRegex);
19
20
// Exact URL path matching (ignores query parameters)
21
static UrlPattern urlPathEqualTo(String testPath);
22
23
// Regex URL path matching
24
static UrlPattern urlPathMatching(String urlRegex);
25
26
// URL path template matching with parameter extraction
27
static UrlPattern urlPathTemplate(String pathTemplate);
28
29
// Match any URL
30
static UrlPattern anyUrl();
31
32
class UrlPattern {
33
static UrlPattern ANY;
34
boolean isRegex();
35
StringValuePattern getPattern();
36
PathTemplate getPathTemplate();
37
}
38
```
39
40
**Usage Examples:**
41
42
```java
43
// Exact URL matching
44
stubFor(get(urlEqualTo("/api/users/123"))
45
.willReturn(aResponse().withStatus(200)));
46
47
// Regex URL matching
48
stubFor(get(urlMatching("/api/users/[0-9]+"))
49
.willReturn(aResponse().withStatus(200)));
50
51
// Path template with parameters
52
stubFor(get(urlPathTemplate("/api/users/{id}/orders/{orderId}"))
53
.willReturn(aResponse().withStatus(200)));
54
55
// Path-only matching (ignores query params)
56
stubFor(get(urlPathEqualTo("/api/search"))
57
.willReturn(aResponse().withStatus(200)));
58
```
59
60
### String Value Pattern Matching
61
62
Comprehensive string pattern matching with logical operators and case sensitivity options.
63
64
```java { .api }
65
/**
66
* String value pattern matching methods
67
*/
68
// Basic String Patterns
69
/** Exact string equality matching */
70
static StringValuePattern equalTo(String value);
71
72
/** Case-insensitive equality matching */
73
static StringValuePattern equalToIgnoreCase(String value);
74
75
/** Substring containment matching */
76
static StringValuePattern containing(String value);
77
78
/** Inverted substring matching */
79
static StringValuePattern notContaining(String value);
80
81
/** Regular expression matching */
82
static StringValuePattern matching(String regex);
83
84
/** Inverted regular expression matching */
85
static StringValuePattern notMatching(String regex);
86
87
/** Match absent/null values */
88
static StringValuePattern absent();
89
90
// Logical Operators
91
/** Logical AND combination of patterns */
92
static LogicalAnd and(StringValuePattern... matchers);
93
94
/** Logical OR combination of patterns */
95
static LogicalOr or(StringValuePattern... matchers);
96
97
/** Logical NOT wrapper for patterns */
98
static NotPattern not(StringValuePattern unexpectedPattern);
99
100
abstract class StringValuePattern {
101
/** Check if pattern expects value presence */
102
boolean isPresent();
103
104
/** Check if pattern expects value absence */
105
Boolean isAbsent();
106
107
/** Combine with another pattern using AND logic */
108
LogicalAnd and(StringValuePattern other);
109
110
/** Combine with another pattern using OR logic */
111
LogicalOr or(StringValuePattern other);
112
}
113
```
114
115
**Usage Examples:**
116
117
```java
118
// String pattern matching
119
stubFor(get(urlEqualTo("/api/search"))
120
.withQueryParam("q", containing("java"))
121
.withQueryParam("category", equalToIgnoreCase("programming"))
122
.willReturn(aResponse().withStatus(200)));
123
124
// Logical combinations
125
stubFor(post(urlEqualTo("/api/users"))
126
.withHeader("Content-Type", or(
127
equalTo("application/json"),
128
equalTo("application/vnd.api+json")
129
))
130
.willReturn(aResponse().withStatus(201)));
131
132
// Regex matching
133
stubFor(get(urlEqualTo("/api/users"))
134
.withHeader("User-Agent", matching(".*Chrome.*"))
135
.withHeader("Accept-Language", not(containing("en")))
136
.willReturn(aResponse().withStatus(200)));
137
```
138
139
### JSON Content Matching
140
141
Advanced JSON matching with path expressions, schema validation, and flexible comparison options.
142
143
```java { .api }
144
/**
145
* JSON content matching methods
146
*/
147
// JSON Equality Matching
148
/** Basic JSON equality */
149
static StringValuePattern equalToJson(String json);
150
151
/** JSON equality with comparison options */
152
static StringValuePattern equalToJson(String json, boolean ignoreArrayOrder, boolean ignoreExtraElements);
153
154
/** JSON equality from JsonNode */
155
static StringValuePattern equalToJson(JsonNode jsonNode, boolean ignoreArrayOrder, boolean ignoreExtraElements);
156
157
// JSONPath Expression Matching
158
/** Simple JSONPath expression matching */
159
static StringValuePattern matchingJsonPath(String jsonPath);
160
161
/** JSONPath with value pattern matching */
162
static StringValuePattern matchingJsonPath(String jsonPath, StringValuePattern valuePattern);
163
164
// JSON Schema Validation
165
/** JSON Schema validation */
166
static StringValuePattern matchingJsonSchema(String schema);
167
168
/** JSON Schema validation with specific version */
169
static StringValuePattern matchingJsonSchema(String schema, JsonSchemaVersion version);
170
```
171
172
**Usage Examples:**
173
174
```java
175
// JSON equality matching
176
stubFor(post(urlEqualTo("/api/users"))
177
.withRequestBody(equalToJson(
178
"{\"name\":\"John\",\"email\":\"john@example.com\"}",
179
true, // ignore array order
180
true // ignore extra elements
181
))
182
.willReturn(aResponse().withStatus(201)));
183
184
// JSONPath matching
185
stubFor(post(urlEqualTo("/api/orders"))
186
.withRequestBody(matchingJsonPath("$.items[?(@.price > 100)]"))
187
.withRequestBody(matchingJsonPath("$.customer.email",
188
matching(".*@company\\.com")))
189
.willReturn(aResponse().withStatus(201)));
190
191
// JSON Schema validation
192
String userSchema = """
193
{
194
"type": "object",
195
"properties": {
196
"name": {"type": "string"},
197
"age": {"type": "number", "minimum": 0}
198
},
199
"required": ["name", "age"]
200
}
201
""";
202
203
stubFor(post(urlEqualTo("/api/users"))
204
.withRequestBody(matchingJsonSchema(userSchema))
205
.willReturn(aResponse().withStatus(201)));
206
```
207
208
### XML Content Matching
209
210
XML matching with XPath expressions and namespace support.
211
212
```java { .api }
213
/**
214
* XML content matching methods
215
*/
216
// XML Equality Matching
217
/** Basic XML equality */
218
static StringValuePattern equalToXml(String xml);
219
220
/** XML equality with placeholder support */
221
static StringValuePattern equalToXml(String xml, boolean enablePlaceholders);
222
223
// XPath Expression Matching
224
/** Simple XPath expression matching */
225
static StringValuePattern matchingXPath(String xpath);
226
227
/** XPath with value pattern matching */
228
static StringValuePattern matchingXPath(String xpath, StringValuePattern valuePattern);
229
230
/** XPath with namespace context */
231
static StringValuePattern matchingXPath(String xpath, Map<String, String> namespaces);
232
233
/** XPath with namespaces and value pattern */
234
static StringValuePattern matchingXPath(String xpath, Map<String, String> namespaces, StringValuePattern valuePattern);
235
```
236
237
**Usage Examples:**
238
239
```java
240
// XML equality matching
241
stubFor(post(urlEqualTo("/api/soap"))
242
.withRequestBody(equalToXml(
243
"<soap:Envelope><soap:Body><getUserRequest><userId>123</userId></getUserRequest></soap:Body></soap:Envelope>",
244
true // enable placeholders
245
))
246
.willReturn(aResponse().withStatus(200)));
247
248
// XPath matching
249
Map<String, String> namespaces = Map.of(
250
"soap", "http://schemas.xmlsoap.org/soap/envelope/",
251
"usr", "http://example.com/user"
252
);
253
254
stubFor(post(urlEqualTo("/api/soap"))
255
.withRequestBody(matchingXPath("//usr:getUserRequest/usr:userId", namespaces, matching("[0-9]+")))
256
.willReturn(aResponse().withStatus(200)));
257
```
258
259
### Date and Time Matching
260
261
Date and time pattern matching with various formats and comparison operations.
262
263
```java { .api }
264
/**
265
* Date and time matching methods
266
*/
267
// Exact Date Matching
268
/** Match exact date/time from string */
269
static StringValuePattern equalToDateTime(String dateTimeSpec);
270
271
/** Match exact date/time from ZonedDateTime */
272
static StringValuePattern equalToDateTime(ZonedDateTime dateTime);
273
274
/** Match exact date/time from LocalDateTime */
275
static StringValuePattern equalToDateTime(LocalDateTime dateTime);
276
277
// Before Date Matching
278
/** Match dates before specified time */
279
static StringValuePattern before(String dateTimeSpec);
280
281
/** Match dates before ZonedDateTime */
282
static StringValuePattern before(ZonedDateTime dateTime);
283
284
/** Match dates before LocalDateTime */
285
static StringValuePattern before(LocalDateTime dateTime);
286
287
/** Match dates before current time */
288
static StringValuePattern beforeNow();
289
290
// After Date Matching
291
/** Match dates after specified time */
292
static StringValuePattern after(String dateTimeSpec);
293
294
/** Match dates after ZonedDateTime */
295
static StringValuePattern after(ZonedDateTime dateTime);
296
297
/** Match dates after LocalDateTime */
298
static StringValuePattern after(LocalDateTime dateTime);
299
300
/** Match dates after current time */
301
static StringValuePattern afterNow();
302
303
// Current Time Matching
304
/** Match current time (within reasonable tolerance) */
305
static StringValuePattern isNow();
306
```
307
308
**Usage Examples:**
309
310
```java
311
// Date/time matching in headers or body
312
stubFor(post(urlEqualTo("/api/bookings"))
313
.withHeader("X-Booking-Date", after("2024-01-01T00:00:00Z"))
314
.withHeader("X-Expiry-Date", beforeNow())
315
.withRequestBody(matchingJsonPath("$.timestamp", isNow()))
316
.willReturn(aResponse().withStatus(201)));
317
318
// Date range matching
319
stubFor(get(urlEqualTo("/api/events"))
320
.withQueryParam("startDate", after("2024-01-01"))
321
.withQueryParam("endDate", before("2024-12-31"))
322
.willReturn(aResponse().withStatus(200)));
323
```
324
325
### Multipart Request Matching
326
327
Matching for multipart form data and file uploads.
328
329
```java { .api }
330
/**
331
* Multipart request matching
332
*/
333
interface MultipartValuePatternBuilder {
334
/** Set part name */
335
MultipartValuePatternBuilder withName(String name);
336
337
/** Set filename pattern */
338
MultipartValuePatternBuilder withFileName(StringValuePattern filenamePattern);
339
340
/** Add header pattern */
341
MultipartValuePatternBuilder withHeader(String name, StringValuePattern headerPattern);
342
343
/** Add body content pattern */
344
MultipartValuePatternBuilder withBody(ContentPattern<?> bodyPattern);
345
346
/** Build multipart pattern */
347
MultipartValuePattern build();
348
}
349
350
class MultipartValuePattern {
351
enum MatchingType { ALL, ANY }
352
353
String getName();
354
StringValuePattern getFilename();
355
Map<String, MultiValuePattern> getHeaders();
356
List<ContentPattern<?>> getBodyPatterns();
357
MatchingType getMatchingType();
358
boolean isMatchAny();
359
boolean isMatchAll();
360
}
361
```
362
363
**Usage Examples:**
364
365
```java
366
// Multipart file upload matching
367
stubFor(post(urlEqualTo("/api/upload"))
368
.withMultipartRequestBody(
369
aMultipart()
370
.withName("file")
371
.withFileName(matching(".*\\.pdf"))
372
.withHeader("Content-Type", equalTo("application/pdf"))
373
.withBody(binaryEqualTo(expectedFileContent))
374
)
375
.willReturn(aResponse().withStatus(200)));
376
```
377
378
### Custom Request Matching
379
380
Extension points for custom request matching logic.
381
382
```java { .api }
383
/**
384
* Custom request matching interfaces
385
*/
386
interface RequestMatcherExtension extends Extension {
387
/** Match request with custom logic */
388
MatchResult match(Request request, Parameters parameters);
389
}
390
391
abstract class RequestMatcher extends NamedValueMatcher<Request> {
392
/** Constructor with matcher name */
393
protected RequestMatcher(String name);
394
}
395
396
class CustomMatcherDefinition {
397
/** Create custom matcher definition */
398
CustomMatcherDefinition(String name, Parameters parameters);
399
400
String getName();
401
Parameters getParameters();
402
}
403
```