Skip to content

modifyHeaders fails when a value is added to or removed from a header that was set - #1088

Closed
chuuminggg wants to merge 1 commit into
spring-projects:4.0.xfrom
chuuminggg:headers-set-then-modify
Closed

chuuminggg wants to merge 1 commit into
spring-projects:4.0.xfrom
chuuminggg:headers-set-then-modify

Conversation

@chuuminggg

Copy link
Copy Markdown
Contributor

When modifyHeaders() sets a header and a later modification adds or removes a value of the same header, preprocessing fails with an UnsupportedOperationException:

modifyHeaders().set("a", "alpha").add("a", "avocado");
// java.lang.UnsupportedOperationException
//     at java.base/java.util.AbstractList.add(AbstractList.java:155)
//     at java.base/java.util.AbstractList.add(AbstractList.java:113)
//     at org.springframework.util.MultiValueMapAdapter.add(MultiValueMapAdapter.java:67)
//     at org.springframework.http.HttpHeaders.add(HttpHeaders.java:1796)

modifyHeaders().set("a", "alpha", "avocado").remove("a", "alpha");
// java.lang.UnsupportedOperationException: remove
//     at java.base/java.util.Iterator.remove(Iterator.java:102)
//     at java.base/java.util.AbstractCollection.remove(AbstractCollection.java:285)
//     at org.springframework.restdocs.operation.preprocess.HeadersModifyingOperationPreprocessor$RemoveValueHeaderModification.applyTo(HeadersModifyingOperationPreprocessor.java:182)

set(String, String...) stores its values as Arrays.asList(values), and SetHeaderModification puts that fixed-size list into the headers as it is. The add modification then calls HttpHeaders.add, which appends to that list. The remove-value modification calls List.remove on it.

This PR makes SetHeaderModification put a copy of the values into the headers. The list in the headers can then be modified. Each request and response also gets its own list, so modifying one doesn't change the values that the preprocessor sets on the next one.

The new tests cover adding a value to a header that was set and removing a value from it, for both a request and a response.

Previously, modifyHeaders() put the fixed-size list of values passed to
set into the headers. A later modification that added a value to or
removed a value from the same header then failed with an
UnsupportedOperationException. A copy of the values is now used.

Signed-off-by: chuuminggg <rorrxr@naver.com>
@wilkinsona

Copy link
Copy Markdown
Member

Thanks for the suggestion but I consider that to be a misuse of the API.

@wilkinsona wilkinsona closed this Nov 6, 2026
@wilkinsona wilkinsona added status: declined Suggestion or change that we don't want to make at this time and removed status: waiting-for-triage Untriaged issue labels Nov 6, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

status: declined Suggestion or change that we don't want to make at this time

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants