Summary
When one interaction configures its request body and response body via the same plugin, and
that plugin persists different interaction_configuration data for each part, one of the
two is silently dropped.
Root cause
request_builder.rs and response_builder.rs (rust/pact_consumer/src/builders/) each wrap
the plugin's returned interaction_configuration under a "request"/"response" key
(correctly matching the convention pact-jvm also uses), but the call that stores it —
self.plugin_config.insert(matcher.plugin_name(), plugin_config) (request_builder.rs:225,
same pattern in response_builder.rs) — is a plain HashMap::insert, which replaces any
existing entry for that plugin name wholesale rather than merging.
A few lines further down (request_builder.rs:232-241) there is a merge-if-key-exists code
path, but it only merges pact_configuration, not interaction_configuration:
if let Some(plugin_config) = plugin_config {
let plugin_name = matcher.plugin_name();
if self.plugin_config.contains_key(&*plugin_name) {
let entry = self.plugin_config.get_mut(&*plugin_name).unwrap();
for (k, v) in plugin_config.pact_configuration {
entry.pact_configuration.insert(k.clone(), v.clone());
}
} else {
self.plugin_config.insert(plugin_name.to_string(), plugin_config.clone());
}
}
Net effect: whichever of request/response is configured second for a given plugin
overwrites the first's interaction_configuration entirely, since the earlier .insert()
call above already wrote a PluginConfiguration whose interaction_configuration only has
one of the two keys.
How this was found
Found while adding Lua plugin support to pact-plugins (a JWT content-matcher plugin used for
both the request and response body of one interaction). It didn't surface there because both
parts happened to use identical config values, so the overwrite was invisible. Full write-up
with pact-jvm's (correct) equivalent behavior for comparison:
https://github.com/pact-foundation/pact-plugins/blob/lua-plugins/docs/known-issues/consumer-dsl-plugin-config-inconsistencies.md#issue-1-pact-references-interaction-level-plugin-config-doesnt-merge-interaction_configuration-across-requestresponse
Suggested fix
Give interaction_configuration the same merge-if-key-exists treatment pact_configuration
already gets, in both request_builder.rs and response_builder.rs (worth checking
message_builder.rs/sync_message_builder.rs too, though those don't have a request/response
split so may not need it).
Summary
When one interaction configures its request body and response body via the same plugin, and
that plugin persists different
interaction_configurationdata for each part, one of thetwo is silently dropped.
Root cause
request_builder.rsandresponse_builder.rs(rust/pact_consumer/src/builders/) each wrapthe plugin's returned
interaction_configurationunder a"request"/"response"key(correctly matching the convention
pact-jvmalso uses), but the call that stores it —self.plugin_config.insert(matcher.plugin_name(), plugin_config)(request_builder.rs:225,same pattern in
response_builder.rs) — is a plainHashMap::insert, which replaces anyexisting entry for that plugin name wholesale rather than merging.
A few lines further down (
request_builder.rs:232-241) there is a merge-if-key-exists codepath, but it only merges
pact_configuration, notinteraction_configuration:Net effect: whichever of request/response is configured second for a given plugin
overwrites the first's
interaction_configurationentirely, since the earlier.insert()call above already wrote a
PluginConfigurationwhoseinteraction_configurationonly hasone of the two keys.
How this was found
Found while adding Lua plugin support to
pact-plugins(a JWT content-matcher plugin used forboth the request and response body of one interaction). It didn't surface there because both
parts happened to use identical config values, so the overwrite was invisible. Full write-up
with pact-jvm's (correct) equivalent behavior for comparison:
https://github.com/pact-foundation/pact-plugins/blob/lua-plugins/docs/known-issues/consumer-dsl-plugin-config-inconsistencies.md#issue-1-pact-references-interaction-level-plugin-config-doesnt-merge-interaction_configuration-across-requestresponse
Suggested fix
Give
interaction_configurationthe same merge-if-key-exists treatmentpact_configurationalready gets, in both
request_builder.rsandresponse_builder.rs(worth checkingmessage_builder.rs/sync_message_builder.rstoo, though those don't have a request/responsesplit so may not need it).