Skip to content

pact_consumer: interaction_configuration not merged across request/response builders (only pact_configuration is) #538

Description

@rholshausen

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).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions