Updates for Spring Framework 7

This commit is contained in:
spencergibb
2025-06-05 15:58:14 -04:00
parent e40020e290
commit 6f22bcb7ba
84 changed files with 238 additions and 219 deletions

View File

@@ -6,7 +6,7 @@
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-gateway</artifactId>
<version>4.3.1-SNAPSHOT</version>
<version>5.0.0-SNAPSHOT</version>
</parent>
<artifactId>spring-cloud-gateway-docs</artifactId>
<packaging>jar</packaging>

View File

@@ -6,7 +6,7 @@
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-gateway</artifactId>
<version>4.3.1-SNAPSHOT</version>
<version>5.0.0-SNAPSHOT</version>
<packaging>pom</packaging>
<name>Spring Cloud Gateway</name>
@@ -15,7 +15,7 @@
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-build</artifactId>
<version>4.3.1-SNAPSHOT</version>
<version>5.0.0-SNAPSHOT</version>
<relativePath/>
</parent>
<scm>
@@ -55,8 +55,8 @@
<blockhound.version>1.0.8.RELEASE</blockhound.version>
<java.version>17</java.version>
<junit-pioneer.version>2.3.0</junit-pioneer.version>
<spring-cloud-circuitbreaker.version>3.3.1-SNAPSHOT</spring-cloud-circuitbreaker.version>
<spring-cloud-commons.version>4.3.1-SNAPSHOT</spring-cloud-commons.version>
<spring-cloud-circuitbreaker.version>5.0.0-SNAPSHOT</spring-cloud-circuitbreaker.version>
<spring-cloud-commons.version>5.0.0-SNAPSHOT</spring-cloud-commons.version>
<spring-cloud-function.version>4.3.1-SNAPSHOT</spring-cloud-function.version>
<spring-cloud-stream.version>4.3.1-SNAPSHOT</spring-cloud-stream.version>
</properties>

View File

@@ -6,12 +6,12 @@
<parent>
<artifactId>spring-cloud-dependencies-parent</artifactId>
<groupId>org.springframework.cloud</groupId>
<version>4.3.1-SNAPSHOT</version>
<version>5.0.0-SNAPSHOT</version>
<relativePath/>
</parent>
<artifactId>spring-cloud-gateway-dependencies</artifactId>
<version>4.3.1-SNAPSHOT</version>
<version>5.0.0-SNAPSHOT</version>
<packaging>pom</packaging>
<name>spring-cloud-gateway-dependencies</name>

View File

@@ -18,7 +18,7 @@
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-gateway-integration-tests</artifactId>
<version>4.3.1-SNAPSHOT</version>
<version>5.0.0-SNAPSHOT</version>
<relativePath>..</relativePath> <!-- lookup parent from repository -->
</parent>

View File

@@ -16,7 +16,7 @@
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-gateway-integration-tests</artifactId>
<version>4.3.1-SNAPSHOT</version>
<version>5.0.0-SNAPSHOT</version>
<relativePath>..</relativePath> <!-- lookup parent from repository -->
</parent>

View File

@@ -16,7 +16,7 @@
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-gateway-integration-tests</artifactId>
<version>4.3.1-SNAPSHOT</version>
<version>5.0.0-SNAPSHOT</version>
<relativePath>..</relativePath> <!-- lookup parent from repository -->
</parent>

View File

@@ -16,7 +16,7 @@
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-gateway-integration-tests</artifactId>
<version>4.3.1-SNAPSHOT</version>
<version>5.0.0-SNAPSHOT</version>
<relativePath>..</relativePath> <!-- lookup parent from repository -->
</parent>

View File

@@ -16,7 +16,7 @@
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-gateway</artifactId>
<version>4.3.1-SNAPSHOT</version>
<version>5.0.0-SNAPSHOT</version>
<relativePath>..</relativePath> <!-- lookup parent from repository -->
</parent>

View File

@@ -11,7 +11,7 @@
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-gateway</artifactId>
<version>4.3.1-SNAPSHOT</version>
<version>5.0.0-SNAPSHOT</version>
<relativePath>..</relativePath>
</parent>

View File

@@ -365,7 +365,7 @@ public class ProxyExchange<T> {
webRequest.getHeaderNames().forEachRemaining(headerNames::add);
Set<String> filteredKeys = filterHeaderKeys(headerNames);
filteredKeys.stream()
.filter(key -> !headers.containsKey(key))
.filter(key -> !headers.containsHeader(key))
.forEach(header -> headers.addAll(header, Arrays.asList(webRequest.getHeaderValues(header))));
}
@@ -379,7 +379,7 @@ public class ProxyExchange<T> {
}
private Set<String> filterHeaderKeys(HttpHeaders headers) {
return filterHeaderKeys(headers.keySet());
return filterHeaderKeys(headers.headerNames());
}
private Set<String> filterHeaderKeys(Collection<String> headerNames) {
@@ -529,7 +529,7 @@ public class ProxyExchange<T> {
@Override
public Enumeration<String> getHeaderNames() {
Set<String> names = headers.keySet();
Set<String> names = headers.headerNames();
if (names.isEmpty()) {
return super.getHeaderNames();
}

View File

@@ -25,6 +25,7 @@ import java.util.Set;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jspecify.annotations.Nullable;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
@@ -97,17 +98,15 @@ public class ProxyResponseAutoConfiguration implements WebMvcConfigurer {
private static class NoOpResponseErrorHandler extends DefaultResponseErrorHandler {
@Override
public void handleError(ClientHttpResponse response) throws IOException {
}
@Override
public void handleError(URI url, HttpMethod method, ClientHttpResponse response) throws IOException {
}
@Override
protected void handleError(ClientHttpResponse response, HttpStatusCode statusCode, URI url, HttpMethod method)
throws IOException {
protected void handleError(ClientHttpResponse response, HttpStatusCode statusCode, @Nullable URI url,
@Nullable HttpMethod method) throws IOException {
}
}

View File

@@ -21,6 +21,7 @@ import java.net.URI;
import java.util.Collections;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import org.jspecify.annotations.Nullable;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
@@ -39,6 +40,7 @@ import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.HttpStatusCode;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.http.client.ClientHttpResponse;
@@ -193,7 +195,14 @@ public class GetWithBodyRequestTests {
private static class NoOpResponseErrorHandler extends DefaultResponseErrorHandler {
@Override
public void handleError(ClientHttpResponse response) throws IOException {
public void handleError(URI url, HttpMethod method, ClientHttpResponse response) throws IOException {
}
@Override
protected void handleError(ClientHttpResponse response, HttpStatusCode statusCode, @Nullable URI url,
@Nullable HttpMethod method) throws IOException {
}
}

View File

@@ -558,7 +558,7 @@ public class ProductionConfigurationTests {
@GetMapping("/headers")
public Map<String, List<String>> headers(@RequestHeader HttpHeaders headers) {
return new LinkedMultiValueMap<>(headers);
return new LinkedMultiValueMap<>(headers.asMultiValueMap());
}
}

View File

@@ -6,7 +6,7 @@
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-gateway</artifactId>
<version>4.3.1-SNAPSHOT</version>
<version>5.0.0-SNAPSHOT</version>
<relativePath>..</relativePath> <!-- lookup parent from repository -->
</parent>
<artifactId>spring-cloud-gateway-proxyexchange-webflux</artifactId>

View File

@@ -6,7 +6,7 @@
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-gateway</artifactId>
<version>4.3.1-SNAPSHOT</version>
<version>5.0.0-SNAPSHOT</version>
<relativePath>..</relativePath> <!-- lookup parent from repository -->
</parent>
<artifactId>spring-cloud-gateway-proxyexchange-webmvc</artifactId>

View File

@@ -16,7 +16,7 @@
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-gateway</artifactId>
<version>4.3.1-SNAPSHOT</version>
<version>5.0.0-SNAPSHOT</version>
<relativePath>..</relativePath> <!-- lookup parent from repository -->
</parent>

View File

@@ -22,7 +22,7 @@
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-gateway</artifactId>
<version>4.3.1-SNAPSHOT</version>
<version>5.0.0-SNAPSHOT</version>
<relativePath>..</relativePath> <!-- lookup parent from repository -->
</parent>
<artifactId>spring-cloud-gateway-server-mvc</artifactId>

View File

@@ -133,12 +133,20 @@ public abstract class AfterFilterFunctions {
String replacement = originalReplacement.replace("$\\", "$");
Pattern pattern = Pattern.compile(regexp);
return (request, response) -> {
response.headers().computeIfPresent(name, (key, values) -> {
BiFunction<String, List<String>, List<String>> remappingFunction = (key, values) -> {
List<String> rewrittenValues = values.stream()
.map(value -> pattern.matcher(value).replaceAll(replacement))
.toList();
.map(value -> pattern.matcher(value).replaceAll(replacement))
.toList();
return new ArrayList<>(rewrittenValues);
});
};
if (response.headers().get(name) != null) {
List<String> oldValue = response.headers().get(name);
List<String> newValue = remappingFunction.apply(name, oldValue);
if (newValue != null)
response.headers().put(name, newValue);
else
response.headers().remove(name);
}
return response;
};
}

View File

@@ -171,7 +171,7 @@ public abstract class BeforeFilterFunctions {
public static Function<ServerRequest, ServerRequest> mapRequestHeader(String fromHeader, String toHeader) {
return request -> {
if (request.headers().asHttpHeaders().containsKey(fromHeader)) {
if (request.headers().asHttpHeaders().containsHeader(fromHeader)) {
List<String> values = request.headers().header(fromHeader);
return ServerRequest.from(request).header(toHeader, values.toArray(new String[0])).build();
}
@@ -281,7 +281,7 @@ public abstract class BeforeFilterFunctions {
public static Function<ServerRequest, ServerRequest> requestHeaderToRequestUri(String name) {
return request -> {
if (request.headers().asHttpHeaders().containsKey(name)) {
if (request.headers().asHttpHeaders().containsHeader(name)) {
String newUri = request.headers().firstHeader(name);
try {
MvcUtils.setRequestUrl(request, new URI(newUri));
@@ -302,7 +302,7 @@ public abstract class BeforeFilterFunctions {
Assert.notNull(maxSize, "maxSize may not be null");
Assert.isTrue(maxSize.toBytes() > 0, "maxSize must be greater than 0");
return request -> {
if (request.headers().asHttpHeaders().containsKey(HttpHeaders.CONTENT_LENGTH)) {
if (request.headers().asHttpHeaders().containsHeader(HttpHeaders.CONTENT_LENGTH)) {
long contentLength = request.headers().asHttpHeaders().getContentLength();
if (contentLength > maxSize.toBytes()) {
String errorMessage = String.format(REQUEST_SIZE_ERROR_MSG, DataSize.ofBytes(contentLength),

View File

@@ -304,12 +304,6 @@ public abstract class BodyFilterFunctions {
return delegate.method();
}
@Override
@Deprecated
public String methodName() {
return delegate.methodName();
}
@Override
public URI uri() {
return delegate.uri();
@@ -325,12 +319,6 @@ public abstract class BodyFilterFunctions {
return delegate.path();
}
@Override
@Deprecated
public PathContainer pathContainer() {
return delegate.pathContainer();
}
@Override
public RequestPath requestPath() {
return delegate.requestPath();

View File

@@ -42,6 +42,7 @@ import org.springframework.cloud.gateway.server.mvc.common.MvcUtils;
import org.springframework.cloud.loadbalancer.support.LoadBalancerClientFactory;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.HttpServerErrorException;
import org.springframework.web.servlet.function.HandlerFilterFunction;
@@ -135,7 +136,7 @@ public abstract class LoadBalancerFilterFunctions {
}
private static MultiValueMap<String, String> buildCookies(MultiValueMap<String, Cookie> cookies) {
HttpHeaders newCookies = new HttpHeaders();
LinkedMultiValueMap<String, String> newCookies = new LinkedMultiValueMap<>(cookies.size());
if (cookies != null) {
cookies.forEach((key, value) -> value
.forEach(cookie -> newCookies.put(cookie.getName(), Collections.singletonList(cookie.getValue()))));

View File

@@ -31,7 +31,7 @@ public class RemoveContentLengthRequestHeadersFilter implements HttpHeadersFilte
@Override
public HttpHeaders apply(HttpHeaders input, ServerRequest request) {
if (input.containsKey(HttpHeaders.CONTENT_LENGTH)) {
if (input.containsHeader(HttpHeaders.CONTENT_LENGTH)) {
HttpHeaders filtered = new HttpHeaders();
// avoids read only if input is read only

View File

@@ -31,7 +31,7 @@ public class RemoveHttp2StatusResponseHeadersFilter implements HttpHeadersFilter
@Override
public HttpHeaders apply(HttpHeaders input, ServerResponse serverResponse) {
if (input.containsKey(":status")) {
if (input.containsHeader(":status")) {
HttpHeaders filtered = new HttpHeaders();
filtered.addAll(input);

View File

@@ -32,7 +32,7 @@ public class TransferEncodingNormalizationRequestHeadersFilter
public HttpHeaders apply(HttpHeaders input, ServerRequest request) {
String transferEncoding = input.getFirst(HttpHeaders.TRANSFER_ENCODING);
if (transferEncoding != null && "chunked".equalsIgnoreCase(transferEncoding.trim())
&& input.containsKey(HttpHeaders.CONTENT_LENGTH)) {
&& input.containsHeader(HttpHeaders.CONTENT_LENGTH)) {
HttpHeaders filtered = new HttpHeaders();
// avoids read only if input is read only

View File

@@ -199,7 +199,7 @@ public class XForwardedRequestHeadersFilter implements HttpHeadersFilter.Request
headers.add(name, value);
}
// these headers should be treated as a single comma separated header
if (headers.containsKey(name)) {
if (headers.containsHeader(name)) {
List<String> values = headers.get(name).stream().filter(shouldWrite).toList();
String delimitedValue = StringUtils.collectionToCommaDelimitedString(values);
headers.set(name, delimitedValue);

View File

@@ -55,7 +55,7 @@ abstract class AbstractGatewayServerResponse extends GatewayErrorHandlingServerR
MultiValueMap<String, Cookie> cookies) {
this.statusCode = statusCode;
this.headers = HttpHeaders.writableHttpHeaders(headers);
this.headers = HttpHeaders.copyOf(headers);
this.cookies = new LinkedMultiValueMap<>(cookies);
}
@@ -69,12 +69,6 @@ abstract class AbstractGatewayServerResponse extends GatewayErrorHandlingServerR
this.statusCode = statusCode;
}
@Override
@Deprecated
public int rawStatusCode() {
return this.statusCode.value();
}
@Override
public final HttpHeaders headers() {
return this.headers;

View File

@@ -61,7 +61,7 @@ public final class FunctionHandlerHeaderUtils {
for (String name : headers.keySet()) {
Object value = headers.get(name);
name = name.toLowerCase(Locale.ROOT);
if (!IGNORED.containsKey(name) && !ignoredHeders.contains(name)) {
if (!IGNORED.containsHeader(name) && !ignoredHeders.contains(name)) {
Collection<?> values = multi(value);
for (Object object : values) {
result.set(name, object.toString());
@@ -79,10 +79,10 @@ public final class FunctionHandlerHeaderUtils {
public static HttpHeaders sanitize(HttpHeaders request, List<String> ignoredHeders,
List<String> requestOnlyHeaders) {
HttpHeaders result = new HttpHeaders();
for (String name : request.keySet()) {
for (String name : request.headerNames()) {
List<String> value = request.get(name);
name = name.toLowerCase(Locale.ROOT);
if (!IGNORED.containsKey(name) && !REQUEST_ONLY.containsKey(name) && !ignoredHeders.contains(name)
if (!IGNORED.containsHeader(name) && !REQUEST_ONLY.containsHeader(name) && !ignoredHeders.contains(name)
&& !requestOnlyHeaders.contains(name)) {
result.put(name, value);
}
@@ -97,7 +97,7 @@ public final class FunctionHandlerHeaderUtils {
public static MessageHeaders fromHttp(HttpHeaders headers) {
Map<String, Object> map = new LinkedHashMap<>();
for (String name : headers.keySet()) {
for (String name : headers.headerNames()) {
Collection<?> values = multi(headers.get(name));
name = name.toLowerCase(Locale.ROOT);
Object value = values == null ? null : (values.size() == 1 ? values.iterator().next() : values);

View File

@@ -85,12 +85,6 @@ final class GatewayAsyncServerResponse extends GatewayErrorHandlingServerRespons
return delegate(ServerResponse::statusCode);
}
@Override
@Deprecated
public int rawStatusCode() {
return delegate(ServerResponse::rawStatusCode);
}
@Override
public HttpHeaders headers() {
return delegate(ServerResponse::headers);

View File

@@ -345,12 +345,6 @@ public abstract class GatewayRequestPredicates {
super.setPathOptions(PathContainer.Options.MESSAGE_ROUTE);
}
@SuppressWarnings("deprecation")
@Override
public void setMatchOptionalTrailingSeparator(boolean matchOptionalTrailingSeparator) {
raiseError();
}
@Override
public void setCaseSensitive(boolean caseSensitive) {
raiseError();

View File

@@ -33,6 +33,7 @@ import org.springframework.boot.autoconfigure.web.client.RestTemplateAutoConfigu
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.http.client.ClientHttpRequestFactoryBuilder;
import org.springframework.boot.http.client.ClientHttpRequestFactorySettings;
import org.springframework.boot.http.client.HttpRedirects;
import org.springframework.boot.http.client.SimpleClientHttpRequestFactoryBuilder;
import org.springframework.boot.test.context.FilteredClassLoader;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
@@ -158,7 +159,7 @@ public class GatewayServerMvcAutoConfigurationTests {
assertThat(settings.readTimeout()).isEqualTo(Duration.ofSeconds(2));
assertThat(settings.connectTimeout()).isEqualTo(Duration.ofSeconds(1));
assertThat(settings.sslBundle()).isNotNull();
assertThat(settings.redirects()).isEqualTo(ClientHttpRequestFactorySettings.Redirects.DONT_FOLLOW);
assertThat(settings.redirects()).isEqualTo(HttpRedirects.DONT_FOLLOW);
}
@Test

View File

@@ -337,7 +337,7 @@ public class ServerMvcIntegrationTests {
Map<String, Object> map = res.getResponseBody();
Map<String, Object> headers = getMap(map, "headers");
assertThat(headers).doesNotContainKey("x-bar");
assertThat(res.getResponseHeaders()).containsEntry("x-bar", Collections.singletonList("val1"));
assertThat(res.getResponseHeaders().asMultiValueMap()).containsEntry("x-bar", Collections.singletonList("val1"));
});
}
@@ -739,7 +739,7 @@ public class ServerMvcIntegrationTests {
.isOk()
.expectBody(Map.class)
.consumeWith(res -> {
HttpHeaders headers = res.getResponseHeaders();
MultiValueMap<String, String> headers = res.getResponseHeaders().asMultiValueMap();
assertThat(headers).doesNotContainEntry("X-Test", List.of("value1"));
assertThat(headers).containsEntry("X-Test", List.of("value2"));
});

View File

@@ -75,7 +75,7 @@ public class TokenRelayFilterFunctionsTests {
@Test
public void emptyPrincipal() throws Exception {
filter.filter(ServerRequest.create(request, converters), req -> {
assertThat(req.headers().asHttpHeaders().containsKey(HttpHeaders.AUTHORIZATION)).isFalse();
assertThat(req.headers().asHttpHeaders().containsHeader(HttpHeaders.AUTHORIZATION)).isFalse();
return null;
});
}
@@ -131,7 +131,7 @@ public class TokenRelayFilterFunctionsTests {
public void principalIsNotOAuth2AuthenticationToken() throws Exception {
request.setUserPrincipal(new TestingAuthenticationToken("my", null));
filter.filter(ServerRequest.create(request, converters), req -> {
assertThat(req.headers().asHttpHeaders().containsKey(HttpHeaders.AUTHORIZATION)).isFalse();
assertThat(req.headers().asHttpHeaders().containsHeader(HttpHeaders.AUTHORIZATION)).isFalse();
return null;
});
}

View File

@@ -270,7 +270,7 @@ public class ForwardedRequestHeadersFilterTests {
HttpHeaders headers = filter.apply(request.headers().asHttpHeaders(), request);
assertThat(headers).doesNotContainKeys(FORWARDED_HEADER);
assertThat(headers.headerNames()).doesNotContain(FORWARDED_HEADER);
}
// verify that existing forwarded header is not forwarded if not trusted
@@ -288,7 +288,7 @@ public class ForwardedRequestHeadersFilterTests {
HttpHeaders headers = filter.apply(request.headers().asHttpHeaders(), request);
assertThat(headers).containsKeys(FORWARDED_HEADER);
assertThat(headers.headerNames()).contains(FORWARDED_HEADER);
List<String> forwardedHeaders = headers.get(FORWARDED_HEADER);
Optional<String> filtered = forwardedHeaders.stream().filter(value -> value.contains("127.0.0.1")).findFirst();
assertThat(filtered).isEmpty();
@@ -309,7 +309,7 @@ public class ForwardedRequestHeadersFilterTests {
HttpHeaders headers = filter.apply(request.headers().asHttpHeaders(), request);
assertThat(headers).containsKeys(FORWARDED_HEADER);
assertThat(headers.headerNames()).contains(FORWARDED_HEADER);
List<String> forwardedHeaders = headers.get(FORWARDED_HEADER);
Optional<String> filtered = forwardedHeaders.stream().filter(value -> value.contains("127.0.0.1")).findFirst();
assertThat(filtered).isEmpty();

View File

@@ -36,7 +36,7 @@ public class TransferEncodingNormalizationRequestHeadersFilterTests {
.buildRequest(null);
HttpHeaders headers = testFilter(ServerRequest.create(servletRequest, Collections.emptyList()));
assertThat(headers).containsKey(HttpHeaders.CONTENT_LENGTH).doesNotContainKey(HttpHeaders.TRANSFER_ENCODING);
assertThat(headers.headerNames()).contains(HttpHeaders.CONTENT_LENGTH).doesNotContain(HttpHeaders.TRANSFER_ENCODING);
}
@Test
@@ -47,7 +47,7 @@ public class TransferEncodingNormalizationRequestHeadersFilterTests {
.buildRequest(null);
HttpHeaders headers = testFilter(ServerRequest.create(servletRequest, Collections.emptyList()));
assertThat(headers).doesNotContainKey(HttpHeaders.CONTENT_LENGTH).containsKey(HttpHeaders.TRANSFER_ENCODING);
assertThat(headers.headerNames()).doesNotContain(HttpHeaders.CONTENT_LENGTH).contains(HttpHeaders.TRANSFER_ENCODING);
}
@Test
@@ -58,7 +58,7 @@ public class TransferEncodingNormalizationRequestHeadersFilterTests {
.buildRequest(null);
HttpHeaders headers = testFilter(ServerRequest.create(servletRequest, Collections.emptyList()));
assertThat(headers).doesNotContainKey(HttpHeaders.CONTENT_LENGTH).containsKey(HttpHeaders.TRANSFER_ENCODING);
assertThat(headers.headerNames()).doesNotContain(HttpHeaders.CONTENT_LENGTH).contains(HttpHeaders.TRANSFER_ENCODING);
}
private HttpHeaders testFilter(ServerRequest request) {

View File

@@ -59,8 +59,8 @@ public class XForwardedRequestHeadersFilterTests {
HttpHeaders headers = filter.apply(request.headers().asHttpHeaders(), request);
assertThat(headers).doesNotContainKeys(X_FORWARDED_FOR_HEADER)
.containsKeys(X_FORWARDED_HOST_HEADER, X_FORWARDED_PORT_HEADER, X_FORWARDED_PROTO_HEADER);
assertThat(headers.headerNames()).doesNotContain(X_FORWARDED_FOR_HEADER)
.contains(X_FORWARDED_HOST_HEADER, X_FORWARDED_PORT_HEADER, X_FORWARDED_PROTO_HEADER);
assertThat(headers.getFirst(X_FORWARDED_HOST_HEADER)).isEqualTo("myhost");
assertThat(headers.getFirst(X_FORWARDED_PORT_HEADER)).isEqualTo("80");
@@ -114,7 +114,7 @@ public class XForwardedRequestHeadersFilterTests {
HttpHeaders headers = filter.apply(request.headers().asHttpHeaders(), request);
assertThat(headers).doesNotContainKeys(X_FORWARDED_FOR_HEADER, X_FORWARDED_HOST_HEADER, X_FORWARDED_PORT_HEADER,
assertThat(headers.headerNames()).doesNotContain(X_FORWARDED_FOR_HEADER, X_FORWARDED_HOST_HEADER, X_FORWARDED_PORT_HEADER,
X_FORWARDED_PROTO_HEADER);
}
@@ -135,7 +135,7 @@ public class XForwardedRequestHeadersFilterTests {
HttpHeaders headers = filter.apply(request.headers().asHttpHeaders(), request);
assertThat(headers).containsKeys(X_FORWARDED_FOR_HEADER, X_FORWARDED_HOST_HEADER, X_FORWARDED_PORT_HEADER,
assertThat(headers.headerNames()).contains(X_FORWARDED_FOR_HEADER, X_FORWARDED_HOST_HEADER, X_FORWARDED_PORT_HEADER,
X_FORWARDED_PROTO_HEADER);
assertThat(headers.getFirst(X_FORWARDED_FOR_HEADER)).doesNotContain("127.0.0.1")
@@ -156,7 +156,7 @@ public class XForwardedRequestHeadersFilterTests {
HttpHeaders headers = filter.apply(request.headers().asHttpHeaders(), request);
assertThat(headers).containsKeys(X_FORWARDED_FOR_HEADER, X_FORWARDED_HOST_HEADER, X_FORWARDED_PORT_HEADER,
assertThat(headers.headerNames()).contains(X_FORWARDED_FOR_HEADER, X_FORWARDED_HOST_HEADER, X_FORWARDED_PORT_HEADER,
X_FORWARDED_PROTO_HEADER);
assertThat(headers.getFirst(X_FORWARDED_FOR_HEADER)).doesNotContain("127.0.0.1");

View File

@@ -35,7 +35,7 @@ public class TestAutoConfiguration {
@Bean
RestTemplateCustomizer testRestClientRestTemplateCustomizer() {
return restTemplate -> restTemplate.setClientHttpRequestInitializers(List.of(request -> {
if (!request.getHeaders().containsKey(HttpHeaders.ACCEPT)) {
if (!request.getHeaders().containsHeader(HttpHeaders.ACCEPT)) {
request.getHeaders().setAccept(List.of(MediaType.ALL));
}
}));

View File

@@ -210,7 +210,7 @@ public class HeaderAssertions {
* @since 5.0.3
*/
public TestRestClient.ResponseSpec exists(String name) {
if (!getHeaders().containsKey(name)) {
if (!getHeaders().containsHeader(name)) {
String message = getMessage(name) + " does not exist";
this.exchangeResult.assertWithDiagnostics(() -> AssertionErrors.fail(message));
}
@@ -221,7 +221,7 @@ public class HeaderAssertions {
* Expect that the header with the given name is not present.
*/
public TestRestClient.ResponseSpec doesNotExist(String name) {
if (getHeaders().containsKey(name)) {
if (getHeaders().containsHeader(name)) {
String message = getMessage(name) + " exists with value=[" + getHeaders().getFirst(name) + "]";
this.exchangeResult.assertWithDiagnostics(() -> AssertionErrors.fail(message));
}

View File

@@ -6,7 +6,7 @@
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-gateway</artifactId>
<version>4.3.1-SNAPSHOT</version>
<version>5.0.0-SNAPSHOT</version>
<relativePath>..</relativePath> <!-- lookup parent from repository -->
</parent>
<artifactId>spring-cloud-gateway-server-webflux</artifactId>

View File

@@ -6,7 +6,7 @@
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-gateway</artifactId>
<version>4.3.1-SNAPSHOT</version>
<version>5.0.0-SNAPSHOT</version>
<relativePath>..</relativePath> <!-- lookup parent from repository -->
</parent>
<artifactId>spring-cloud-gateway-server-webmvc</artifactId>

View File

@@ -7,7 +7,7 @@
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-gateway</artifactId>
<version>4.3.1-SNAPSHOT</version>
<version>5.0.0-SNAPSHOT</version>
<relativePath>..</relativePath> <!-- lookup parent from repository -->
</parent>
<artifactId>spring-cloud-gateway-server</artifactId>

View File

@@ -153,8 +153,8 @@ public class FunctionRoutingFilter implements GlobalFilter, Ordered {
ServerHttpResponse response = exchange.getResponse();
Mono<DataBuffer> messageBody = writeBody(response, outputMessage, outClass);
HttpHeaders responseHeaders = response.getHeaders();
if (!responseHeaders.containsKey(HttpHeaders.TRANSFER_ENCODING)
|| responseHeaders.containsKey(HttpHeaders.CONTENT_LENGTH)) {
if (!responseHeaders.containsHeader(HttpHeaders.TRANSFER_ENCODING)
|| responseHeaders.containsHeader(HttpHeaders.CONTENT_LENGTH)) {
messageBody = messageBody.doOnNext(data -> headers.setContentLength(data.readableByteCount()));
}
responseHeaders.addAll(newResponseHeaders);

View File

@@ -171,8 +171,8 @@ public class NettyRoutingFilter implements GlobalFilter, Ordered {
HttpHeaders filteredResponseHeaders = HttpHeadersFilter.filter(getHeadersFilters(), headers, exchange,
Type.RESPONSE);
if (!filteredResponseHeaders.containsKey(HttpHeaders.TRANSFER_ENCODING)
&& filteredResponseHeaders.containsKey(HttpHeaders.CONTENT_LENGTH)) {
if (!filteredResponseHeaders.containsHeader(HttpHeaders.TRANSFER_ENCODING)
&& filteredResponseHeaders.containsHeader(HttpHeaders.CONTENT_LENGTH)) {
// It is not valid to have both the transfer-encoding header and
// the content-length header.
// Remove the transfer-encoding header in the response if the
@@ -180,7 +180,7 @@ public class NettyRoutingFilter implements GlobalFilter, Ordered {
response.getHeaders().remove(HttpHeaders.TRANSFER_ENCODING);
}
exchange.getAttributes().put(CLIENT_RESPONSE_HEADER_NAMES, filteredResponseHeaders.keySet());
exchange.getAttributes().put(CLIENT_RESPONSE_HEADER_NAMES, filteredResponseHeaders.headerNames());
response.getHeaders().addAll(filteredResponseHeaders);

View File

@@ -59,7 +59,7 @@ public class MapRequestHeaderGatewayFilterFactory
return new GatewayFilter() {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
if (!exchange.getRequest().getHeaders().containsKey(config.getFromHeader())) {
if (!exchange.getRequest().getHeaders().containsHeader(config.getFromHeader())) {
return chain.filter(exchange);
}
List<String> headerValues = exchange.getRequest().getHeaders().get(config.getFromHeader());

View File

@@ -81,7 +81,16 @@ public class RewriteResponseHeaderGatewayFilterFactory
protected void rewriteHeaders(ServerWebExchange exchange, Config config) {
final String name = config.getName();
final HttpHeaders responseHeaders = exchange.getResponse().getHeaders();
responseHeaders.computeIfPresent(name, (k, v) -> rewriteHeaders(config, v));
if (responseHeaders.get(name) != null) {
List<String> oldValue = responseHeaders.get(name);
List<String> newValue = rewriteHeaders(config, oldValue);
if (newValue != null) {
responseHeaders.put(name, newValue);
}
else {
responseHeaders.remove(name);
}
}
}
protected List<String> rewriteHeaders(Config config, List<String> headers) {

View File

@@ -188,7 +188,9 @@ public class SecureHeadersGatewayFilterFactory
private void addHeaderIfEnabled(HttpHeaders headers, Set<String> headersToAdd, String headerName,
String headerValue) {
if (headersToAdd.contains(headerName.toLowerCase(Locale.ROOT))) {
headers.addIfAbsent(headerName, headerValue);
if (!headers.containsHeader(headerName)) {
headers.add(headerName, headerValue);
}
}
}

View File

@@ -232,8 +232,8 @@ public class ModifyResponseBodyGatewayFilterFactory
return bodyInserter.insert(outputMessage, new BodyInserterContext()).then(Mono.defer(() -> {
Mono<DataBuffer> messageBody = writeBody(getDelegate(), outputMessage, outClass);
HttpHeaders headers = getDelegate().getHeaders();
if (!headers.containsKey(HttpHeaders.TRANSFER_ENCODING)
|| headers.containsKey(HttpHeaders.CONTENT_LENGTH)) {
if (!headers.containsHeader(HttpHeaders.TRANSFER_ENCODING)
|| headers.containsHeader(HttpHeaders.CONTENT_LENGTH)) {
messageBody = messageBody.doOnNext(data -> headers.setContentLength(data.readableByteCount()));
}

View File

@@ -34,7 +34,7 @@ public class TransferEncodingNormalizationHeadersFilter implements HttpHeadersFi
public HttpHeaders filter(HttpHeaders input, ServerWebExchange exchange) {
String transferEncoding = input.getFirst(HttpHeaders.TRANSFER_ENCODING);
if (transferEncoding != null && "chunked".equalsIgnoreCase(transferEncoding.trim())
&& input.containsKey(HttpHeaders.CONTENT_LENGTH)) {
&& input.containsHeader(HttpHeaders.CONTENT_LENGTH)) {
HttpHeaders filtered = new HttpHeaders();
// avoids read only if input is read only

View File

@@ -325,7 +325,7 @@ public class XForwardedHeadersFilter implements HttpHeadersFilter, Ordered {
headers.add(name, value);
}
// these headers should be treated as a single comma separated header
if (headers.containsKey(name)) {
if (headers.containsHeader(name)) {
List<String> values = headers.get(name).stream().filter(shouldWrite).toList();
String delimitedValue = StringUtils.collectionToCommaDelimitedString(values);
headers.set(name, delimitedValue);

View File

@@ -95,7 +95,8 @@ public class PathRoutePredicateFactory extends AbstractRoutePredicateFactory<Pat
public Predicate<ServerWebExchange> apply(Config config) {
final ArrayList<PathPattern> pathPatterns = new ArrayList<>();
synchronized (this.pathPatternParser) {
pathPatternParser.setMatchOptionalTrailingSeparator(config.isMatchTrailingSlash());
// FIXME: 5.0.0 setMatchOptionalTrailingSeparator missing
// pathPatternParser.setMatchOptionalTrailingSeparator(config.isMatchTrailingSlash());
config.getPatterns().forEach(pattern -> {
String basePath = webFluxProperties.getBasePath();
boolean basePathIsNotBlank = StringUtils.hasText(basePath);

View File

@@ -61,7 +61,7 @@ public final class MessageHeaderUtils {
for (String name : headers.keySet()) {
Object value = headers.get(name);
name = name.toLowerCase(Locale.ROOT);
if (!IGNORED.containsKey(name) && !ignoredHeders.contains(name)) {
if (!IGNORED.containsHeader(name) && !ignoredHeders.contains(name)) {
Collection<?> values = multi(value);
for (Object object : values) {
result.set(name, object.toString());
@@ -79,10 +79,10 @@ public final class MessageHeaderUtils {
public static HttpHeaders sanitize(HttpHeaders request, List<String> ignoredHeders,
List<String> requestOnlyHeaders) {
HttpHeaders result = new HttpHeaders();
for (String name : request.keySet()) {
for (String name : request.headerNames()) {
List<String> value = request.get(name);
name = name.toLowerCase(Locale.ROOT);
if (!IGNORED.containsKey(name) && !REQUEST_ONLY.containsKey(name) && !ignoredHeders.contains(name)
if (!IGNORED.containsHeader(name) && !REQUEST_ONLY.containsHeader(name) && !ignoredHeders.contains(name)
&& !requestOnlyHeaders.contains(name)) {
result.put(name, value);
}
@@ -97,7 +97,7 @@ public final class MessageHeaderUtils {
public static MessageHeaders fromHttp(HttpHeaders headers) {
Map<String, Object> map = new LinkedHashMap<>();
for (String name : headers.keySet()) {
for (String name : headers.headerNames()) {
Collection<?> values = multi(headers.get(name));
name = name.toLowerCase(Locale.ROOT);
Object value = values == null ? null : (values.size() == 1 ? values.iterator().next() : values);

View File

@@ -40,7 +40,7 @@ public class GatewayHttpTagsProvider implements GatewayTagsProvider {
// it needs to be checked for first, otherwise the delegate response
// who's status DIDN'T change, will be used
if (exchange.getResponse() instanceof AbstractServerHttpResponse) {
Integer statusInt = ((AbstractServerHttpResponse) exchange.getResponse()).getRawStatusCode();
Integer statusInt = ((AbstractServerHttpResponse) exchange.getResponse()).getStatusCode().value();
if (statusInt != null) {
status = String.valueOf(statusInt);
httpStatusCodeStr = status;

View File

@@ -84,7 +84,7 @@ public class GatewayMetricsFilterTests extends BaseWebClientTests {
// cannot use netty client since we cannot read custom http status
ResponseEntity<String> response = new TestRestTemplate().exchange(baseUri + "/headers", HttpMethod.POST,
new HttpEntity<>(headers), String.class);
assertThat(response.getStatusCodeValue()).isEqualTo(432);
assertThat(response.getStatusCode().value()).isEqualTo(432);
assertMetricsContainsTag("outcome", "CUSTOM");
assertMetricsContainsTag("status", "432");
assertMetricsContainsTag("routeId", "test_custom_http_status_metrics");

View File

@@ -92,7 +92,7 @@ class LoadBalancerServiceInstanceCookieFilterTests {
void shouldContinueChainWhenNoServiceInstanceResponse() {
ServerWebExchange filteredExchange = testFilter(exchange);
assertThat(filteredExchange.getRequest().getHeaders()).isEmpty();
assertThat(filteredExchange.getRequest().getHeaders().isEmpty()).isTrue();
}
@Test
@@ -104,7 +104,7 @@ class LoadBalancerServiceInstanceCookieFilterTests {
ServerWebExchange filteredExchange = testFilter(exchange);
assertThat(filteredExchange.getRequest().getHeaders()).isEmpty();
assertThat(filteredExchange.getRequest().getHeaders().isEmpty()).isTrue();
}
@Test
@@ -116,7 +116,7 @@ class LoadBalancerServiceInstanceCookieFilterTests {
ServerWebExchange filteredExchange = testFilter(exchange);
assertThat(filteredExchange.getRequest().getHeaders()).isEmpty();
assertThat(filteredExchange.getRequest().getHeaders().isEmpty()).isTrue();
}
private ServerWebExchange testFilter(ServerWebExchange exchange) {

View File

@@ -106,12 +106,12 @@ public class WebsocketRoutingFilterTests {
MockServerWebExchange exchange = MockServerWebExchange.from(request);
exchange.getAttributes().put(PRESERVE_HOST_HEADER_ATTRIBUTE, preserveHostHeader);
HttpHeaders httpHeaders = HttpHeadersFilter.filterRequest(filters, exchange);
assertThat(httpHeaders).doesNotContainKeys("Sec-Websocket-Something").containsKey("x-foo");
assertThat(httpHeaders.headerNames()).doesNotContain("Sec-Websocket-Something").contains("x-foo");
if (preserveHostHeader) {
assertThat(httpHeaders).containsKey(HOST);
assertThat(httpHeaders.headerNames()).contains(HOST);
}
else {
assertThat(httpHeaders).doesNotContainKeys(HOST);
assertThat(httpHeaders.headerNames()).doesNotContain(HOST);
}
}

View File

@@ -130,7 +130,7 @@ public class RequestRateLimiterGatewayFilterFactoryTests extends BaseWebClientTe
Mono<Void> response = filter.filter(exchange, this.filterChain);
response.subscribe(aVoid -> {
assertThat(exchange.getResponse().getStatusCode()).isEqualTo(expectedStatus);
assertThat(exchange.getResponse().getHeaders()).containsEntry("X-Tokens-Remaining",
assertThat(exchange.getResponse().getHeaders().asMultiValueMap()).containsEntry("X-Tokens-Remaining",
Collections.singletonList(tokensRemaining));
});

View File

@@ -43,7 +43,8 @@ class RewriteRequestParameterGatewayFilterFactoryIntegrationTests extends BaseWe
.expectStatus()
.isOk()
.expectBody()
.jsonPath("$.args.size", "fall2023");
.jsonPath("$.args.size")
.isEqualTo("fall2023");
}
@EnableAutoConfiguration

View File

@@ -80,9 +80,10 @@ public class SecureHeadersGatewayFilterFactoryUnitTests {
filter.filter(exchange, filterChain).block();
ServerHttpResponse response = exchange.getResponse();
assertThat(response.getHeaders()).containsOnlyKeys(X_XSS_PROTECTION_HEADER, STRICT_TRANSPORT_SECURITY_HEADER,
X_FRAME_OPTIONS_HEADER, X_CONTENT_TYPE_OPTIONS_HEADER, REFERRER_POLICY_HEADER,
CONTENT_SECURITY_POLICY_HEADER, X_DOWNLOAD_OPTIONS_HEADER, X_PERMITTED_CROSS_DOMAIN_POLICIES_HEADER);
assertThat(response.getHeaders().headerNames()).containsOnly(X_XSS_PROTECTION_HEADER,
STRICT_TRANSPORT_SECURITY_HEADER, X_FRAME_OPTIONS_HEADER, X_CONTENT_TYPE_OPTIONS_HEADER,
REFERRER_POLICY_HEADER, CONTENT_SECURITY_POLICY_HEADER, X_DOWNLOAD_OPTIONS_HEADER,
X_PERMITTED_CROSS_DOMAIN_POLICIES_HEADER);
}
@Test
@@ -98,9 +99,10 @@ public class SecureHeadersGatewayFilterFactoryUnitTests {
filter.filter(exchange, filterChain).block();
ServerHttpResponse response = captor.getValue().getResponse();
assertThat(response.getHeaders()).doesNotContainKeys(X_XSS_PROTECTION_HEADER, STRICT_TRANSPORT_SECURITY_HEADER,
X_FRAME_OPTIONS_HEADER, X_CONTENT_TYPE_OPTIONS_HEADER, REFERRER_POLICY_HEADER,
CONTENT_SECURITY_POLICY_HEADER, X_DOWNLOAD_OPTIONS_HEADER, X_PERMITTED_CROSS_DOMAIN_POLICIES_HEADER);
assertThat(response.getHeaders().headerNames()).doesNotContain(X_XSS_PROTECTION_HEADER,
STRICT_TRANSPORT_SECURITY_HEADER, X_FRAME_OPTIONS_HEADER, X_CONTENT_TYPE_OPTIONS_HEADER,
REFERRER_POLICY_HEADER, CONTENT_SECURITY_POLICY_HEADER, X_DOWNLOAD_OPTIONS_HEADER,
X_PERMITTED_CROSS_DOMAIN_POLICIES_HEADER);
}
@@ -117,9 +119,10 @@ public class SecureHeadersGatewayFilterFactoryUnitTests {
filter.filter(exchange, filterChain).block();
ServerHttpResponse response = exchange.getResponse();
assertThat(response.getHeaders()).containsKeys(X_XSS_PROTECTION_HEADER, STRICT_TRANSPORT_SECURITY_HEADER,
X_FRAME_OPTIONS_HEADER, X_CONTENT_TYPE_OPTIONS_HEADER, REFERRER_POLICY_HEADER,
CONTENT_SECURITY_POLICY_HEADER, X_DOWNLOAD_OPTIONS_HEADER, X_PERMITTED_CROSS_DOMAIN_POLICIES_HEADER);
assertThat(response.getHeaders().headerNames()).contains(X_XSS_PROTECTION_HEADER,
STRICT_TRANSPORT_SECURITY_HEADER, X_FRAME_OPTIONS_HEADER, X_CONTENT_TYPE_OPTIONS_HEADER,
REFERRER_POLICY_HEADER, CONTENT_SECURITY_POLICY_HEADER, X_DOWNLOAD_OPTIONS_HEADER,
X_PERMITTED_CROSS_DOMAIN_POLICIES_HEADER);
assertThat(response.getHeaders().get(STRICT_TRANSPORT_SECURITY_HEADER)).containsOnly("max-age=65535");
assertThat(response.getHeaders().get(REFERRER_POLICY_HEADER)).containsOnly("referrer");
@@ -184,7 +187,7 @@ public class SecureHeadersGatewayFilterFactoryUnitTests {
filter.filter(exchange, filterChain).block();
ServerHttpResponse response = captor.getValue().getResponse();
assertThat(response.getHeaders()).doesNotContainKeys(PERMISSIONS_POLICY_HEADER);
assertThat(response.getHeaders().headerNames()).doesNotContain(PERMISSIONS_POLICY_HEADER);
}
@Test
@@ -199,9 +202,10 @@ public class SecureHeadersGatewayFilterFactoryUnitTests {
ServerHttpResponse response = captor.getValue().getResponse();
assertThat(response.getHeaders()).containsKeys(X_XSS_PROTECTION_HEADER, STRICT_TRANSPORT_SECURITY_HEADER,
X_FRAME_OPTIONS_HEADER, X_CONTENT_TYPE_OPTIONS_HEADER, REFERRER_POLICY_HEADER,
CONTENT_SECURITY_POLICY_HEADER, X_DOWNLOAD_OPTIONS_HEADER, X_PERMITTED_CROSS_DOMAIN_POLICIES_HEADER);
assertThat(response.getHeaders().headerNames()).contains(X_XSS_PROTECTION_HEADER,
STRICT_TRANSPORT_SECURITY_HEADER, X_FRAME_OPTIONS_HEADER, X_CONTENT_TYPE_OPTIONS_HEADER,
REFERRER_POLICY_HEADER, CONTENT_SECURITY_POLICY_HEADER, X_DOWNLOAD_OPTIONS_HEADER,
X_PERMITTED_CROSS_DOMAIN_POLICIES_HEADER);
assertThat(response.getHeaders().get(PERMISSIONS_POLICY_HEADER))
.containsExactly(SecureHeadersProperties.PERMISSIONS_POLICY_HEADER_OPT_IN_DEFAULT);
@@ -235,7 +239,7 @@ public class SecureHeadersGatewayFilterFactoryUnitTests {
filter.filter(exchange, filterChain).block();
ServerHttpResponse response = captor.getValue().getResponse();
assertThat(response.getHeaders()).containsOnlyKeys(X_PERMITTED_CROSS_DOMAIN_POLICIES_HEADER,
assertThat(response.getHeaders().headerNames()).containsOnly(X_PERMITTED_CROSS_DOMAIN_POLICIES_HEADER,
PERMISSIONS_POLICY_HEADER);
}
@@ -255,7 +259,7 @@ public class SecureHeadersGatewayFilterFactoryUnitTests {
filter.filter(exchange, filterChain).block();
ServerHttpResponse response = exchange.getResponse();
assertThat(response.getHeaders()).containsOnlyKeys(X_XSS_PROTECTION_HEADER, X_FRAME_OPTIONS_HEADER,
assertThat(response.getHeaders().headerNames()).containsOnly(X_XSS_PROTECTION_HEADER, X_FRAME_OPTIONS_HEADER,
X_CONTENT_TYPE_OPTIONS_HEADER, REFERRER_POLICY_HEADER, CONTENT_SECURITY_POLICY_HEADER,
X_DOWNLOAD_OPTIONS_HEADER, X_PERMITTED_CROSS_DOMAIN_POLICIES_HEADER, PERMISSIONS_POLICY_HEADER);
assertThat(response.getHeaders().get(PERMISSIONS_POLICY_HEADER)).containsExactly("camera=*");

View File

@@ -66,7 +66,7 @@ public class SetStatusGatewayFilterFactoryTests extends BaseWebClientTests {
headers.set(HttpHeaders.HOST, "www.setcustomstatus.org");
ResponseEntity<String> response = new TestRestTemplate().exchange(baseUri + "/headers", HttpMethod.GET,
new HttpEntity<>(headers), String.class);
assertThat(response.getStatusCodeValue()).isEqualTo(432);
assertThat(response.getStatusCode().value()).isEqualTo(432);
// https://jira.spring.io/browse/SPR-16748
/*

View File

@@ -37,6 +37,7 @@ import org.springframework.context.annotation.Import;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
@@ -97,16 +98,17 @@ public class SpringCloudCircuitBreakerTestConfig {
@RequestMapping("/resetExchangeFallbackController")
public ResponseEntity<Map<String, String>> resetExchangeFallbackController(ServerWebExchange exchange) {
LinkedMultiValueMap<String, String> map = exchange.getRequest()
.getHeaders()
.headerSet()
.stream()
.filter(entry -> entry.getKey().startsWith("X-Test-"))
.map(entry -> new AbstractMap.SimpleEntry<>(entry.getKey() + "-fallback", entry.getValue()))
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue,
(list1, list2) -> Stream.concat(list1.stream(), list2.stream()).collect(Collectors.toList()),
LinkedMultiValueMap::new));
return ResponseEntity.status(HttpStatus.OK)
.headers((HttpHeaders) exchange.getRequest()
.getHeaders()
.entrySet()
.stream()
.filter(entry -> entry.getKey().startsWith("X-Test-"))
.map(entry -> new AbstractMap.SimpleEntry<>(entry.getKey() + "-fallback", entry.getValue()))
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue,
(list1, list2) -> Stream.concat(list1.stream(), list2.stream()).collect(Collectors.toList()),
HttpHeaders::new)))
.headers(new HttpHeaders(map))
.body(Collections.singletonMap("from", "resetExchangeFallbackController"));
}

View File

@@ -94,7 +94,7 @@ public class TokenRelayGatewayFilterFactoryTests {
public void emptyPrincipal() {
GatewayFilter filter = new TokenRelayGatewayFilterFactory(objectProvider).apply();
filter.filter(mockExchange, filterChain).block(TIMEOUT);
assertThat(request.getHeaders()).doesNotContainKeys(HttpHeaders.AUTHORIZATION);
assertThat(request.getHeaders().headerNames()).doesNotContain(HttpHeaders.AUTHORIZATION);
}
@Test
@@ -125,8 +125,8 @@ public class TokenRelayGatewayFilterFactoryTests {
verify(filterChain).filter(sweCaptor.capture());
ServerWebExchange mutatedServerWebExchange = sweCaptor.getValue();
assertThat(mutatedServerWebExchange.getRequest().getHeaders()).containsEntry(HttpHeaders.AUTHORIZATION,
Collections.singletonList("Bearer mytoken"));
assertThat(mutatedServerWebExchange.getRequest().getHeaders().asMultiValueMap())
.containsEntry(HttpHeaders.AUTHORIZATION, Collections.singletonList("Bearer mytoken"));
ArgumentCaptor<OAuth2AuthorizeRequest> authorizeRequestCaptor = ArgumentCaptor
.forClass(OAuth2AuthorizeRequest.class);
@@ -169,8 +169,8 @@ public class TokenRelayGatewayFilterFactoryTests {
verify(filterChain).filter(sweCaptor.capture());
ServerWebExchange mutatedServerWebExchange = sweCaptor.getValue();
assertThat(mutatedServerWebExchange.getRequest().getHeaders()).containsEntry(HttpHeaders.AUTHORIZATION,
Collections.singletonList("Bearer mytoken"));
assertThat(mutatedServerWebExchange.getRequest().getHeaders().asMultiValueMap())
.containsEntry(HttpHeaders.AUTHORIZATION, Collections.singletonList("Bearer mytoken"));
ArgumentCaptor<OAuth2AuthorizeRequest> authorizeRequestCaptor = ArgumentCaptor
.forClass(OAuth2AuthorizeRequest.class);
@@ -191,7 +191,7 @@ public class TokenRelayGatewayFilterFactoryTests {
GatewayFilter filter = new TokenRelayGatewayFilterFactory(objectProvider).apply();
filter.filter(exchange, filterChain).block(TIMEOUT);
assertThat(request.getHeaders()).doesNotContainKeys(HttpHeaders.AUTHORIZATION);
assertThat(request.getHeaders().headerNames()).doesNotContain(HttpHeaders.AUTHORIZATION);
}
@Test
@@ -223,8 +223,8 @@ public class TokenRelayGatewayFilterFactoryTests {
ArgumentCaptor<ServerWebExchange> sweCaptor = ArgumentCaptor.forClass(ServerWebExchange.class);
verify(filterChain).filter(sweCaptor.capture());
ServerWebExchange mutatedServerWebExchange = sweCaptor.getValue();
assertThat(mutatedServerWebExchange.getRequest().getHeaders()).containsEntry(HttpHeaders.AUTHORIZATION,
Collections.singletonList("Bearer mytoken"));
assertThat(mutatedServerWebExchange.getRequest().getHeaders().asMultiValueMap())
.containsEntry(HttpHeaders.AUTHORIZATION, Collections.singletonList("Bearer mytoken"));
ArgumentCaptor<OAuth2AuthorizeRequest> authorizeRequestCaptor = ArgumentCaptor
.forClass(OAuth2AuthorizeRequest.class);

View File

@@ -186,7 +186,8 @@ public class LocalResponseCacheGatewayFilterFactoryTests extends BaseWebClientTe
.header(CUSTOM_HEADER, "2")
.exchange()
.expectBody()
.jsonPath("$.headers." + CUSTOM_HEADER, customHeaderFromReq1));
.jsonPath("$.headers." + CUSTOM_HEADER)
.isEqualTo(customHeaderFromReq1));
}
@Test
@@ -211,7 +212,8 @@ public class LocalResponseCacheGatewayFilterFactoryTests extends BaseWebClientTe
.header("X-Request-Vary", "*")
.exchange()
.expectBody()
.jsonPath("$.headers." + CUSTOM_HEADER, "1");
.jsonPath("$.headers." + CUSTOM_HEADER)
.isEqualTo("1");
testClient.get()
.uri(uri)
.header("Host", "www.localresponsecache.org")
@@ -219,7 +221,8 @@ public class LocalResponseCacheGatewayFilterFactoryTests extends BaseWebClientTe
.header("X-Request-Vary", "*")
.exchange()
.expectBody()
.jsonPath("$.headers." + CUSTOM_HEADER, "2");
.jsonPath("$.headers." + CUSTOM_HEADER)
.isEqualTo("2");
}
@Test
@@ -325,7 +328,8 @@ public class LocalResponseCacheGatewayFilterFactoryTests extends BaseWebClientTe
.header(CUSTOM_HEADER, "2")
.exchange()
.expectBody()
.jsonPath("$.headers." + CUSTOM_HEADER, "2");
.jsonPath("$.headers." + CUSTOM_HEADER)
.isEqualTo("2");
}
@Test
@@ -348,7 +352,8 @@ public class LocalResponseCacheGatewayFilterFactoryTests extends BaseWebClientTe
.header(CUSTOM_HEADER, "2")
.exchange()
.expectBody()
.jsonPath("$.headers." + CUSTOM_HEADER, "2");
.jsonPath("$.headers." + CUSTOM_HEADER)
.isEqualTo("2");
}
@Test
@@ -390,7 +395,7 @@ public class LocalResponseCacheGatewayFilterFactoryTests extends BaseWebClientTe
.exchange()
.expectBody(Map.class)
.consumeWith(response -> {
assertThat(response.getResponseHeaders()).hasEntrySatisfying("Vary",
assertThat(response.getResponseHeaders().asMultiValueMap()).hasEntrySatisfying("Vary",
o -> assertThat(o).contains(varyHeader));
assertThat((Map) response.getResponseBody().get("headers")).containsEntry(nonVaryHeader,
expectedNonVaryResponse);

View File

@@ -54,7 +54,7 @@ class RemoveHeaderAfterCacheExchangeMutatorTest {
mutator.accept(inputExchange, cachedResponse);
assertThat(inputExchange.getResponse().getHeaders()).doesNotContainKey(HTTP_HEADER_TO_REMOVE)
assertThat(inputExchange.getResponse().getHeaders().asMultiValueMap()).doesNotContainKey(HTTP_HEADER_TO_REMOVE)
.containsEntry(CACHE_CONTROL, List.of("max-age=60"))
.containsEntry(CONTENT_TYPE, List.of("application/octet-stream"))
.hasSize(2);
@@ -70,7 +70,7 @@ class RemoveHeaderAfterCacheExchangeMutatorTest {
mutator.accept(inputExchange, cachedResponse);
assertThat(inputExchange.getResponse().getHeaders()).doesNotContainKey(HTTP_HEADER_TO_REMOVE)
assertThat(inputExchange.getResponse().getHeaders().asMultiValueMap()).doesNotContainKey(HTTP_HEADER_TO_REMOVE)
.doesNotContainKey(PRAGMA)
.doesNotContainKey(EXPIRES)
.containsEntry(CACHE_CONTROL, List.of("max-age=60"))
@@ -87,7 +87,8 @@ class RemoveHeaderAfterCacheExchangeMutatorTest {
mutator.accept(inputExchange, cachedResponse);
assertThat(inputExchange.getResponse().getHeaders()).containsEntry(CACHE_CONTROL, List.of("max-age=60"))
assertThat(inputExchange.getResponse().getHeaders().asMultiValueMap())
.containsEntry(CACHE_CONTROL, List.of("max-age=60"))
.containsEntry(CONTENT_TYPE, List.of("application/octet-stream"))
.hasSize(2);
}

View File

@@ -57,7 +57,7 @@ class SetResponseHeadersAfterCacheExchangeMutatorTest {
toTest.accept(inputExchange, cachedResponse);
Assertions.assertThat(inputExchange.getResponse().getHeaders())
Assertions.assertThat(inputExchange.getResponse().getHeaders().asMultiValueMap())
.containsEntry("X-Header-1", List.of("Value-cached"));
}
@@ -69,7 +69,7 @@ class SetResponseHeadersAfterCacheExchangeMutatorTest {
toTest.accept(inputExchange, cachedResponse);
Assertions.assertThat(inputExchange.getResponse().getHeaders()).doesNotContainKey("X-Header-1");
Assertions.assertThat(inputExchange.getResponse().getHeaders().headerNames()).doesNotContain("X-Header-1");
}
}

View File

@@ -297,7 +297,7 @@ public class ForwardedHeadersFilterTests {
HttpHeaders headers = filter.filter(request.getHeaders(), MockServerWebExchange.from(request));
assertThat(headers).doesNotContainKeys(FORWARDED_HEADER);
assertThat(headers.headerNames()).doesNotContain(FORWARDED_HEADER);
}
// verify that existing forwarded header is not forwarded if not trusted
@@ -313,7 +313,7 @@ public class ForwardedHeadersFilterTests {
HttpHeaders headers = filter.filter(request.getHeaders(), MockServerWebExchange.from(request));
assertThat(headers).containsKeys(FORWARDED_HEADER);
assertThat(headers.headerNames()).contains(FORWARDED_HEADER);
List<String> forwardedHeaders = headers.get(FORWARDED_HEADER);
Optional<String> filtered = forwardedHeaders.stream().filter(value -> value.contains("127.0.0.1")).findFirst();
assertThat(filtered).isEmpty();
@@ -332,7 +332,7 @@ public class ForwardedHeadersFilterTests {
HttpHeaders headers = filter.filter(request.getHeaders(), MockServerWebExchange.from(request));
assertThat(headers).containsKeys(FORWARDED_HEADER);
assertThat(headers.headerNames()).contains(FORWARDED_HEADER);
List<String> forwardedHeaders = headers.get(FORWARDED_HEADER);
Optional<String> filtered = forwardedHeaders.stream().filter(value -> value.contains("127.0.0.1")).findFirst();
assertThat(filtered).isEmpty();

View File

@@ -39,7 +39,7 @@ public class GRPCRequestHeadersFilterTest {
HttpHeaders headers = filter.filter(request.getHeaders(), MockServerWebExchange.from(request));
assertThat(headers).containsKeys("te");
assertThat(headers.headerNames()).contains("te");
assertThat(headers.getFirst("te")).isEqualTo("trailers");
}
@@ -54,7 +54,7 @@ public class GRPCRequestHeadersFilterTest {
HttpHeaders headers = filter.filter(request.getHeaders(), MockServerWebExchange.from(request));
assertThat(headers).doesNotContainKeys("te");
assertThat(headers.headerNames()).doesNotContain("te");
}
}

View File

@@ -50,7 +50,7 @@ public class HttpHeadersFilterMixedTypeTests {
HttpHeaders result = HttpHeadersFilter.filterRequest(Arrays.asList(filter1, filter2),
MockServerWebExchange.from(mockRequest));
assertThat(result).containsOnlyKeys("header1", "header3");
assertThat(result.headerNames()).containsOnly("header1", "header3");
}
private HttpHeadersFilter filterRemovingHeaders(Type type, String... headerNames) {

View File

@@ -46,7 +46,7 @@ public class HttpHeadersFilterTests {
HttpHeaders headers = HttpHeadersFilter.filterRequest(filters, MockServerWebExchange.from(request));
assertThat(headers).containsOnlyKeys("X-C");
assertThat(headers.headerNames()).containsOnly("X-C");
}
private HttpHeaders filter(HttpHeaders input, String keyToFilter) {

View File

@@ -98,7 +98,7 @@ public class RemoveHopByHopHeadersFilterTests {
Set<String> toRemove = new HashSet<>(HEADERS_REMOVED_ON_REQUEST);
toRemove.addAll(Arrays.asList(additionalHeaders));
assertThat(headers).doesNotContainKeys(toRemove.toArray(new String[0]));
assertThat(headers.headerNames()).doesNotContain(toRemove.toArray(new String[0]));
}
}

View File

@@ -35,7 +35,8 @@ public class TransferEncodingNormalizationHeadersFilterTests {
.header(HttpHeaders.CONTENT_LENGTH, "6");
HttpHeaders headers = testFilter(MockServerWebExchange.from(builder));
assertThat(headers).containsKey(HttpHeaders.CONTENT_LENGTH).doesNotContainKey(HttpHeaders.TRANSFER_ENCODING);
assertThat(headers.headerNames()).contains(HttpHeaders.CONTENT_LENGTH)
.doesNotContain(HttpHeaders.TRANSFER_ENCODING);
}
@Test
@@ -45,7 +46,8 @@ public class TransferEncodingNormalizationHeadersFilterTests {
.header(HttpHeaders.TRANSFER_ENCODING, "chunked");
HttpHeaders headers = testFilter(MockServerWebExchange.from(builder));
assertThat(headers).doesNotContainKey(HttpHeaders.CONTENT_LENGTH).containsKey(HttpHeaders.TRANSFER_ENCODING);
assertThat(headers.headerNames()).doesNotContain(HttpHeaders.CONTENT_LENGTH)
.contains(HttpHeaders.TRANSFER_ENCODING);
}
@Test
@@ -55,7 +57,8 @@ public class TransferEncodingNormalizationHeadersFilterTests {
.header(HttpHeaders.TRANSFER_ENCODING, "Chunked ");
HttpHeaders headers = testFilter(MockServerWebExchange.from(builder));
assertThat(headers).doesNotContainKey(HttpHeaders.CONTENT_LENGTH).containsKey(HttpHeaders.TRANSFER_ENCODING);
assertThat(headers.headerNames()).doesNotContain(HttpHeaders.CONTENT_LENGTH)
.contains(HttpHeaders.TRANSFER_ENCODING);
}
private HttpHeaders testFilter(MockServerWebExchange exchange) {

View File

@@ -63,8 +63,8 @@ public class XForwardedHeadersFilterTests {
HttpHeaders headers = filter.filter(request.getHeaders(), MockServerWebExchange.from(request));
assertThat(headers).doesNotContainKeys(X_FORWARDED_FOR_HEADER)
.containsKeys(X_FORWARDED_HOST_HEADER, X_FORWARDED_PORT_HEADER, X_FORWARDED_PROTO_HEADER);
assertThat(headers.headerNames()).doesNotContain(X_FORWARDED_FOR_HEADER)
.contains(X_FORWARDED_HOST_HEADER, X_FORWARDED_PORT_HEADER, X_FORWARDED_PROTO_HEADER);
assertThat(headers.getFirst(X_FORWARDED_HOST_HEADER)).isEqualTo("localhost:8080");
assertThat(headers.getFirst(X_FORWARDED_PORT_HEADER)).isEqualTo("8080");
@@ -82,8 +82,8 @@ public class XForwardedHeadersFilterTests {
HttpHeaders headers = filter.filter(request.getHeaders(), MockServerWebExchange.from(request));
assertThat(headers).containsKeys(X_FORWARDED_FOR_HEADER, X_FORWARDED_HOST_HEADER, X_FORWARDED_PORT_HEADER,
X_FORWARDED_PROTO_HEADER);
assertThat(headers.headerNames()).contains(X_FORWARDED_FOR_HEADER, X_FORWARDED_HOST_HEADER,
X_FORWARDED_PORT_HEADER, X_FORWARDED_PROTO_HEADER);
assertThat(headers.getFirst(X_FORWARDED_FOR_HEADER)).isEqualTo("10.0.0.1");
assertThat(headers.getFirst(X_FORWARDED_HOST_HEADER)).isEqualTo("localhost:8080");
@@ -102,8 +102,8 @@ public class XForwardedHeadersFilterTests {
HttpHeaders headers = filter.filter(request.getHeaders(), MockServerWebExchange.from(request));
assertThat(headers).containsKeys(X_FORWARDED_FOR_HEADER, X_FORWARDED_HOST_HEADER, X_FORWARDED_PORT_HEADER,
X_FORWARDED_PROTO_HEADER);
assertThat(headers.headerNames()).contains(X_FORWARDED_FOR_HEADER, X_FORWARDED_HOST_HEADER,
X_FORWARDED_PORT_HEADER, X_FORWARDED_PROTO_HEADER);
assertThat(headers.getFirst(X_FORWARDED_FOR_HEADER)).isEqualTo("10.0.0.1");
assertThat(headers.getFirst(X_FORWARDED_HOST_HEADER)).isEqualTo("localhost");
@@ -125,8 +125,8 @@ public class XForwardedHeadersFilterTests {
HttpHeaders headers = filter.filter(request.getHeaders(), MockServerWebExchange.from(request));
assertThat(headers).containsKeys(X_FORWARDED_FOR_HEADER, X_FORWARDED_HOST_HEADER, X_FORWARDED_PORT_HEADER,
X_FORWARDED_PROTO_HEADER);
assertThat(headers.headerNames()).contains(X_FORWARDED_FOR_HEADER, X_FORWARDED_HOST_HEADER,
X_FORWARDED_PORT_HEADER, X_FORWARDED_PROTO_HEADER);
assertThat(headers.getFirst(X_FORWARDED_FOR_HEADER)).isEqualTo("192.168.0.2,10.0.0.1");
assertThat(headers.getFirst(X_FORWARDED_HOST_HEADER)).isEqualTo("example.com,localhost:8080");
@@ -154,8 +154,8 @@ public class XForwardedHeadersFilterTests {
HttpHeaders headers = filter.filter(request.getHeaders(), MockServerWebExchange.from(request));
assertThat(headers).containsKeys(X_FORWARDED_FOR_HEADER, X_FORWARDED_HOST_HEADER, X_FORWARDED_PORT_HEADER,
X_FORWARDED_PROTO_HEADER, X_FORWARDED_PREFIX_HEADER);
assertThat(headers.headerNames()).contains(X_FORWARDED_FOR_HEADER, X_FORWARDED_HOST_HEADER,
X_FORWARDED_PORT_HEADER, X_FORWARDED_PROTO_HEADER, X_FORWARDED_PREFIX_HEADER);
assertThat(headers.getFirst(X_FORWARDED_FOR_HEADER)).isEqualTo("10.0.0.1");
assertThat(headers.getFirst(X_FORWARDED_HOST_HEADER)).isEqualTo("localhost:8080");
@@ -184,7 +184,7 @@ public class XForwardedHeadersFilterTests {
HttpHeaders headers = filter.filter(request.getHeaders(), exchange);
assertThat(headers).containsKeys(X_FORWARDED_PREFIX_HEADER);
assertThat(headers.headerNames()).contains(X_FORWARDED_PREFIX_HEADER);
assertThat(headers.getFirst(X_FORWARDED_PREFIX_HEADER)).isEqualTo("/prefix");
}
@@ -210,7 +210,7 @@ public class XForwardedHeadersFilterTests {
HttpHeaders headers = filter.filter(request.getHeaders(), exchange);
assertThat(headers).containsKeys(X_FORWARDED_PREFIX_HEADER);
assertThat(headers.headerNames()).contains(X_FORWARDED_PREFIX_HEADER);
assertThat(headers.getFirst(X_FORWARDED_PREFIX_HEADER)).isEqualTo("/resource");
}
@@ -260,7 +260,7 @@ public class XForwardedHeadersFilterTests {
HttpHeaders headers = filter.filter(request.getHeaders(), exchange);
assertThat(headers).isEmpty();
assertThat(headers.isEmpty()).isTrue();
}
@Test
@@ -286,7 +286,7 @@ public class XForwardedHeadersFilterTests {
HttpHeaders headers = filter.filter(request.getHeaders(), exchange);
assertThat(headers).isEmpty();
assertThat(headers.isEmpty()).isTrue();
}
@Test
@@ -304,7 +304,7 @@ public class XForwardedHeadersFilterTests {
HttpHeaders headers = filter.filter(request.getHeaders(), MockServerWebExchange.from(request));
assertThat(headers).isEmpty();
assertThat(headers.isEmpty()).isTrue();
}
@Test
@@ -318,7 +318,7 @@ public class XForwardedHeadersFilterTests {
HttpHeaders headers = filter.filter(request.getHeaders(), MockServerWebExchange.from(request));
assertThat(headers).containsKeys(X_FORWARDED_FOR_HEADER);
assertThat(headers.headerNames()).contains(X_FORWARDED_FOR_HEADER);
assertThat(headers.getFirst(X_FORWARDED_FOR_HEADER)).isEqualTo("10.0.0.1,10.0.0.1");
}
@@ -334,7 +334,7 @@ public class XForwardedHeadersFilterTests {
HttpHeaders headers = filter.filter(request.getHeaders(), MockServerWebExchange.from(request));
assertThat(headers).doesNotContainKeys(X_FORWARDED_PROTO_HEADER, X_FORWARDED_HOST_HEADER);
assertThat(headers.headerNames()).doesNotContain(X_FORWARDED_PROTO_HEADER, X_FORWARDED_HOST_HEADER);
}
@Test
@@ -375,8 +375,8 @@ public class XForwardedHeadersFilterTests {
HttpHeaders headers = filter.filter(request.getHeaders(), MockServerWebExchange.from(request));
assertThat(headers).doesNotContainKeys(X_FORWARDED_FOR_HEADER, X_FORWARDED_HOST_HEADER, X_FORWARDED_PORT_HEADER,
X_FORWARDED_PROTO_HEADER);
assertThat(headers.headerNames()).doesNotContain(X_FORWARDED_FOR_HEADER, X_FORWARDED_HOST_HEADER,
X_FORWARDED_PORT_HEADER, X_FORWARDED_PROTO_HEADER);
}
// : verify that existing x-forwarded-* headers are not forwarded
@@ -394,8 +394,8 @@ public class XForwardedHeadersFilterTests {
HttpHeaders headers = filter.filter(request.getHeaders(), MockServerWebExchange.from(request));
assertThat(headers).containsKeys(X_FORWARDED_FOR_HEADER, X_FORWARDED_HOST_HEADER, X_FORWARDED_PORT_HEADER,
X_FORWARDED_PROTO_HEADER);
assertThat(headers.headerNames()).contains(X_FORWARDED_FOR_HEADER, X_FORWARDED_HOST_HEADER,
X_FORWARDED_PORT_HEADER, X_FORWARDED_PROTO_HEADER);
assertThat(headers.getFirst(X_FORWARDED_FOR_HEADER)).doesNotContain("127.0.0.1")
.contains("10.0.0.1", "10.0.0.10");
@@ -412,8 +412,8 @@ public class XForwardedHeadersFilterTests {
HttpHeaders headers = filter.filter(request.getHeaders(), MockServerWebExchange.from(request));
assertThat(headers).containsKeys(X_FORWARDED_FOR_HEADER, X_FORWARDED_HOST_HEADER, X_FORWARDED_PORT_HEADER,
X_FORWARDED_PROTO_HEADER);
assertThat(headers.headerNames()).contains(X_FORWARDED_FOR_HEADER, X_FORWARDED_HOST_HEADER,
X_FORWARDED_PORT_HEADER, X_FORWARDED_PROTO_HEADER);
assertThat(headers.getFirst(X_FORWARDED_FOR_HEADER)).doesNotContain("127.0.0.1");
}

View File

@@ -111,7 +111,8 @@ class B3BraveObservedHttpHeadersFilterTests {
headers = responseHttpHeadersFilter.filter(headers, exchange);
// then
assertThat(headers).containsOnlyKeys("X-A", "b3").doesNotContainEntry("b3", request.getHeaders().get("b3"));
assertThat(headers.asMultiValueMap()).containsOnlyKeys("X-A", "b3")
.doesNotContainEntry("b3", request.getHeaders().get("b3"));
assertThat(headers.get("b3").get(0)).matches("^" + context.traceId() + "-(.*)-1-" + context.spanId() + "$");
List<FinishedSpan> finishedSpans = testSpanHandler.spans()
.stream()

View File

@@ -70,7 +70,7 @@ class GatewayPropagatingSenderTracingObservationHandlerTests {
handler.onStart(gatewayContext);
then(headers).doesNotContainKeys("foo", "bar")
then(headers.asMultiValueMap()).doesNotContainKeys("foo", "bar")
.containsEntry("baz", Collections.singletonList("baz value"))
.containsEntry("remote", Collections.singletonList("remote value"));
}

View File

@@ -86,7 +86,7 @@ public class ObservedHttpHeadersFilterTests extends SampleTestRunner {
// then
assertThat((String) exchange.getAttribute(ObservedResponseHttpHeadersFilter.OBSERVATION_STOPPED))
.isNotNull();
assertThat(headers).containsEntry("X-A", Collections.singletonList("aValue"))
assertThat(headers.asMultiValueMap()).containsEntry("X-A", Collections.singletonList("aValue"))
.containsEntry("X-B3-Sampled", Collections.singletonList("1"))
.containsEntry("X-B3-TraceId", Collections.singletonList(context.traceId()))
.doesNotContainEntry("X-B3-SpanId", Collections.singletonList(context.spanId()))

View File

@@ -119,9 +119,9 @@ public class ServerWebExchangeUtilsTests {
.as("exchange attributes")
.doesNotContainKey(GATEWAY_PREDICATE_PATH_CONTAINER_ATTR);
Assertions.assertThat(exchange.getRequest().getHeaders())
Assertions.assertThat(exchange.getRequest().getHeaders().headerNames())
.as("request headers")
.doesNotContainKey(HttpHeaders.ORIGIN);
.doesNotContain(HttpHeaders.ORIGIN);
}));
}

View File

@@ -44,6 +44,7 @@ import org.springframework.http.codec.multipart.FilePart;
import org.springframework.http.codec.multipart.Part;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.util.FileCopyUtils;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PatchMapping;
@@ -175,14 +176,15 @@ public class HttpBinCompatibleController {
@RequestMapping(value = "/responseheaders/{status}", method = { RequestMethod.GET, RequestMethod.POST })
public ResponseEntity<Map<String, Object>> responseHeaders(@PathVariable int status, ServerWebExchange exchange) {
HttpHeaders httpHeaders = exchange.getRequest()
LinkedMultiValueMap<String, String> map = exchange.getRequest()
.getHeaders()
.headerSet()
.stream()
.filter(entry -> entry.getKey().startsWith("X-Test-"))
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue,
(list1, list2) -> Stream.concat(list1.stream(), list2.stream()).collect(Collectors.toList()),
HttpHeaders::new));
LinkedMultiValueMap::new));
HttpHeaders httpHeaders = new HttpHeaders(map);
return ResponseEntity.status(status).headers(httpHeaders).body(Collections.singletonMap("status", status));
}

View File

@@ -58,7 +58,7 @@ public class HttpStatusTests extends BaseWebClientTests {
@Test
void nonStandardCodeWorks() {
ResponseEntity<String> response = new TestRestTemplate().getForEntity(baseUri + "/status/432", String.class);
assertThat(response.getStatusCodeValue()).isEqualTo(432);
assertThat(response.getStatusCode().value()).isEqualTo(432);
assertThat(response.getBody()).isEqualTo("Failed with 432");
/*

View File

@@ -366,7 +366,7 @@ public class WebSocketIntegrationTests {
@Override
public Mono<Void> handle(WebSocketSession session) {
HttpHeaders headers = session.getHandshakeInfo().getHeaders();
if (!headers.containsKey("my-header")) {
if (!headers.containsHeader("my-header")) {
return Mono.error(new IllegalStateException("Missing my-header"));
}
String payload = "my-header:" + headers.getFirst("my-header");

View File

@@ -11,7 +11,7 @@
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-gateway</artifactId>
<version>4.3.1-SNAPSHOT</version>
<version>5.0.0-SNAPSHOT</version>
<relativePath>..</relativePath>
</parent>

View File

@@ -400,13 +400,13 @@ public class ProxyExchange<T> {
private void addHeaders(HttpHeaders headers, HttpHeaders toAdd) {
Set<String> filteredKeys = filterHeaderKeys(toAdd);
filteredKeys.stream()
.filter(key -> !headers.containsKey(key))
.filter(key -> !headers.containsHeader(key))
.forEach(header -> headers.addAll(header, toAdd.get(header)));
}
private Set<String> filterHeaderKeys(HttpHeaders headers) {
final Set<String> excludedHeaders = this.excluded != null ? this.excluded : Collections.emptySet();
return headers.keySet()
return headers.headerNames()
.stream()
.filter(header -> !excludedHeaders.contains(header.toLowerCase(Locale.ROOT)))
.collect(Collectors.toSet());

View File

@@ -479,7 +479,7 @@ public class ProductionConfigurationTests {
@GetMapping("/headers")
public Map<String, List<String>> headers(@RequestHeader HttpHeaders headers) {
return headers;
return headers.asMultiValueMap();
}
@DeleteMapping("/foos/{id}/no-body")

View File

@@ -6,7 +6,7 @@
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-gateway</artifactId>
<version>4.3.1-SNAPSHOT</version>
<version>5.0.0-SNAPSHOT</version>
<relativePath>..</relativePath> <!-- lookup parent from repository -->
</parent>
<artifactId>spring-cloud-starter-gateway-mvc</artifactId>

View File

@@ -6,7 +6,7 @@
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-gateway</artifactId>
<version>4.3.1-SNAPSHOT</version>
<version>5.0.0-SNAPSHOT</version>
<relativePath>..</relativePath> <!-- lookup parent from repository -->
</parent>
<artifactId>spring-cloud-starter-gateway-server-webflux</artifactId>

View File

@@ -6,7 +6,7 @@
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-gateway</artifactId>
<version>4.3.1-SNAPSHOT</version>
<version>5.0.0-SNAPSHOT</version>
<relativePath>..</relativePath> <!-- lookup parent from repository -->
</parent>
<artifactId>spring-cloud-starter-gateway-server-webmvc</artifactId>

View File

@@ -6,7 +6,7 @@
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-gateway</artifactId>
<version>4.3.1-SNAPSHOT</version>
<version>5.0.0-SNAPSHOT</version>
<relativePath>..</relativePath> <!-- lookup parent from repository -->
</parent>
<artifactId>spring-cloud-starter-gateway</artifactId>