0
# Extension System
1
2
Plugin architecture for extending WireMock functionality with custom transformers, filters, event listeners, and administrative capabilities. Supports both programmatic and declarative extension registration.
3
4
## Capabilities
5
6
### Core Extension Infrastructure
7
8
Base extension interface and lifecycle management for all WireMock extensions.
9
10
```java { .api }
11
/**
12
* Base interface for all WireMock extensions
13
*/
14
interface Extension {
15
/** Get unique extension name */
16
String getName();
17
18
/** Called when extension is loaded and server starts */
19
default void start() {}
20
21
/** Called when server stops */
22
default void stop() {}
23
}
24
25
/**
26
* Parameter container for extension configuration
27
*/
28
class Parameters extends Metadata {
29
/** Get parameter value by key */
30
<T> T get(String key);
31
32
/** Get parameter value with default */
33
<T> T get(String key, T defaultValue);
34
35
/** Check if parameter exists */
36
boolean containsKey(String key);
37
38
/** Get all parameter keys */
39
Set<String> keySet();
40
41
/** Check if parameters are empty */
42
boolean isEmpty();
43
}
44
```
45
46
### Response Transformation Extensions
47
48
Modern response transformation capabilities with access to request context and serve events.
49
50
```java { .api }
51
/**
52
* Modern interface for transforming HTTP responses
53
*/
54
interface ResponseTransformerV2 extends Extension {
55
/** Transform response with full context */
56
Response transform(Response response, ServeEvent serveEvent);
57
58
/** Check if transformer applies to this request */
59
default boolean applyGlobally() {
60
return false;
61
}
62
}
63
64
/**
65
* Interface for transforming response definitions before serving
66
*/
67
interface ResponseDefinitionTransformerV2 extends Extension {
68
/** Transform response definition */
69
ResponseDefinition transform(ResponseDefinition responseDefinition,
70
Request request, Parameters parameters);
71
72
/** Get transformer name */
73
String getName();
74
75
/** Check if transformer applies globally */
76
default boolean applyGlobally() {
77
return false;
78
}
79
}
80
81
/**
82
* Abstract base class for response transformers
83
*/
84
abstract class AbstractTransformer implements ResponseDefinitionTransformerV2 {
85
/** Constructor with transformer name */
86
protected AbstractTransformer(String name);
87
88
/** Constructor with global application flag */
89
protected AbstractTransformer(String name, boolean applyGlobally);
90
91
String getName();
92
boolean applyGlobally();
93
}
94
95
/**
96
* Base class for stub mapping transformations during recording
97
*/
98
abstract class StubMappingTransformer {
99
/** Transform stub mapping */
100
abstract StubMapping transform(StubMapping stubMapping,
101
FileSource files, Parameters parameters);
102
103
/** Get transformer name */
104
abstract String getName();
105
}
106
```
107
108
**Usage Examples:**
109
110
```java
111
// Custom response transformer
112
public class TimestampTransformer implements ResponseTransformerV2 {
113
@Override
114
public String getName() {
115
return "timestamp-transformer";
116
}
117
118
@Override
119
public Response transform(Response response, ServeEvent serveEvent) {
120
String originalBody = response.getBodyAsString();
121
String timestampedBody = originalBody.replace(
122
"{{timestamp}}",
123
Instant.now().toString()
124
);
125
126
return Response.Builder.like(response)
127
.but()
128
.body(timestampedBody)
129
.build();
130
}
131
}
132
133
// Register transformer
134
wireMock.stubFor(get(urlEqualTo("/api/time"))
135
.willReturn(aResponse()
136
.withBody("Current time: {{timestamp}}")
137
.withTransformers("timestamp-transformer")));
138
```
139
140
### Request Filtering Extensions
141
142
Modern request filtering system for intercepting and modifying requests before they reach stub matching.
143
144
```java { .api }
145
/**
146
* Modern interface for filtering incoming requests
147
*/
148
interface RequestFilterV2 extends Extension {
149
/** Filter request and return action */
150
RequestFilterAction filter(Request request, Parameters parameters);
151
}
152
153
/**
154
* V2 filter specifically for stub requests
155
*/
156
interface StubRequestFilterV2 extends RequestFilterV2 {
157
// Inherits filter method from RequestFilterV2
158
}
159
160
/**
161
* V2 filter for admin API requests
162
*/
163
interface AdminRequestFilterV2 extends RequestFilterV2 {
164
// Inherits filter method from RequestFilterV2
165
}
166
167
/**
168
* Action class for filter responses
169
*/
170
class RequestFilterAction {
171
/** Continue processing request */
172
static RequestFilterAction continueWith(Request request);
173
174
/** Stop processing and return response */
175
static RequestFilterAction stopWith(ResponseDefinition responseDefinition);
176
177
/** Check if processing should continue */
178
boolean isContinue();
179
180
/** Check if processing should stop */
181
boolean isStop();
182
183
/** Get the request (possibly modified) */
184
Request getRequest();
185
186
/** Get the response definition to return */
187
ResponseDefinition getResponseDefinition();
188
}
189
```
190
191
**Usage Examples:**
192
193
```java
194
// Custom request filter
195
public class AuthFilter implements StubRequestFilterV2 {
196
@Override
197
public String getName() {
198
return "auth-filter";
199
}
200
201
@Override
202
public RequestFilterAction filter(Request request, Parameters parameters) {
203
String authHeader = request.getHeader("Authorization");
204
205
if (authHeader == null || !authHeader.startsWith("Bearer ")) {
206
return RequestFilterAction.stopWith(
207
aResponse()
208
.withStatus(401)
209
.withBody("Unauthorized")
210
.build()
211
);
212
}
213
214
return RequestFilterAction.continueWith(request);
215
}
216
}
217
218
// Register filter in configuration
219
WireMockServer server = new WireMockServer(
220
wireMockConfig()
221
.extensions("com.example.AuthFilter")
222
);
223
```
224
225
### Event Listening Extensions
226
227
Modern event listener system for monitoring request lifecycle and stub management events.
228
229
```java { .api }
230
/**
231
* Modern interface for listening to request lifecycle events
232
*/
233
interface ServeEventListener extends Extension {
234
/** Called before request matching */
235
default void beforeMatch(ServeEvent serveEvent, Parameters parameters) {}
236
237
/** Called after request matching */
238
default void afterMatch(ServeEvent serveEvent, Parameters parameters) {}
239
240
/** Called before response is sent */
241
default void beforeResponseSent(ServeEvent serveEvent, Parameters parameters) {}
242
243
/** Called after request processing is complete */
244
default void afterComplete(ServeEvent serveEvent, Parameters parameters) {}
245
}
246
247
/**
248
* Interface for listening to stub mapping lifecycle events
249
*/
250
interface StubLifecycleListener extends Extension {
251
/** Called when stub mapping is created */
252
default void onStubMappingAdded(StubMapping stubMapping) {}
253
254
/** Called when stub mapping is updated */
255
default void onStubMappingUpdated(StubMapping oldStubMapping, StubMapping newStubMapping) {}
256
257
/** Called when stub mapping is removed */
258
default void onStubMappingRemoved(StubMapping stubMapping) {}
259
260
/** Called when all stubs are reset */
261
default void onStubMappingsReset() {}
262
}
263
```
264
265
**Usage Examples:**
266
267
```java
268
// Request monitoring listener
269
public class RequestMonitor implements ServeEventListener {
270
@Override
271
public String getName() {
272
return "request-monitor";
273
}
274
275
@Override
276
public void beforeMatch(ServeEvent serveEvent, Parameters parameters) {
277
LoggedRequest request = serveEvent.getRequest();
278
System.out.println("Incoming request: " + request.getMethod() + " " + request.getUrl());
279
}
280
281
@Override
282
public void afterComplete(ServeEvent serveEvent, Parameters parameters) {
283
System.out.println("Request completed in " +
284
serveEvent.getTiming().getTotalTime() + "ms");
285
}
286
}
287
288
// Stub change listener
289
public class StubChangeLogger implements StubLifecycleListener {
290
@Override
291
public String getName() {
292
return "stub-change-logger";
293
}
294
295
@Override
296
public void onStubMappingAdded(StubMapping stubMapping) {
297
System.out.println("Added stub: " + stubMapping.getName());
298
}
299
300
@Override
301
public void onStubMappingRemoved(StubMapping stubMapping) {
302
System.out.println("Removed stub: " + stubMapping.getName());
303
}
304
}
305
```
306
307
### Template System Extensions
308
309
Extensions for providing custom Handlebars helpers and template model data.
310
311
```java { .api }
312
/**
313
* Interface for providing custom Handlebars template helpers
314
*/
315
interface TemplateHelperProviderExtension extends Extension {
316
/** Get map of helper name to helper instance */
317
Map<String, Helper<?>> provideTemplateHelpers();
318
}
319
320
/**
321
* Interface for providing additional template model data
322
*/
323
interface TemplateModelDataProviderExtension extends Extension {
324
/** Get additional model data for template rendering */
325
Map<String, Object> provideTemplateModelData(ServeEvent serveEvent);
326
}
327
328
/**
329
* Main response templating transformer implementation
330
*/
331
class ResponseTemplateTransformer extends AbstractTransformer {
332
/** Constructor with global application */
333
ResponseTemplateTransformer(boolean global);
334
335
/** Constructor with global and permitted system keys */
336
ResponseTemplateTransformer(boolean global, String... permittedSystemKeys);
337
}
338
```
339
340
**Usage Examples:**
341
342
```java
343
// Custom template helper
344
public class CustomHelpers implements TemplateHelperProviderExtension {
345
@Override
346
public String getName() {
347
return "custom-helpers";
348
}
349
350
@Override
351
public Map<String, Helper<?>> provideTemplateHelpers() {
352
return Map.of(
353
"uppercase", (Helper<String>) (context, options) ->
354
context != null ? context.toString().toUpperCase() : "",
355
"randomId", (Helper<Object>) (context, options) ->
356
UUID.randomUUID().toString()
357
);
358
}
359
}
360
361
// Use custom helpers in templates
362
stubFor(get(urlEqualTo("/api/user"))
363
.willReturn(aResponse()
364
.withBody("User: {{uppercase request.headers.X-User-Name}}, ID: {{randomId}}")
365
.withTransformers("response-template")));
366
```
367
368
### Admin API Extensions
369
370
Extensions for adding custom administrative endpoints and mappings loaders.
371
372
```java { .api }
373
/**
374
* Interface for extending the admin API with custom routes
375
*/
376
interface AdminApiExtension extends Extension {
377
/** Contribute additional admin routes */
378
void contributeAdminApiRoutes(AdminRoutes adminRoutes);
379
}
380
381
/**
382
* Interface for custom stub mapping loaders
383
*/
384
interface MappingsLoaderExtension extends Extension {
385
/** Load mappings from custom source */
386
void loadMappingsInto(StubMappings stubMappings);
387
}
388
```
389
390
### Extension Configuration and Registration
391
392
Configuration and registration mechanisms for extensions.
393
394
```java { .api }
395
/**
396
* Extension declarations for configuration
397
*/
398
class ExtensionDeclarations {
399
/** Get declared extensions */
400
Map<String, ExtensionDeclaration> getExtensions();
401
402
/** Get extension by name */
403
ExtensionDeclaration getExtension(String name);
404
405
/** Check if extension is declared */
406
boolean hasExtension(String name);
407
}
408
409
class ExtensionDeclaration {
410
String getName();
411
String getClassName();
412
Map<String, Object> getParameters();
413
}
414
415
/**
416
* Extension factory interface
417
*/
418
interface ExtensionFactory {
419
/** Create extension instance */
420
Extension create();
421
}
422
```
423
424
**Usage Examples:**
425
426
```java
427
// Programmatic extension registration
428
WireMockServer server = new WireMockServer(
429
wireMockConfig()
430
.extensions(
431
new TimestampTransformer(),
432
new AuthFilter(),
433
new RequestMonitor()
434
)
435
.extensionScanningEnabled(true)
436
);
437
438
// Class-based registration
439
WireMockServer server = new WireMockServer(
440
wireMockConfig()
441
.extensions(
442
"com.example.TimestampTransformer",
443
"com.example.AuthFilter"
444
)
445
);
446
447
// Factory-based registration
448
WireMockServer server = new WireMockServer(
449
wireMockConfig()
450
.extensionFactories(
451
() -> new TimestampTransformer(),
452
CustomExtensionFactory.class
453
)
454
);
455
```
456
457
### Legacy Extension Interfaces
458
459
```java { .api }
460
/**
461
* @deprecated Use ResponseTransformerV2 instead
462
*/
463
@Deprecated
464
interface ResponseTransformer extends Extension {
465
Response transform(Request request, Response response,
466
FileSource files, Parameters parameters);
467
}
468
469
/**
470
* @deprecated Use ServeEventListener instead
471
*/
472
@Deprecated
473
interface PostServeAction extends Extension {
474
void doAction(ServeEvent serveEvent, Parameters parameters);
475
}
476
477
/**
478
* @deprecated Use RequestFilterV2 instead
479
*/
480
@Deprecated
481
interface RequestFilter extends Extension {
482
RequestWrapper filter(RequestWrapper request);
483
}
484
```