Skip to content

Commit 011fea1

Browse files
nosanwilkinsona
authored andcommitted
Allow multiple values to be specified when configuring a default header
See gh-17286
1 parent 2f49d6d commit 011fea1

File tree

4 files changed

+41
-18
lines changed

4 files changed

+41
-18
lines changed

spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/client/RestTemplateBuilder.java

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ public class RestTemplateBuilder {
9191

9292
private final BasicAuthentication basicAuthentication;
9393

94-
private final Map<String, String> defaultHeaders;
94+
private final Map<String, List<String>> defaultHeaders;
9595

9696
private final Set<RestTemplateCustomizer> customizers;
9797

@@ -122,7 +122,7 @@ private RestTemplateBuilder(RequestFactoryCustomizer requestFactoryCustomizer, b
122122
String rootUri, Set<HttpMessageConverter<?>> messageConverters,
123123
Set<ClientHttpRequestInterceptor> interceptors, Supplier<ClientHttpRequestFactory> requestFactorySupplier,
124124
UriTemplateHandler uriTemplateHandler, ResponseErrorHandler errorHandler,
125-
BasicAuthentication basicAuthentication, Map<String, String> defaultHeaders,
125+
BasicAuthentication basicAuthentication, Map<String, List<String>> defaultHeaders,
126126
Set<RestTemplateCustomizer> customizers, Set<RestTemplateRequestCustomizer<?>> requestCustomizers) {
127127
this.requestFactoryCustomizer = requestFactoryCustomizer;
128128
this.detectRequestFactory = detectRequestFactory;
@@ -395,15 +395,17 @@ this.errorHandler, new BasicAuthentication(username, password, charset), this.de
395395
* Add a default header that will be set if not already present on the outgoing
396396
* {@link HttpClientRequest}.
397397
* @param name the name of the header
398-
* @param value the header value
398+
* @param values the header values
399399
* @return a new builder instance
400400
* @since 2.2.0
401401
*/
402-
public RestTemplateBuilder defaultHeader(String name, String value) {
402+
public RestTemplateBuilder defaultHeader(String name, String... values) {
403+
Assert.notNull(name, "Name must not be null");
404+
Assert.notNull(values, "Values must not be null");
403405
return new RestTemplateBuilder(this.requestFactoryCustomizer, this.detectRequestFactory, this.rootUri,
404406
this.messageConverters, this.interceptors, this.requestFactory, this.uriTemplateHandler,
405-
this.errorHandler, this.basicAuthentication, append(this.defaultHeaders, name, value), this.customizers,
406-
this.requestCustomizers);
407+
this.errorHandler, this.basicAuthentication, append(this.defaultHeaders, name, values),
408+
this.customizers, this.requestCustomizers);
407409
}
408410

409411
/**
@@ -683,6 +685,10 @@ private <T> Set<T> setOf(Collection<? extends T> collection) {
683685
return Collections.unmodifiableSet(new LinkedHashSet<>(collection));
684686
}
685687

688+
private static <T> List<T> listOf(T[] items) {
689+
return Collections.unmodifiableList(new ArrayList<>(Arrays.asList(items)));
690+
}
691+
686692
private static <T> Set<T> append(Collection<? extends T> collection, Collection<? extends T> additions) {
687693
Set<T> result = new LinkedHashSet<>((collection != null) ? collection : Collections.emptySet());
688694
if (additions != null) {
@@ -691,9 +697,11 @@ private static <T> Set<T> append(Collection<? extends T> collection, Collection<
691697
return Collections.unmodifiableSet(result);
692698
}
693699

694-
private static <K, V> Map<K, V> append(Map<K, V> map, K key, V value) {
695-
Map<K, V> result = new LinkedHashMap<>((map != null) ? map : Collections.emptyMap());
696-
result.put(key, value);
700+
private static <K, V> Map<K, List<V>> append(Map<K, List<V>> map, K key, V[] values) {
701+
Map<K, List<V>> result = new LinkedHashMap<>((map != null) ? map : Collections.emptyMap());
702+
if (values != null) {
703+
result.put(key, listOf(values));
704+
}
697705
return Collections.unmodifiableMap(result);
698706
}
699707

spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/client/RestTemplateBuilderClientHttpRequestFactoryWrapper.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
import java.io.IOException;
2020
import java.net.URI;
21+
import java.util.List;
2122
import java.util.Map;
2223
import java.util.Set;
2324

@@ -39,12 +40,12 @@ class RestTemplateBuilderClientHttpRequestFactoryWrapper extends AbstractClientH
3940

4041
private final BasicAuthentication basicAuthentication;
4142

42-
private final Map<String, String> defaultHeaders;
43+
private final Map<String, List<String>> defaultHeaders;
4344

4445
private final Set<RestTemplateRequestCustomizer<?>> requestCustomizers;
4546

4647
RestTemplateBuilderClientHttpRequestFactoryWrapper(ClientHttpRequestFactory requestFactory,
47-
BasicAuthentication basicAuthentication, Map<String, String> defaultHeaders,
48+
BasicAuthentication basicAuthentication, Map<String, List<String>> defaultHeaders,
4849
Set<RestTemplateRequestCustomizer<?>> requestCustomizers) {
4950
super(requestFactory);
5051
this.basicAuthentication = basicAuthentication;
@@ -61,7 +62,7 @@ protected ClientHttpRequest createRequest(URI uri, HttpMethod httpMethod, Client
6162
if (this.basicAuthentication != null) {
6263
this.basicAuthentication.applyTo(headers);
6364
}
64-
this.defaultHeaders.forEach(headers::addIfAbsent);
65+
this.defaultHeaders.forEach(headers::putIfAbsent);
6566
LambdaSafe.callbacks(RestTemplateRequestCustomizer.class, this.requestCustomizers, request)
6667
.invoke((customizer) -> customizer.customize(request));
6768
return request;

spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/client/RestTemplateBuilderClientHttpRequestFactoryWrapperTests.java

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,11 @@
1818

1919
import java.io.IOException;
2020
import java.net.URI;
21+
import java.util.Arrays;
2122
import java.util.Collections;
2223
import java.util.LinkedHashMap;
2324
import java.util.LinkedHashSet;
25+
import java.util.List;
2426
import java.util.Map;
2527
import java.util.Set;
2628

@@ -80,16 +82,16 @@ void createRequestWhenHasBasicAuthAndExistingAuthHeaderDoesNotAddHeader() throws
8082
@Test
8183
void createRequestWhenHasDefaultHeadersAddsMissing() throws IOException {
8284
this.headers.add("one", "existing");
83-
Map<String, String> defaultHeaders = new LinkedHashMap<>();
84-
defaultHeaders.put("one", "1");
85-
defaultHeaders.put("two", "2");
86-
defaultHeaders.put("three", "3");
85+
Map<String, List<String>> defaultHeaders = new LinkedHashMap<>();
86+
defaultHeaders.put("one", Collections.singletonList("1"));
87+
defaultHeaders.put("two", Arrays.asList("2", "3"));
88+
defaultHeaders.put("three", Collections.singletonList("4"));
8789
this.requestFactory = new RestTemplateBuilderClientHttpRequestFactoryWrapper(this.requestFactory, null,
8890
defaultHeaders, Collections.emptySet());
8991
ClientHttpRequest request = createRequest();
9092
assertThat(request.getHeaders().get("one")).containsExactly("existing");
91-
assertThat(request.getHeaders().get("two")).containsExactly("2");
92-
assertThat(request.getHeaders().get("three")).containsExactly("3");
93+
assertThat(request.getHeaders().get("two")).containsExactly("2", "3");
94+
assertThat(request.getHeaders().get("three")).containsExactly("4");
9395
}
9496

9597
@Test

spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/client/RestTemplateBuilderTests.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import java.net.URI;
2121
import java.nio.charset.StandardCharsets;
2222
import java.time.Duration;
23+
import java.util.Arrays;
2324
import java.util.Collections;
2425
import java.util.Set;
2526
import java.util.function.Supplier;
@@ -33,6 +34,7 @@
3334

3435
import org.springframework.http.HttpHeaders;
3536
import org.springframework.http.HttpMethod;
37+
import org.springframework.http.MediaType;
3638
import org.springframework.http.client.BufferingClientHttpRequestFactory;
3739
import org.springframework.http.client.ClientHttpRequest;
3840
import org.springframework.http.client.ClientHttpRequestFactory;
@@ -321,6 +323,16 @@ void defaultHeaderAddsHeader() throws IOException {
321323
assertThat(request.getHeaders()).contains(entry("spring", Collections.singletonList("boot")));
322324
}
323325

326+
@Test
327+
void defaultHeaderAddsHeaderValues() throws IOException {
328+
String name = HttpHeaders.ACCEPT;
329+
String[] values = { MediaType.APPLICATION_JSON_VALUE, MediaType.APPLICATION_XML_VALUE };
330+
RestTemplate template = this.builder.defaultHeader(name, values).build();
331+
ClientHttpRequestFactory requestFactory = template.getRequestFactory();
332+
ClientHttpRequest request = requestFactory.createRequest(URI.create("http://localhost"), HttpMethod.GET);
333+
assertThat(request.getHeaders()).contains(entry(name, Arrays.asList(values)));
334+
}
335+
324336
@Test
325337
void requestCustomizersAddsCustomizers() throws IOException {
326338
RestTemplate template = this.builder

0 commit comments

Comments
 (0)