Q38 of 40 · Karate
How would you build a custom Karate plugin or extend the DSL? What's the extension boundary?
Short answer
Short answer: Karate exposes HttpClientFactory to replace the HTTP client entirely and PerfEvent for custom metrics hooks. For custom logic, write a Java class and call it via Java.type() or karate.call(). New Gherkin keywords are not supported — the extension boundary is Java and JavaScript called from within feature files, not parser-level DSL changes.
Detail
Karate's extension points, from easiest to most advanced:
1. JavaScript helpers (easiest): write utility functions in a .js file, import with read(), and call from any scenario. No Java required.
2. Java class via Java.type(): any Java class on the classpath is callable:
* def CryptoHelper = Java.type('com.example.test.CryptoHelper')
* def signature = CryptoHelper.hmacSign(payload, secret)
3. Custom RuntimeHook: implement com.intuit.karate.RuntimeHook to hook into beforeScenario, afterScenario, beforeStep, afterStep — useful for custom reporting, performance tracking, or injecting variables at runtime:
public class MyHook implements RuntimeHook {
@Override public boolean beforeScenario(ScenarioRuntime sr) {
sr.engine.setVariable("runId", UUID.randomUUID().toString());
return true;
}
}
Register in karate-config.js: karate.configure('hooks', [new MyHook()])
4. Custom HttpClient (most advanced): implement HttpClientFactory to replace the HTTP transport layer entirely — useful for adding custom signing, HTTP/3, or a non-standard transport.
What is NOT possible: adding new Gherkin keywords (Given myCustomStep), changing the DSL syntax, or modifying the match semantics. Karate's parser is not extensible at the keyword level.
// EXAMPLE
HmacSigningHook.java
// Custom RuntimeHook that adds HMAC signature to every request
public class HmacSigningHook implements RuntimeHook {
private final String secretKey;
public HmacSigningHook(String secretKey) {
this.secretKey = secretKey;
}
@Override
public boolean beforeRequest(HttpRequest request, ScenarioRuntime sr) {
String body = request.getBodyAsString() != null
? request.getBodyAsString() : "";
String timestamp = String.valueOf(System.currentTimeMillis());
String signature = HmacUtils.sign(timestamp + body, secretKey);
request.setHeader("X-Timestamp", timestamp);
request.setHeader("X-Signature", signature);
return true; // proceed with the request
}
}
// Register in karate-config.js:
// var HmacSigningHook = Java.type('com.example.test.HmacSigningHook');
// karate.configure('hooks', [new HmacSigningHook(java.lang.System.getenv('HMAC_SECRET'))]);