Skip to content

Commit f33e027

Browse files
committed
Switches BeanPostProcessor to ApiVersionConfigurer
1 parent ee13b3f commit f33e027

File tree

2 files changed

+63
-189
lines changed

2 files changed

+63
-189
lines changed

spring-cloud-gateway-server-webflux/src/main/java/org/springframework/cloud/gateway/config/GatewayAutoConfiguration.java

Lines changed: 32 additions & 95 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@
2222
import java.security.KeyStoreException;
2323
import java.security.NoSuchAlgorithmException;
2424
import java.security.cert.CertificateException;
25-
import java.util.ArrayList;
2625
import java.util.List;
2726
import java.util.Set;
2827
import java.util.function.Supplier;
@@ -42,11 +41,9 @@
4241
import org.springframework.aot.hint.RuntimeHints;
4342
import org.springframework.aot.hint.RuntimeHintsRegistrar;
4443
import org.springframework.aot.hint.TypeReference;
45-
import org.springframework.beans.BeansException;
4644
import org.springframework.beans.factory.BeanFactory;
4745
import org.springframework.beans.factory.ObjectProvider;
4846
import org.springframework.beans.factory.annotation.Qualifier;
49-
import org.springframework.beans.factory.config.BeanPostProcessor;
5047
import org.springframework.boot.actuate.autoconfigure.endpoint.condition.ConditionalOnAvailableEndpoint;
5148
import org.springframework.boot.actuate.autoconfigure.endpoint.web.WebEndpointProperties;
5249
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
@@ -191,15 +188,10 @@
191188
import org.springframework.util.CollectionUtils;
192189
import org.springframework.util.StringUtils;
193190
import org.springframework.validation.Validator;
194-
import org.springframework.web.accept.ApiVersionParser;
195-
import org.springframework.web.accept.SemanticApiVersionParser;
196191
import org.springframework.web.reactive.DispatcherHandler;
197-
import org.springframework.web.reactive.accept.ApiVersionDeprecationHandler;
198-
import org.springframework.web.reactive.accept.ApiVersionResolver;
199192
import org.springframework.web.reactive.accept.ApiVersionStrategy;
200-
import org.springframework.web.reactive.accept.DefaultApiVersionStrategy;
201-
import org.springframework.web.reactive.accept.MediaTypeParamApiVersionResolver;
202-
import org.springframework.web.reactive.accept.PathApiVersionResolver;
193+
import org.springframework.web.reactive.config.ApiVersionConfigurer;
194+
import org.springframework.web.reactive.config.WebFluxConfigurer;
203195
import org.springframework.web.reactive.socket.client.ReactorNettyWebSocketClient;
204196
import org.springframework.web.reactive.socket.client.WebSocketClient;
205197
import org.springframework.web.reactive.socket.server.RequestUpgradeStrategy;
@@ -774,23 +766,41 @@ public GzipMessageBodyResolver gzipMessageBodyResolver() {
774766
return new GzipMessageBodyResolver();
775767
}
776768

777-
@Bean
778-
public GatewayServerWebfluxBeanPostProcessor gatewayServerWebfluxBeanPostProcessor(
779-
ObjectProvider<WebFluxProperties> properties,
780-
ObjectProvider<ApiVersionDeprecationHandler> deprecationHandlerProvider,
781-
ObjectProvider<ApiVersionParser<?>> versionParserProvider,
782-
ObjectProvider<ApiVersionResolver> versionResolvers) {
783-
return new GatewayServerWebfluxBeanPostProcessor(
784-
properties.getIfAvailable(WebFluxProperties::new).getApiversion(),
785-
deprecationHandlerProvider.getIfAvailable(), versionParserProvider.getIfAvailable(),
786-
versionResolvers.orderedStream().toList());
787-
}
788-
789769
@Bean
790770
static ConfigurableHintsRegistrationProcessor configurableHintsRegistrationProcessor() {
791771
return new ConfigurableHintsRegistrationProcessor();
792772
}
793773

774+
@Configuration(proxyBeanMethods = false)
775+
static class GatewayWebFluxApiVersionConfig implements WebFluxConfigurer {
776+
777+
final Apiversion versionProperties;
778+
779+
GatewayWebFluxApiVersionConfig(ObjectProvider<WebFluxProperties> webFluxProperties) {
780+
this.versionProperties = webFluxProperties.getIfAvailable(WebFluxProperties::new).getApiversion();
781+
}
782+
783+
@Override
784+
public void configureApiVersioning(ApiVersionConfigurer configurer) {
785+
Boolean required = versionProperties.getRequired();
786+
Boolean detectSupported = versionProperties.getDetectSupported();
787+
788+
Apiversion.Use use = versionProperties.getUse();
789+
// only set defaults is one or more use options is set
790+
if (StringUtils.hasText(use.getHeader()) || StringUtils.hasText(use.getQueryParameter())
791+
|| use.getPathSegment() != null || !CollectionUtils.isEmpty(use.getMediaTypeParameter())) {
792+
if (required == null) {
793+
configurer.setVersionRequired(false);
794+
}
795+
if (detectSupported == null) {
796+
configurer.detectSupportedVersions(true);
797+
}
798+
configurer.setSupportedVersionPredicate(comparable -> true);
799+
}
800+
}
801+
802+
}
803+
794804
@Configuration(proxyBeanMethods = false)
795805
@ConditionalOnClass(AsyncProxyManager.class)
796806
protected static class Bucket4jConfiguration {
@@ -964,79 +974,6 @@ public TokenRelayGatewayFilterFactory tokenRelayGatewayFilterFactory(
964974

965975
}
966976

967-
protected static class GatewayServerWebfluxBeanPostProcessor implements BeanPostProcessor {
968-
969-
private final Apiversion versionProperties;
970-
971-
private final ApiVersionDeprecationHandler deprecationHandler;
972-
973-
private final ApiVersionParser<?> versionParser;
974-
975-
private final List<ApiVersionResolver> apiVersionResolvers;
976-
977-
public GatewayServerWebfluxBeanPostProcessor(Apiversion versionProperties,
978-
ApiVersionDeprecationHandler deprecationHandler, ApiVersionParser<?> versionParser,
979-
List<ApiVersionResolver> apiVersionResolvers) {
980-
this.versionProperties = versionProperties;
981-
this.deprecationHandler = deprecationHandler;
982-
this.versionParser = (versionParser != null) ? versionParser : new SemanticApiVersionParser();
983-
this.apiVersionResolvers = apiVersionResolvers;
984-
}
985-
986-
@Override
987-
public @Nullable Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
988-
989-
// TODO: Use custom ApiVersionConfigurer when able to
990-
if (bean instanceof ApiVersionStrategy && beanName.equals("webFluxApiVersionStrategy")) {
991-
List<ApiVersionResolver> versionResolvers = new ArrayList<>();
992-
if (StringUtils.hasText(versionProperties.getUse().getHeader())) {
993-
versionResolvers.add(exchange -> exchange.getRequest()
994-
.getHeaders()
995-
.getFirst(versionProperties.getUse().getHeader()));
996-
}
997-
if (!CollectionUtils.isEmpty(versionProperties.getUse().getMediaTypeParameter())) {
998-
versionProperties.getUse().getMediaTypeParameter().forEach((mediaType, param) -> {
999-
versionResolvers.add(new MediaTypeParamApiVersionResolver(mediaType, param));
1000-
});
1001-
}
1002-
if (versionProperties.getUse().getPathSegment() != null) {
1003-
versionResolvers.add(new PathApiVersionResolver(versionProperties.getUse().getPathSegment()));
1004-
}
1005-
if (StringUtils.hasText(versionProperties.getUse().getQueryParameter())) {
1006-
versionResolvers.add(exchange -> exchange.getRequest()
1007-
.getQueryParams()
1008-
.getFirst(versionProperties.getUse().getQueryParameter()));
1009-
}
1010-
1011-
if (apiVersionResolvers != null && !apiVersionResolvers.isEmpty()) {
1012-
versionResolvers.addAll(apiVersionResolvers);
1013-
}
1014-
1015-
if (versionResolvers.isEmpty()) {
1016-
return bean;
1017-
}
1018-
1019-
Boolean required = versionProperties.getRequired();
1020-
if (required == null) {
1021-
required = false;
1022-
}
1023-
Boolean detectSupported = versionProperties.getDetectSupported();
1024-
if (detectSupported == null) {
1025-
detectSupported = true;
1026-
}
1027-
DefaultApiVersionStrategy strategy = new DefaultApiVersionStrategy(versionResolvers, versionParser,
1028-
required, versionProperties.getDefaultVersion(), detectSupported, comparable -> true,
1029-
deprecationHandler);
1030-
if (!CollectionUtils.isEmpty(versionProperties.getSupported())) {
1031-
strategy.addSupportedVersion(versionProperties.getSupported().toArray(new String[0]));
1032-
}
1033-
return strategy;
1034-
}
1035-
return bean;
1036-
}
1037-
1038-
}
1039-
1040977
}
1041978

1042979
class GatewayHints implements RuntimeHintsRegistrar {

spring-cloud-gateway-server-webmvc/src/main/java/org/springframework/cloud/gateway/server/mvc/GatewayServerMvcAutoConfiguration.java

Lines changed: 31 additions & 94 deletions
Original file line numberDiff line numberDiff line change
@@ -16,16 +16,10 @@
1616

1717
package org.springframework.cloud.gateway.server.mvc;
1818

19-
import java.util.ArrayList;
20-
import java.util.List;
2119
import java.util.Map;
2220

23-
import org.jspecify.annotations.Nullable;
24-
25-
import org.springframework.beans.BeansException;
2621
import org.springframework.beans.factory.BeanFactory;
2722
import org.springframework.beans.factory.ObjectProvider;
28-
import org.springframework.beans.factory.config.BeanPostProcessor;
2923
import org.springframework.boot.SpringApplication;
3024
import org.springframework.boot.autoconfigure.AutoConfiguration;
3125
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
@@ -69,6 +63,7 @@
6963
import org.springframework.context.ApplicationEventPublisher;
7064
import org.springframework.context.annotation.Bean;
7165
import org.springframework.context.annotation.Conditional;
66+
import org.springframework.context.annotation.Configuration;
7267
import org.springframework.context.annotation.Import;
7368
import org.springframework.core.env.ConfigurableEnvironment;
7469
import org.springframework.core.env.Environment;
@@ -77,16 +72,9 @@
7772
import org.springframework.util.ClassUtils;
7873
import org.springframework.util.CollectionUtils;
7974
import org.springframework.util.StringUtils;
80-
import org.springframework.web.accept.ApiVersionDeprecationHandler;
81-
import org.springframework.web.accept.ApiVersionParser;
82-
import org.springframework.web.accept.ApiVersionResolver;
83-
import org.springframework.web.accept.ApiVersionStrategy;
84-
import org.springframework.web.accept.DefaultApiVersionStrategy;
85-
import org.springframework.web.accept.MediaTypeParamApiVersionResolver;
86-
import org.springframework.web.accept.PathApiVersionResolver;
87-
import org.springframework.web.accept.QueryApiVersionResolver;
88-
import org.springframework.web.accept.SemanticApiVersionParser;
8975
import org.springframework.web.client.RestClient;
76+
import org.springframework.web.servlet.config.annotation.ApiVersionConfigurer;
77+
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
9078

9179
/**
9280
* AutoConfiguration for Spring Cloud Gateway MVC server.
@@ -232,16 +220,34 @@ static GatewayMvcRuntimeHintsProcessor gatewayMvcRuntimeHintsProcessor() {
232220
return new GatewayMvcRuntimeHintsProcessor();
233221
}
234222

235-
@Bean
236-
GatewayServerWebMvcBeanPostProcessor gatewayServerWebMvcBeanPostProcessor(
237-
ObjectProvider<WebMvcProperties> properties,
238-
ObjectProvider<ApiVersionDeprecationHandler> deprecationHandlerProvider,
239-
ObjectProvider<ApiVersionParser<?>> versionParserProvider,
240-
ObjectProvider<ApiVersionResolver> versionResolvers) {
241-
return new GatewayServerWebMvcBeanPostProcessor(
242-
properties.getIfAvailable(WebMvcProperties::new).getApiversion(),
243-
deprecationHandlerProvider.getIfAvailable(), versionParserProvider.getIfAvailable(),
244-
versionResolvers.orderedStream().toList());
223+
@Configuration(proxyBeanMethods = false)
224+
static class GatewayMvcApiVersionConfig implements WebMvcConfigurer {
225+
226+
final Apiversion versionProperties;
227+
228+
GatewayMvcApiVersionConfig(ObjectProvider<WebMvcProperties> webMvcProperties) {
229+
this.versionProperties = webMvcProperties.getIfAvailable(WebMvcProperties::new).getApiversion();
230+
}
231+
232+
@Override
233+
public void configureApiVersioning(ApiVersionConfigurer configurer) {
234+
Boolean required = versionProperties.getRequired();
235+
Boolean detectSupported = versionProperties.getDetectSupported();
236+
237+
Apiversion.Use use = versionProperties.getUse();
238+
// only set defaults is one or more use options is set
239+
if (StringUtils.hasText(use.getHeader()) || StringUtils.hasText(use.getQueryParameter())
240+
|| use.getPathSegment() != null || !CollectionUtils.isEmpty(use.getMediaTypeParameter())) {
241+
if (required == null) {
242+
configurer.setVersionRequired(false);
243+
}
244+
if (detectSupported == null) {
245+
configurer.detectSupportedVersions(true);
246+
}
247+
configurer.setSupportedVersionPredicate(comparable -> true);
248+
}
249+
}
250+
245251
}
246252

247253
static class GatewayHttpClientEnvironmentPostProcessor implements EnvironmentPostProcessor {
@@ -288,73 +294,4 @@ else if (StringUtils.hasText(restrictedHeaders) && !restrictedHeaders.contains("
288294

289295
}
290296

291-
protected static class GatewayServerWebMvcBeanPostProcessor implements BeanPostProcessor {
292-
293-
private final Apiversion versionProperties;
294-
295-
private final ApiVersionDeprecationHandler deprecationHandler;
296-
297-
private final ApiVersionParser<?> versionParser;
298-
299-
private final List<ApiVersionResolver> apiVersionResolvers;
300-
301-
public GatewayServerWebMvcBeanPostProcessor(Apiversion versionProperties,
302-
ApiVersionDeprecationHandler deprecationHandler, ApiVersionParser<?> versionParser,
303-
List<ApiVersionResolver> apiVersionResolvers) {
304-
this.versionProperties = versionProperties;
305-
this.deprecationHandler = deprecationHandler;
306-
this.versionParser = (versionParser != null) ? versionParser : new SemanticApiVersionParser();
307-
this.apiVersionResolvers = apiVersionResolvers;
308-
}
309-
310-
@Override
311-
public @Nullable Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
312-
313-
// TODO: Use custom ApiVersionConfigurer when able to
314-
if (bean instanceof ApiVersionStrategy && beanName.equals("mvcApiVersionStrategy")) {
315-
List<ApiVersionResolver> versionResolvers = new ArrayList<>();
316-
if (StringUtils.hasText(versionProperties.getUse().getHeader())) {
317-
versionResolvers.add(request -> request.getHeader(versionProperties.getUse().getHeader()));
318-
}
319-
if (!CollectionUtils.isEmpty(versionProperties.getUse().getMediaTypeParameter())) {
320-
versionProperties.getUse().getMediaTypeParameter().forEach((mediaType, param) -> {
321-
versionResolvers.add(new MediaTypeParamApiVersionResolver(mediaType, param));
322-
});
323-
}
324-
if (versionProperties.getUse().getPathSegment() != null) {
325-
versionResolvers.add(new PathApiVersionResolver(versionProperties.getUse().getPathSegment()));
326-
}
327-
if (StringUtils.hasText(versionProperties.getUse().getQueryParameter())) {
328-
versionResolvers.add(new QueryApiVersionResolver(versionProperties.getUse().getQueryParameter()));
329-
}
330-
331-
if (apiVersionResolvers != null && !apiVersionResolvers.isEmpty()) {
332-
versionResolvers.addAll(apiVersionResolvers);
333-
}
334-
335-
if (versionResolvers.isEmpty()) {
336-
return bean;
337-
}
338-
339-
Boolean required = versionProperties.getRequired();
340-
if (required == null) {
341-
required = false;
342-
}
343-
Boolean detectSupported = versionProperties.getDetectSupported();
344-
if (detectSupported == null) {
345-
detectSupported = true;
346-
}
347-
DefaultApiVersionStrategy strategy = new DefaultApiVersionStrategy(versionResolvers, versionParser,
348-
required, versionProperties.getDefaultVersion(), detectSupported, comparable -> true,
349-
deprecationHandler);
350-
if (!CollectionUtils.isEmpty(versionProperties.getSupported())) {
351-
strategy.addSupportedVersion(versionProperties.getSupported().toArray(new String[0]));
352-
}
353-
return strategy;
354-
}
355-
return bean;
356-
}
357-
358-
}
359-
360297
}

0 commit comments

Comments
 (0)