Skip to content

Commit 5034d1e

Browse files
committed
Introduce ServerHttpRequest.Builder.header() variant for setting headers
Prior to this commit, the `header(String, String)` method in the ServerHttpRequest.Builder API actually added a header value instead of setting or overriding a header value. Since this conflicted with the stated behavior in the Javadoc as well as the original intention of the method, we have decided to introduce an overloaded variant `header(String, String...)` which accepts a var-args list of header values to set or override. In addition, this commit deprecates the existing `header(String, String)` method for removal in Spring Framework 5.2. In order not to be a breaking change for custom implementations of the builder API, this commit implements the new `header(String, String...)` method as an interface `default` method, with the intent to remove the default implementation in Spring Framework 5.2 closes gh-23333
1 parent 0f9c793 commit 5034d1e

File tree

3 files changed

+76
-4
lines changed

3 files changed

+76
-4
lines changed

spring-web/src/main/java/org/springframework/http/server/reactive/DefaultServerHttpRequestBuilder.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,7 @@ public ServerHttpRequest.Builder contextPath(String contextPath) {
111111
}
112112

113113
@Override
114+
@SuppressWarnings("deprecation")
114115
public ServerHttpRequest.Builder header(String key, String value) {
115116
this.httpHeaders.add(key, value);
116117
return this;

spring-web/src/main/java/org/springframework/http/server/reactive/ServerHttpRequest.java

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2018 the original author or authors.
2+
* Copyright 2002-2019 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -18,6 +18,7 @@
1818

1919
import java.net.InetSocketAddress;
2020
import java.net.URI;
21+
import java.util.Arrays;
2122
import java.util.function.Consumer;
2223

2324
import org.springframework.http.HttpCookie;
@@ -34,6 +35,7 @@
3435
*
3536
* @author Arjen Poutsma
3637
* @author Rossen Stoyanchev
38+
* @author Sam Brannen
3739
* @since 5.0
3840
*/
3941
public interface ServerHttpRequest extends HttpRequest, ReactiveHttpInputMessage {
@@ -137,16 +139,37 @@ interface Builder {
137139
Builder contextPath(String contextPath);
138140

139141
/**
140-
* Set or override the specified header.
142+
* Add the given, single header value under the given name.
143+
* @param headerName the header name
144+
* @param headerValue the header value
145+
* @deprecated This method will be removed in Spring Framework 5.2 in
146+
* favor of {@link #header(String, String...)}.
141147
*/
142-
Builder header(String key, String value);
148+
@Deprecated
149+
Builder header(String headerName, String headerValue);
150+
151+
/**
152+
* Set or override the specified header values under the given name.
153+
* <p>If you need to set a single header value, you may invoke this
154+
* method with an explicit one-element array &mdash; for example,
155+
* <code>header("key", new String[] { "value" })</code> &mdash; or you
156+
* may choose to use {@link #headers(Consumer)} for greater control.
157+
* @param headerName the header name
158+
* @param headerValues the header values
159+
* @since 5.1.9
160+
* @see #headers(Consumer)
161+
*/
162+
default Builder header(String headerName, String... headerValues) {
163+
return headers(httpHeaders -> httpHeaders.put(headerName, Arrays.asList(headerValues)));
164+
}
143165

144166
/**
145167
* Manipulate request headers. The provided {@code HttpHeaders} contains
146168
* current request headers, so that the {@code Consumer} can
147169
* {@linkplain HttpHeaders#set(String, String) overwrite} or
148170
* {@linkplain HttpHeaders#remove(Object) remove} existing values, or
149171
* use any other {@link HttpHeaders} methods.
172+
* @see #header(String, String...)
150173
*/
151174
Builder headers(Consumer<HttpHeaders> headersConsumer);
152175

spring-web/src/test/java/org/springframework/http/server/reactive/ServerHttpRequestTests.java

Lines changed: 49 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
* Unit tests for {@link AbstractServerHttpRequest}.
4242
*
4343
* @author Rossen Stoyanchev
44+
* @author Sam Brannen
4445
*/
4546
public class ServerHttpRequestTests {
4647

@@ -88,7 +89,6 @@ public void queryParamsWithNoValue() throws Exception {
8889

8990
@Test
9091
public void mutateRequest() throws Exception {
91-
9292
SslInfo sslInfo = mock(SslInfo.class);
9393
ServerHttpRequest request = createHttpRequest("/").mutate().sslInfo(sslInfo).build();
9494
assertSame(sslInfo, request.getSslInfo());
@@ -123,6 +123,54 @@ public void mutatePathWithEncodedQueryParams() throws Exception {
123123
assertEquals("name=%E6%89%8E%E6%A0%B9", request.getURI().getRawQuery());
124124
}
125125

126+
@Test
127+
@SuppressWarnings("deprecation")
128+
public void mutateHeaderByAddingHeaderValues() throws Exception {
129+
String headerName = "key";
130+
String headerValue1 = "value1";
131+
String headerValue2 = "value2";
132+
133+
ServerHttpRequest request = createHttpRequest("/path");
134+
assertNull(request.getHeaders().get(headerName));
135+
136+
request = request.mutate().header(headerName, headerValue1).build();
137+
138+
assertNotNull(request.getHeaders().get(headerName));
139+
assertEquals(1, request.getHeaders().get(headerName).size());
140+
assertEquals(headerValue1, request.getHeaders().get(headerName).get(0));
141+
142+
request = request.mutate().header(headerName, headerValue2).build();
143+
144+
assertNotNull(request.getHeaders().get(headerName));
145+
assertEquals(2, request.getHeaders().get(headerName).size());
146+
assertEquals(headerValue1, request.getHeaders().get(headerName).get(0));
147+
assertEquals(headerValue2, request.getHeaders().get(headerName).get(1));
148+
}
149+
150+
@Test
151+
public void mutateHeaderBySettingHeaderValues() throws Exception {
152+
String headerName = "key";
153+
String headerValue1 = "value1";
154+
String headerValue2 = "value2";
155+
String headerValue3 = "value3";
156+
157+
ServerHttpRequest request = createHttpRequest("/path");
158+
assertNull(request.getHeaders().get(headerName));
159+
160+
request = request.mutate().header(headerName, headerValue1, headerValue2).build();
161+
162+
assertNotNull(request.getHeaders().get(headerName));
163+
assertEquals(2, request.getHeaders().get(headerName).size());
164+
assertEquals(headerValue1, request.getHeaders().get(headerName).get(0));
165+
assertEquals(headerValue2, request.getHeaders().get(headerName).get(1));
166+
167+
request = request.mutate().header(headerName, new String[] { headerValue3 }).build();
168+
169+
assertNotNull(request.getHeaders().get(headerName));
170+
assertEquals(1, request.getHeaders().get(headerName).size());
171+
assertEquals(headerValue3, request.getHeaders().get(headerName).get(0));
172+
}
173+
126174
private ServerHttpRequest createHttpRequest(String uriString) throws Exception {
127175
URI uri = URI.create(uriString);
128176
MockHttpServletRequest request = new TestHttpServletRequest(uri);

0 commit comments

Comments
 (0)