Skip to content

[BUG] Spring SDK dynamic headers mutate immutable or template-owned value collections #7771

Closed

Description

@Aias00

Current behavior

The Spring contract creates static header values with Collections.singleton, while request/template cloning copies at most the outer header map. RequestHeaderParameterProcessor then appends dynamic values to the existing value collection.

There are two manifestations of the same collection-ownership problem:

  1. Normal annotation-created static headers are immutable: combining one with a dynamic parameter for the same header throws before any transport request.
  2. If a programmatic/customized template uses mutable value collections, the shallow copy shares those values with the reusable template. Dynamic values accumulate across subsequent invocations.

Locations / reachable flow

Reproduction / validation

Define this ordinary Spring SDK method:

@GetMapping(value = "/items", headers = "X-Mode=static")
String call(@RequestHeader("X-Mode") String value);

A probe compiled the current contract, RequestTemplate, response handler and header processor. It parsed the actual interface through SpringMvcContract, then called public ShenyuClientMethodHandler.invoke() with a recording in-process transport:

BUILTIN_CONTRACT_EXCEPTION=UnsupportedOperationException TRANSPORT_CALLS=0

As a separate control, the probe changed only that parsed template's value collection to a mutable [static], then invoked with one and two:

MUTABLE_TEMPLATE_REQUESTS=[[static, one], [static, one, two]]
TEMPLATE_AFTER_CALLS=[static, one, two]

The ordinary built-in case is the first-call exception, not repeated accumulation from a built-in ArrayList. Independent review corrected that initial assumption after inspecting Collections.singleton. The executed reproduction covers the RequestHeader branch; the CookieValue counterpart is source-inspected. No external HTTP service or sensitive header values were involved.

Impact / suggested fix

Combining supported static and dynamic headers fails; mutable reusable templates can also retain prior invocation state. Give each invocation mutable, independently owned value collections before parameter processing, and avoid modifying template-owned collections in the processors. Preserve the intended append/replace contract without duplicating static cookie/header values during merges.

Related existing work

#7711 concerns response status handling, #7712 path replacement syntax, #7464 query encoding and #7465 annotation name aliases. #6254 concerns a different MCP request-template header substitution path. Complete-title/open-PR and live RequestTemplate/header/UnsupportedOperationException searches found no matching collection-ownership report.

Reviewed revision

Apache ShenYu 2.7.2-SNAPSHOT, master@66d7d954ca37d651a5ad916f988a8081157a7ab4. P2 / Medium; high confidence. Unit-test and CI issue categories excluded.

Activity

  1. konlue commented on Oct 17, 2026

    @konlue
    Contributor

    /assign

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions