Migrate server-webmvc properties to new namespace (#3782)

* Migrate server-webmvc properties to new namespace

Currently, prefix is spring.cloud.gateway.mvc, the new convention is spring.cloud.gateway.server.webmvc

See gh-3363

Fixes gh-3647

* Properties migration for server-webmvc

Migrate from spring.cloud.gateway.mvc to spring.cloud.gateway.server.webmvc

Fixes gh-3647

* formatting

* Fixes test properties

* Fixes test properties
This commit is contained in:
Spencer Gibb
2025-05-05 18:50:30 -04:00
committed by GitHub
parent 0d1cf2774c
commit 092492ab28
8 changed files with 676 additions and 27 deletions

View File

@@ -36,7 +36,7 @@ public class GatewayMvcProperties {
/**
* Properties prefix.
*/
public static final String PREFIX = "spring.cloud.gateway.mvc";
public static final String PREFIX = "spring.cloud.gateway.server.webmvc";
/**
* List of Routes.

View File

@@ -0,0 +1,193 @@
/*
* Copyright 2013-2025 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.gateway.server.mvc.config;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.boot.context.event.ApplicationFailedEvent;
import org.springframework.boot.context.event.ApplicationPreparedEvent;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.boot.context.event.SpringApplicationEvent;
import org.springframework.boot.context.properties.source.ConfigurationProperty;
import org.springframework.boot.context.properties.source.ConfigurationPropertyName;
import org.springframework.boot.context.properties.source.ConfigurationPropertySource;
import org.springframework.boot.context.properties.source.ConfigurationPropertySources;
import org.springframework.boot.context.properties.source.IterableConfigurationPropertySource;
import org.springframework.boot.env.OriginTrackedMapPropertySource;
import org.springframework.boot.origin.Origin;
import org.springframework.boot.origin.OriginTrackedValue;
import org.springframework.boot.origin.PropertySourceOrigin;
import org.springframework.boot.origin.TextResourceOrigin;
import org.springframework.context.ApplicationListener;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.PropertySource;
import org.springframework.util.ClassUtils;
import org.springframework.util.LinkedMultiValueMap;
class GatewayServerWebMvcPropertiesMigrationListener implements ApplicationListener<SpringApplicationEvent> {
private static final Log logger = LogFactory.getLog(GatewayServerWebMvcPropertiesMigrationListener.class);
private static final String PROPERTIES_MIGRATOR_CLASS = "org.springframework.boot.context.properties.migrator.PropertiesMigrationListener";
private static final String DEPRECATED_ROOT = "spring.cloud.gateway.mvc";
private static final String DEPRECATED_ROUTES_LIST_KEY = DEPRECATED_ROOT + ".routes";
private static final String DEPRECATED_ROUTES_MAP_KEY = DEPRECATED_ROOT + ".routes-map";
private static final String DEPRECATED_ROUTESMAP_KEY = DEPRECATED_ROOT + ".routesMap";
private static final String GATEWAY_PROPERTY_SOURCE_PREFIX = "migrategatewaymvc";
private static final String NEW_ROUTES_LIST_KEY = GatewayMvcProperties.PREFIX + ".routes";
private static final String NEW_ROUTES_MAP_KEY = GatewayMvcProperties.PREFIX + ".routes-map";
private final List<Migration> routesMigrations = new ArrayList<>();
@Override
public void onApplicationEvent(SpringApplicationEvent event) {
// only run if spring-boot-properties-migrator is on the classpath
if (!ClassUtils.isPresent(PROPERTIES_MIGRATOR_CLASS, null)) {
return;
}
if (event instanceof ApplicationPreparedEvent preparedEvent) {
onApplicationPreparedEvent(preparedEvent);
}
if (event instanceof ApplicationReadyEvent || event instanceof ApplicationFailedEvent) {
logLegacyPropertiesReport();
}
}
private void onApplicationPreparedEvent(ApplicationPreparedEvent event) {
// find deprecated keys
ConfigurableEnvironment env = event.getApplicationContext().getEnvironment();
ConfigurationPropertySources.get(env).forEach(propertySource -> {
routesMigrations.addAll(migrate(env, propertySource, GATEWAY_PROPERTY_SOURCE_PREFIX + "routes-",
DEPRECATED_ROUTES_LIST_KEY, NEW_ROUTES_LIST_KEY));
routesMigrations.addAll(migrate(env, propertySource, GATEWAY_PROPERTY_SOURCE_PREFIX + "routes-map-",
DEPRECATED_ROUTES_MAP_KEY, NEW_ROUTES_MAP_KEY));
routesMigrations.addAll(migrate(env, propertySource, GATEWAY_PROPERTY_SOURCE_PREFIX + "routesMap-",
DEPRECATED_ROUTES_MAP_KEY, NEW_ROUTES_MAP_KEY));
});
}
private List<Migration> migrate(ConfigurableEnvironment env, ConfigurationPropertySource propertySource,
String propertySourcePrefix, String deprecatedKey, String newKeyPrefix) {
List<Migration> migrations = new ArrayList<>();
if (propertySource instanceof IterableConfigurationPropertySource iterableSource) {
ConfigurationPropertyName routesParentName = ConfigurationPropertyName.of(deprecatedKey);
List<ConfigurationPropertyName> matchingConfigProps = iterableSource.filter(n -> {
if (n.getNumberOfElements() < routesParentName.getNumberOfElements()) {
return false;
}
ConfigurationPropertyName chop = n.chop(routesParentName.getNumberOfElements());
return routesParentName.equals(chop);
}).stream().toList();
if (!matchingConfigProps.isEmpty()) {
String originalPropertySourceName;
if (propertySource.getUnderlyingSource() instanceof PropertySource<?> underlyingSource) {
originalPropertySourceName = underlyingSource.getName();
}
else {
originalPropertySourceName = propertySource.getUnderlyingSource().toString();
}
String newPropertySourceName = propertySourcePrefix + originalPropertySourceName;
Map<String, OriginTrackedValue> content = new LinkedHashMap<>();
// migrate to new keys
for (ConfigurationPropertyName originalPropertyName : matchingConfigProps) {
ConfigurationPropertyName suffix = originalPropertyName
.subName(routesParentName.getNumberOfElements());
ConfigurationPropertyName newProperty = ConfigurationPropertyName.of(newKeyPrefix).append(suffix);
ConfigurationProperty configurationProperty = propertySource
.getConfigurationProperty(originalPropertyName);
Object value = configurationProperty.getValue();
OriginTrackedValue originTrackedValue = OriginTrackedValue.of(value,
configurationProperty.getOrigin());
content.put(newProperty.toString(), originTrackedValue);
migrations.add(new Migration(originalPropertySourceName, originalPropertyName,
configurationProperty, newProperty));
}
env.getPropertySources()
.addBefore(originalPropertySourceName,
new OriginTrackedMapPropertySource(newPropertySourceName, content));
}
}
return migrations;
}
private void logLegacyPropertiesReport() {
// log warnings
if (!routesMigrations.isEmpty()) {
LinkedMultiValueMap<String, Migration> content = new LinkedMultiValueMap<>();
routesMigrations.forEach(migration -> content.add(migration.originalPropertySourceName(), migration));
StringBuilder report = new StringBuilder();
report.append(String
.format("%nThe use of configuration keys that have been renamed was found in the environment:%n%n"));
content.forEach((name, properties) -> {
report.append(String.format("Property source '%s':%n", name));
// properties.sort(PropertyMigration.COMPARATOR);
properties.forEach((property) -> {
ConfigurationPropertyName originalPropertyName = property.originalPropertyName();
report.append(String.format("\tKey: %s%n", originalPropertyName));
Integer lineNumber = property.determineLineNumber();
if (lineNumber != null) {
report.append(String.format("\t\tLine: %d%n", lineNumber));
}
report.append(String.format("\t\tReplacement: %s%n", property.newProperty().toString()));
});
report.append(String.format("%n"));
});
report.append(String.format("%n"));
report.append("Each configuration key has been temporarily mapped to its "
+ "replacement for your convenience. To silence this warning, please "
+ "update your configuration to use the new keys.");
report.append(String.format("%n"));
logger.warn(report.toString());
}
}
private record Migration(String originalPropertySourceName, ConfigurationPropertyName originalPropertyName,
ConfigurationProperty originalProperty, ConfigurationPropertyName newProperty) {
private Integer determineLineNumber() {
Origin origin = originalProperty.getOrigin();
if (origin instanceof PropertySourceOrigin propertySourceOrigin) {
origin = propertySourceOrigin.getOrigin();
}
if (origin instanceof TextResourceOrigin textOrigin) {
if (textOrigin.getLocation() != null) {
return textOrigin.getLocation().getLine() + 1;
}
}
return null;
}
}
}

View File

@@ -1,46 +1,370 @@
{
"properties": [
{
"name": "spring.cloud.gateway.mvc.form-filter.enabled",
"name": "spring.cloud.gateway.server.webmvc.form-filter.enabled",
"type": "java.lang.Boolean",
"description": "Enables the form-filter.",
"defaultValue": "true"
},
{
"name": "spring.cloud.gateway.mvc.forwarded-request-headers-filter.enabled",
"name": "spring.cloud.gateway.server.webmvc.forwarded-request-headers-filter.enabled",
"type": "java.lang.Boolean",
"description": "Enables the forwarded-request-headers-filter.",
"defaultValue": "true"
},
{
"name": "spring.cloud.gateway.mvc.remove-content-length-request-headers-filter.enabled",
"name": "spring.cloud.gateway.server.webmvc.remove-content-length-request-headers-filter.enabled",
"type": "java.lang.Boolean",
"description": "Enables the remove-content-length-request-headers-filter.",
"defaultValue": "true"
},
{
"name": "spring.cloud.gateway.mvc.remove-hop-by-hop-request-headers-filter.enabled",
"name": "spring.cloud.gateway.server.webmvc.remove-hop-by-hop-request-headers-filter.enabled",
"type": "java.lang.Boolean",
"description": "Enables the forwarded-request-headers-filter.",
"description": "Enables the remove-hop-by-hop-request-headers-filter.",
"defaultValue": "true"
},
{
"name": "spring.cloud.gateway.mvc.remove-hop-by-hop-response-headers-filter.enabled",
"name": "spring.cloud.gateway.server.webmvc.remove-hop-by-hop-response-headers-filter.enabled",
"type": "java.lang.Boolean",
"description": "Enables the forwarded-request-headers-filter.",
"description": "Enables the remove-hop-by-hop-response-headers-filter.",
"defaultValue": "true"
},
{
"name": "spring.cloud.gateway.mvc.transfer-encoding-normalization-request-headers-filter.enabled",
"name": "spring.cloud.gateway.server.webmvc.remove-http2-status-response-headers-filter.enabled",
"type": "java.lang.Boolean",
"description": "Enables the remove-http2-status-response-headers-filter.",
"defaultValue": "true"
},
{
"name": "spring.cloud.gateway.server.webmvc.transfer-encoding-normalization-request-headers-filter.enabled",
"type": "java.lang.Boolean",
"description": "Enables the transfer-encoding-normalization-request-headers-filter.",
"defaultValue": "true"
},
{
"name": "spring.cloud.gateway.mvc.weight-calculator-filter.enabled",
"name": "spring.cloud.gateway.server.webmvc.weight-calculator-filter.enabled",
"type": "java.lang.Boolean",
"description": "Enables the weight-calculator-filter.",
"defaultValue": "true"
},
{
"name": "spring.cloud.gateway.mvc.form-filter.enabled",
"type": "java.lang.Boolean",
"description": "Enables the form-filter.",
"defaultValue": "true",
"deprecated": true,
"deprecation": {
"replacement": "spring.cloud.gateway.server.webmvc.form-filter.enabled",
"since": "4.3.0"
}
},
{
"name": "spring.cloud.gateway.mvc.forwarded-request-headers-filter.enabled",
"type": "java.lang.Boolean",
"description": "Enables the forwarded-request-headers-filter.",
"defaultValue": "true",
"deprecated": true,
"deprecation": {
"replacement": "spring.cloud.gateway.server.webmvc.forwarded-request-headers-filter.enabled",
"since": "4.3.0"
}
},
{
"name": "spring.cloud.gateway.mvc.remove-content-length-request-headers-filter.enabled",
"type": "java.lang.Boolean",
"description": "Enables the remove-content-length-request-headers-filter.",
"defaultValue": "true",
"deprecated": true,
"deprecation": {
"replacement": "spring.cloud.gateway.server.webmvc.remove-content-length-request-headers-filter.enabled",
"since": "4.3.0"
}
},
{
"name": "spring.cloud.gateway.mvc.remove-hop-by-hop-request-headers-filter.enabled",
"type": "java.lang.Boolean",
"description": "Enables the remove-hop-by-hop-request-headers-filter.",
"defaultValue": "true",
"deprecated": true,
"deprecation": {
"replacement": "spring.cloud.gateway.server.webmvc.remove-hop-by-hop-request-headers-filter.enabled",
"since": "4.3.0"
}
},
{
"name": "spring.cloud.gateway.mvc.remove-hop-by-hop-response-headers-filter.enabled",
"type": "java.lang.Boolean",
"description": "Enables the remove-hop-by-hop-response-headers-filter.",
"defaultValue": "true",
"deprecated": true,
"deprecation": {
"replacement": "spring.cloud.gateway.server.webmvc.remove-hop-by-hop-response-headers-filter.enabled",
"since": "4.3.0"
}
},
{
"name": "spring.cloud.gateway.mvc.remove-http2-status-response-headers-filter.enabled",
"type": "java.lang.Boolean",
"description": "Enables the remove-http2-status-response-headers-filter.",
"defaultValue": "true",
"deprecated": true,
"deprecation": {
"replacement": "spring.cloud.gateway.server.webmvc.remove-http2-status-response-headers-filter.enabled",
"since": "4.3.0"
}
},
{
"name": "spring.cloud.gateway.mvc.routes",
"type": "java.util.List<org.springframework.cloud.gateway.server.mvc.config.RouteProperties>",
"description": "List of Routes.",
"deprecated": true,
"deprecation": {
"replacement": "spring.cloud.gateway.server.webmvc.routes",
"since": "4.3.0"
}
},
{
"name": "spring.cloud.gateway.mvc.routes-map",
"type": "java.util.LinkedHashMap<java.lang.String,org.springframework.cloud.gateway.server.mvc.config.RouteProperties>",
"description": "Map of Routes.",
"sourceType": "org.springframework.cloud.gateway.server.mvc.config.GatewayMvcProperties",
"deprecated": true,
"deprecation": {
"replacement": "spring.cloud.gateway.server.webmvc.routes-map",
"since": "4.3.0"
}
},
{
"name": "spring.cloud.gateway.mvc.streaming-buffer-size",
"type": "java.lang.Integer",
"description": "Buffer size for streaming media mime-types.",
"sourceType": "org.springframework.cloud.gateway.server.mvc.config.GatewayMvcProperties",
"defaultValue": 16384,
"deprecated": true,
"deprecation": {
"replacement": "spring.cloud.gateway.server.webmvc.streaming-buffer-size",
"since": "4.3.0"
}
},
{
"name": "spring.cloud.gateway.mvc.streaming-media-types",
"type": "java.util.List<org.springframework.http.MediaType>",
"description": "Mime-types that are streaming.",
"sourceType": "org.springframework.cloud.gateway.server.mvc.config.GatewayMvcProperties",
"deprecated": true,
"deprecation": {
"replacement": "spring.cloud.gateway.server.webmvc.streaming-media-types",
"since": "4.3.0"
}
},
{
"name": "spring.cloud.gateway.mvc.transfer-encoding-normalization-request-headers-filter.enabled",
"type": "java.lang.Boolean",
"description": "Enables the transfer-encoding-normalization-request-headers-filter.",
"defaultValue": "true",
"deprecated": true,
"deprecation": {
"replacement": "spring.cloud.gateway.server.webmvc.transfer-encoding-normalization-request-headers-filter.enabled",
"since": "4.3.0"
}
},
{
"name": "spring.cloud.gateway.mvc.weight-calculator-filter.enabled",
"type": "java.lang.Boolean",
"description": "Enables the weight-calculator-filter.",
"defaultValue": "true",
"deprecated": true,
"deprecation": {
"replacement": "spring.cloud.gateway.server.webmvc.weight-calculator-filter.enabled",
"since": "4.3.0"
}
},
{
"name": "spring.cloud.gateway.mvc.x-forwarded-request-headers-filter.enabled",
"type": "java.lang.Boolean",
"description": "If the XForwardedHeadersFilter is enabled.",
"sourceType": "org.springframework.cloud.gateway.server.mvc.filter.XForwardedRequestHeadersFilterProperties",
"defaultValue": true,
"deprecated": true,
"deprecation": {
"replacement": "spring.cloud.gateway.server.webmvc.x-forwarded-request-headers-filter.enabled",
"since": "4.3.0"
}
},
{
"name": "spring.cloud.gateway.mvc.x-forwarded-request-headers-filter.for-append",
"type": "java.lang.Boolean",
"description": "If appending X-Forwarded-For as a list is enabled.",
"sourceType": "org.springframework.cloud.gateway.server.mvc.filter.XForwardedRequestHeadersFilterProperties",
"defaultValue": true,
"deprecated": true,
"deprecation": {
"replacement": "spring.cloud.gateway.server.webmvc.x-forwarded-request-headers-filter.for-append",
"since": "4.3.0"
}
},
{
"name": "spring.cloud.gateway.mvc.x-forwarded-request-headers-filter.for-enabled",
"type": "java.lang.Boolean",
"description": "If X-Forwarded-For is enabled.",
"sourceType": "org.springframework.cloud.gateway.server.mvc.filter.XForwardedRequestHeadersFilterProperties",
"defaultValue": true,
"deprecated": true,
"deprecation": {
"replacement": "spring.cloud.gateway.server.webmvc.x-forwarded-request-headers-filter.for-enabled",
"since": "4.3.0"
}
},
{
"name": "spring.cloud.gateway.mvc.x-forwarded-request-headers-filter.host-append",
"type": "java.lang.Boolean",
"description": "If appending X-Forwarded-Host as a list is enabled.",
"sourceType": "org.springframework.cloud.gateway.server.mvc.filter.XForwardedRequestHeadersFilterProperties",
"defaultValue": true,
"deprecated": true,
"deprecation": {
"replacement": "spring.cloud.gateway.server.webmvc.x-forwarded-request-headers-filter.host-append",
"since": "4.3.0"
}
},
{
"name": "spring.cloud.gateway.mvc.x-forwarded-request-headers-filter.host-enabled",
"type": "java.lang.Boolean",
"description": "If X-Forwarded-Host is enabled.",
"sourceType": "org.springframework.cloud.gateway.server.mvc.filter.XForwardedRequestHeadersFilterProperties",
"defaultValue": true,
"deprecated": true,
"deprecation": {
"replacement": "spring.cloud.gateway.server.webmvc.x-forwarded-request-headers-filter.host-enabled",
"since": "4.3.0"
}
},
{
"name": "spring.cloud.gateway.mvc.x-forwarded-request-headers-filter.order",
"type": "java.lang.Integer",
"description": "The order of the XForwardedHeadersFilter.",
"sourceType": "org.springframework.cloud.gateway.server.mvc.filter.XForwardedRequestHeadersFilterProperties",
"defaultValue": 0,
"deprecated": true,
"deprecation": {
"replacement": "spring.cloud.gateway.server.webmvc.x-forwarded-request-headers-filter.order",
"since": "4.3.0"
}
},
{
"name": "spring.cloud.gateway.mvc.x-forwarded-request-headers-filter.port-append",
"type": "java.lang.Boolean",
"description": "If appending X-Forwarded-Port as a list is enabled.",
"sourceType": "org.springframework.cloud.gateway.server.mvc.filter.XForwardedRequestHeadersFilterProperties",
"defaultValue": true,
"deprecated": true,
"deprecation": {
"replacement": "spring.cloud.gateway.server.webmvc.x-forwarded-request-headers-filter.port-append",
"since": "4.3.0"
}
},
{
"name": "spring.cloud.gateway.mvc.x-forwarded-request-headers-filter.port-enabled",
"type": "java.lang.Boolean",
"description": "If X-Forwarded-Port is enabled.",
"sourceType": "org.springframework.cloud.gateway.server.mvc.filter.XForwardedRequestHeadersFilterProperties",
"defaultValue": true,
"deprecated": true,
"deprecation": {
"replacement": "spring.cloud.gateway.server.webmvc.x-forwarded-request-headers-filter.port-enabled",
"since": "4.3.0"
}
},
{
"name": "spring.cloud.gateway.mvc.x-forwarded-request-headers-filter.prefix-append",
"type": "java.lang.Boolean",
"description": "If appending X-Forwarded-Prefix as a list is enabled.",
"sourceType": "org.springframework.cloud.gateway.server.mvc.filter.XForwardedRequestHeadersFilterProperties",
"defaultValue": true,
"deprecated": true,
"deprecation": {
"replacement": "spring.cloud.gateway.server.webmvc.x-forwarded-request-headers-filter.prefix-append",
"since": "4.3.0"
}
},
{
"name": "spring.cloud.gateway.mvc.x-forwarded-request-headers-filter.prefix-enabled",
"type": "java.lang.Boolean",
"description": "If X-Forwarded-Prefix is enabled.",
"sourceType": "org.springframework.cloud.gateway.server.mvc.filter.XForwardedRequestHeadersFilterProperties",
"defaultValue": true,
"deprecated": true,
"deprecation": {
"replacement": "spring.cloud.gateway.server.webmvc.x-forwarded-request-headers-filter.prefix-enabled",
"since": "4.3.0"
}
},
{
"name": "spring.cloud.gateway.mvc.x-forwarded-request-headers-filter.proto-append",
"type": "java.lang.Boolean",
"description": "If appending X-Forwarded-Proto as a list is enabled.",
"sourceType": "org.springframework.cloud.gateway.server.mvc.filter.XForwardedRequestHeadersFilterProperties",
"defaultValue": true,
"deprecated": true,
"deprecation": {
"replacement": "spring.cloud.gateway.server.webmvc.x-forwarded-request-headers-filter.proto-append",
"since": "4.3.0"
}
},
{
"name": "spring.cloud.gateway.mvc.x-forwarded-request-headers-filter.proto-enabled",
"type": "java.lang.Boolean",
"description": "If X-Forwarded-Proto is enabled.",
"sourceType": "org.springframework.cloud.gateway.server.mvc.filter.XForwardedRequestHeadersFilterProperties",
"defaultValue": true,
"deprecated": true,
"deprecation": {
"replacement": "spring.cloud.gateway.server.webmvc.x-forwarded-request-headers-filter.proto-enabled",
"since": "4.3.0"
}
},
{
"name": "spring.cloud.gateway.mvc.http-client.connect-timeout",
"type": "java.time.Duration",
"description": "The HttpClient connect timeout.",
"sourceType": "org.springframework.cloud.gateway.server.mvc.config.GatewayMvcProperties$HttpClient",
"deprecated": true,
"deprecation": {
"replacement": "spring.http.client.connect-timeout",
"since": "4.2.0"
}
},
{
"name": "spring.cloud.gateway.mvc.http-client.read-timeout",
"type": "java.time.Duration",
"description": "The HttpClient read timeout.",
"sourceType": "org.springframework.cloud.gateway.server.mvc.config.GatewayMvcProperties$HttpClient",
"deprecated": true,
"deprecation": {
"replacement": "spring.http.client.read-timeout",
"since": "4.2.0"
}
},
{
"name": "spring.cloud.gateway.mvc.http-client.ssl-bundle",
"type": "java.lang.String",
"description": "The name of the SSL bundle to use.",
"sourceType": "org.springframework.cloud.gateway.server.mvc.config.GatewayMvcProperties$HttpClient",
"deprecated": true,
"deprecation": {
"replacement": "spring.http.client.ssl.bundle",
"since": "4.2.0"
}
},
{
"name": "spring.cloud.gateway.mvc.http-client.type",
"type": "org.springframework.cloud.gateway.server.mvc.config.GatewayMvcProperties$HttpClientType",
"description": "The HttpClient type. Defaults to JDK.",
"sourceType": "org.springframework.cloud.gateway.server.mvc.config.GatewayMvcProperties$HttpClient",
"defaultValue": "jdk",
"deprecated": true,
"deprecation": {}
}
]
}

View File

@@ -18,3 +18,7 @@
org.springframework.boot.env.EnvironmentPostProcessor=\
org.springframework.cloud.gateway.server.mvc.GatewayServerMvcAutoConfiguration.GatewayHttpClientEnvironmentPostProcessor,\
org.springframework.cloud.gateway.server.mvc.common.MultipartEnvironmentPostProcessor
# Application Listeners
org.springframework.context.ApplicationListener=\
org.springframework.cloud.gateway.server.mvc.config.GatewayServerWebMvcPropertiesMigrationListener

View File

@@ -0,0 +1,82 @@
/*
* Copyright 2013-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.gateway.server.mvc;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringBootConfiguration;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
import org.springframework.cloud.gateway.server.mvc.config.GatewayMvcProperties;
import org.springframework.cloud.gateway.server.mvc.filter.FormFilter;
import org.springframework.cloud.gateway.server.mvc.filter.ForwardedRequestHeadersFilter;
import org.springframework.cloud.gateway.server.mvc.filter.RemoveContentLengthRequestHeadersFilter;
import org.springframework.cloud.gateway.server.mvc.filter.RemoveHopByHopRequestHeadersFilter;
import org.springframework.cloud.gateway.server.mvc.filter.RemoveHopByHopResponseHeadersFilter;
import org.springframework.cloud.gateway.server.mvc.filter.RemoveHttp2StatusResponseHeadersFilter;
import org.springframework.cloud.gateway.server.mvc.filter.TransferEncodingNormalizationRequestHeadersFilter;
import org.springframework.cloud.gateway.server.mvc.filter.WeightCalculatorFilter;
import org.springframework.cloud.gateway.server.mvc.filter.XForwardedRequestHeadersFilter;
import org.springframework.context.ApplicationContext;
import org.springframework.test.context.ActiveProfiles;
import static org.assertj.core.api.Assertions.assertThat;
@SuppressWarnings("unchecked")
@SpringBootTest(properties = {}, webEnvironment = WebEnvironment.RANDOM_PORT)
@ActiveProfiles("propertiesmigrationtests")
public class GatewayMvcPropertiesMigrationTests {
@Autowired
ApplicationContext context;
@Autowired
GatewayMvcProperties properties;
@SuppressWarnings("rawtypes")
@Test
public void deprecatedFilterEnabledPropertiesWork() {
assertBeanDoesNotExist(FormFilter.class);
assertBeanDoesNotExist(ForwardedRequestHeadersFilter.class);
assertBeanDoesNotExist(RemoveContentLengthRequestHeadersFilter.class);
assertBeanDoesNotExist(RemoveHopByHopRequestHeadersFilter.class);
assertBeanDoesNotExist(RemoveHopByHopResponseHeadersFilter.class);
assertBeanDoesNotExist(RemoveHttp2StatusResponseHeadersFilter.class);
assertBeanDoesNotExist(TransferEncodingNormalizationRequestHeadersFilter.class);
assertBeanDoesNotExist(WeightCalculatorFilter.class);
assertBeanDoesNotExist(XForwardedRequestHeadersFilter.class);
}
@Test
public void deprecatedRoutePropertiesWork() {
assertThat(properties.getRoutes()).hasSize(2);
assertThat(properties.getRoutesMap()).hasSize(2);
}
private void assertBeanDoesNotExist(Class<?> type) {
assertThat(context.getBeanNamesForType(type)).isEmpty();
}
@SpringBootConfiguration
@EnableAutoConfiguration
protected static class TestConfiguration {
}
}

View File

@@ -116,15 +116,15 @@ public class GatewayServerMvcAutoConfigurationTests {
HandlerFunctionAutoConfiguration.class, GatewayServerMvcAutoConfiguration.class,
HttpClientAutoConfiguration.class, RestTemplateAutoConfiguration.class,
RestClientAutoConfiguration.class, SslAutoConfiguration.class))
.withPropertyValues("spring.cloud.gateway.mvc.form-filter.enabled=false",
"spring.cloud.gateway.mvc.forwarded-request-headers-filter.enabled=false",
"spring.cloud.gateway.mvc.remove-content-length-request-headers-filter.enabled=false",
"spring.cloud.gateway.mvc.remove-hop-by-hop-request-headers-filter.enabled=false",
"spring.cloud.gateway.mvc.remove-hop-by-hop-response-headers-filter.enabled=false",
"spring.cloud.gateway.mvc.remove-http2-status-response-headers-filter.enabled=false",
"spring.cloud.gateway.mvc.transfer-encoding-normalization-request-headers-filter.enabled=false",
"spring.cloud.gateway.mvc.weight-calculator-filter.enabled=false",
"spring.cloud.gateway.mvc.x-forwarded-request-headers-filter.enabled=false")
.withPropertyValues("spring.cloud.gateway.server.webmvc.form-filter.enabled=false",
"spring.cloud.gateway.server.webmvc.forwarded-request-headers-filter.enabled=false",
"spring.cloud.gateway.server.webmvc.remove-content-length-request-headers-filter.enabled=false",
"spring.cloud.gateway.server.webmvc.remove-hop-by-hop-request-headers-filter.enabled=false",
"spring.cloud.gateway.server.webmvc.remove-hop-by-hop-response-headers-filter.enabled=false",
"spring.cloud.gateway.server.webmvc.remove-http2-status-response-headers-filter.enabled=false",
"spring.cloud.gateway.server.webmvc.transfer-encoding-normalization-request-headers-filter.enabled=false",
"spring.cloud.gateway.server.webmvc.weight-calculator-filter.enabled=false",
"spring.cloud.gateway.server.webmvc.x-forwarded-request-headers-filter.enabled=false")
.run(context -> {
assertThat(context).doesNotHaveBean(FormFilter.class);
assertThat(context).doesNotHaveBean(ForwardedRequestHeadersFilter.class);

View File

@@ -199,14 +199,13 @@ public class GatewayMvcPropertiesBeanDefinitionRegistrarTests {
void refreshWorks(ConfigurableApplicationContext context) {
Map<String, RouterFunction> routerFunctions = getRouterFunctions(context);
assertThat(routerFunctions).hasSize(6);
TestPropertyValues
.of("spring.cloud.gateway.mvc.routesMap.route3.uri=https://example3.com",
"spring.cloud.gateway.mvc.routesMap.route3.predicates[0].name=Path",
"spring.cloud.gateway.mvc.routesMap.route3.predicates[0].args.pattern=/anything/mapRoute3",
"spring.cloud.gateway.mvc.routesMap.route3.filters[0].Name=HttpbinUriResolver",
"spring.cloud.gateway.mvc.routesMap.route3.filters[1].Name=AddRequestHeader",
"spring.cloud.gateway.mvc.routesMap.route3.filters[1].args.name=X-Test",
"spring.cloud.gateway.mvc.routesMap.route3.filters[1].args.values=mapRoute3")
TestPropertyValues.of("spring.cloud.gateway.server.webmvc.routesMap.route3.uri=https://example3.com",
"spring.cloud.gateway.server.webmvc.routesMap.route3.predicates[0].name=Path",
"spring.cloud.gateway.server.webmvc.routesMap.route3.predicates[0].args.pattern=/anything/mapRoute3",
"spring.cloud.gateway.server.webmvc.routesMap.route3.filters[0].Name=HttpbinUriResolver",
"spring.cloud.gateway.server.webmvc.routesMap.route3.filters[1].Name=AddRequestHeader",
"spring.cloud.gateway.server.webmvc.routesMap.route3.filters[1].args.name=X-Test",
"spring.cloud.gateway.server.webmvc.routesMap.route3.filters[1].args.values=mapRoute3")
.applyTo(context);
ContextRefresher contextRefresher = context.getBean(ContextRefresher.class);
contextRefresher.refresh();

View File

@@ -0,0 +1,47 @@
spring.cloud.gateway.mvc:
form-filter.enabled: false
forwarded-request-headers-filter.enabled: false
remove-content-length-request-headers-filter.enabled: false
remove-hop-by-hop-request-headers-filter.enabled: false
remove-hop-by-hop-response-headers-filter.enabled: false
remove-http2-status-response-headers-filter.enabled: false
transfer-encoding-normalization-request-headers-filter.enabled: false
weight-calculator-filter.enabled: false
x-forwarded-request-headers-filter.enabled: false
routes:
- id: listRoute1
uri: https://examplel1.com
predicates:
- name: Method
args:
methods: GET
- name: Path
args:
pattern: /anything/listRoute1
filters:
- HttpbinUriResolver=
- AddRequestHeader=X-Test,listRoute1
- id: listRoute2
uri: https://examplel2.com
predicates:
- name: Method
args:
methods: GET
- name: Path
args:
pattern: /anything/listRoute2
filters:
- HttpbinUriResolver=
- AddRequestHeader=X-Test,listRoute2
routesMap:
route1:
uri: https://example1.com
predicates:
- Path=/anything/example1
route2:
uri: https://example2.com
predicates:
- Path=/anything/example2
logging:
level:
org.springframework.cloud.gateway.server.mvc: TRACE