diff --git a/spring-web/src/main/java/org/springframework/http/support/Netty4HeadersAdapter.java b/spring-web/src/main/java/org/springframework/http/support/Netty4HeadersAdapter.java index 97e853d4b763..80d030261199 100644 --- a/spring-web/src/main/java/org/springframework/http/support/Netty4HeadersAdapter.java +++ b/spring-web/src/main/java/org/springframework/http/support/Netty4HeadersAdapter.java @@ -17,7 +17,9 @@ package org.springframework.http.support; import java.util.AbstractSet; +import java.util.ArrayList; import java.util.Collection; +import java.util.Collections; import java.util.Iterator; import java.util.List; import java.util.Map; @@ -51,6 +53,12 @@ public Netty4HeadersAdapter(HttpHeaders headers) { this.headers = headers; } + private void addAllIgnoreCase(String key, List values) { + List listToUpdate = this.get(key); + listToUpdate = listToUpdate == null ? new ArrayList<>() : new ArrayList<>(listToUpdate); + listToUpdate.addAll(values); + this.headers.set(key, listToUpdate); + } @Override @Nullable @@ -61,18 +69,18 @@ public String getFirst(String key) { @Override public void add(String key, @Nullable String value) { if (value != null) { - this.headers.add(key, value); + addAllIgnoreCase(key, Collections.singletonList(value)); } } @Override public void addAll(String key, List values) { - this.headers.add(key, values); + addAllIgnoreCase(key, values); } @Override public void addAll(MultiValueMap values) { - values.forEach(this.headers::add); + values.forEach(this::addAllIgnoreCase); } @Override diff --git a/spring-web/src/main/java/org/springframework/http/support/Netty5HeadersAdapter.java b/spring-web/src/main/java/org/springframework/http/support/Netty5HeadersAdapter.java index 26d7b7fd7c49..a633cc765499 100644 --- a/spring-web/src/main/java/org/springframework/http/support/Netty5HeadersAdapter.java +++ b/spring-web/src/main/java/org/springframework/http/support/Netty5HeadersAdapter.java @@ -53,6 +53,12 @@ public Netty5HeadersAdapter(HttpHeaders headers) { this.headers = headers; } + private void addAllIgnoreCase(String key, List values) { + List listToUpdate = this.get(key); + listToUpdate = listToUpdate == null ? new ArrayList<>() : new ArrayList<>(listToUpdate); + listToUpdate.addAll(values); + this.headers.set(key, listToUpdate); + } @Override @Nullable @@ -64,18 +70,18 @@ public String getFirst(String key) { @Override public void add(String key, @Nullable String value) { if (value != null) { - this.headers.add(key, value); + addAllIgnoreCase(key, Collections.singletonList(value)); } } @Override public void addAll(String key, List values) { - this.headers.add(key, values); + addAllIgnoreCase(key, values); } @Override public void addAll(MultiValueMap values) { - values.forEach(this.headers::add); + values.forEach(this::addAllIgnoreCase); } @Override diff --git a/spring-web/src/test/java/org/springframework/http/server/reactive/HeadersAdaptersTests.java b/spring-web/src/test/java/org/springframework/http/server/reactive/HeadersAdaptersTests.java index 9c7adf5451e6..068fcc06aafa 100644 --- a/spring-web/src/test/java/org/springframework/http/server/reactive/HeadersAdaptersTests.java +++ b/spring-web/src/test/java/org/springframework/http/server/reactive/HeadersAdaptersTests.java @@ -20,6 +20,7 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; +import java.util.Collections; import java.util.Iterator; import java.util.List; import java.util.Locale; @@ -126,6 +127,42 @@ void shouldFailIfHeaderRemovedFromKeyset(MultiValueMap headers) assertThatThrownBy(names::remove).isInstanceOf(IllegalStateException.class); } + @ParameterizedHeadersTest + void testAddHeadersOutput(MultiValueMap headers) { + headers.add("TestHeader", "first"); + headers.add("testHeader", "second"); + MultiValueMap multiValueMap = + CollectionUtils.toMultiValueMap(new LinkedCaseInsensitiveMap<>(8, Locale.ENGLISH)); + headers.forEach(multiValueMap::addAll); + assertThat(multiValueMap.toString()).isEqualToIgnoringCase("{testheader=[first, second]}"); + } + + @ParameterizedHeadersTest + void testAddAllSingletonHeadersOutput(MultiValueMap headers) { + headers.addAll("TestHeader", Collections.singletonList("first")); + headers.addAll("testHeader", Collections.singletonList("second")); + MultiValueMap multiValueMap = + CollectionUtils.toMultiValueMap(new LinkedCaseInsensitiveMap<>(8, Locale.ENGLISH)); + headers.forEach(multiValueMap::addAll); + assertThat(multiValueMap.toString()).isEqualToIgnoringCase("{testheader=[first, second]}"); + } + + @ParameterizedHeadersTest + void testAddAllMultipleHeadersOutput(MultiValueMap headers) { + MultiValueMap map1 = + CollectionUtils.toMultiValueMap(new LinkedCaseInsensitiveMap<>(8, Locale.ENGLISH)); + map1.add("TestHeader", "first"); + headers.addAll(map1); + MultiValueMap map2 = + CollectionUtils.toMultiValueMap(new LinkedCaseInsensitiveMap<>(8, Locale.ENGLISH)); + map2.add("testHeader", "second"); + headers.addAll(map2); + MultiValueMap multiValueMap = + CollectionUtils.toMultiValueMap(new LinkedCaseInsensitiveMap<>(8, Locale.ENGLISH)); + headers.forEach(multiValueMap::addAll); + assertThat(multiValueMap.toString()).isEqualToIgnoringCase("{testheader=[first, second]}"); + } + @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) @ParameterizedTest