From 3ad2832cb2c9b98f02d3992f8d4ba1dfcb7c9492 Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Tue, 19 Jan 2021 10:34:11 +0000 Subject: [PATCH] Fix pattern extraction when MVC is using a PathPatternParser Fixes gh-24874 --- .../RequestMappingConditionsDescription.java | 11 ++++- .../web/mappings/MappingsEndpointTests.java | 44 ++++++++++++++++++- 2 files changed, 52 insertions(+), 3 deletions(-) diff --git a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/web/mappings/servlet/RequestMappingConditionsDescription.java b/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/web/mappings/servlet/RequestMappingConditionsDescription.java index f8c21f03769b..46cafd0474ed 100644 --- a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/web/mappings/servlet/RequestMappingConditionsDescription.java +++ b/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/web/mappings/servlet/RequestMappingConditionsDescription.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2019 the original author or authors. + * Copyright 2012-2021 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. @@ -23,6 +23,7 @@ import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.servlet.mvc.condition.MediaTypeExpression; import org.springframework.web.servlet.mvc.condition.NameValueExpression; +import org.springframework.web.servlet.mvc.condition.PatternsRequestCondition; import org.springframework.web.servlet.mvc.method.RequestMappingInfo; /** @@ -53,11 +54,17 @@ public class RequestMappingConditionsDescription { this.methods = requestMapping.getMethodsCondition().getMethods(); this.params = requestMapping.getParamsCondition().getExpressions().stream() .map(NameValueExpressionDescription::new).collect(Collectors.toList()); - this.patterns = requestMapping.getPatternsCondition().getPatterns(); + this.patterns = extractPathPatterns(requestMapping); this.produces = requestMapping.getProducesCondition().getExpressions().stream() .map(MediaTypeExpressionDescription::new).collect(Collectors.toList()); } + private Set extractPathPatterns(RequestMappingInfo requestMapping) { + PatternsRequestCondition patternsCondition = requestMapping.getPatternsCondition(); + return (patternsCondition != null) ? patternsCondition.getPatterns() + : requestMapping.getPathPatternsCondition().getPatternValues(); + } + public List getConsumes() { return this.consumes; } diff --git a/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/web/mappings/MappingsEndpointTests.java b/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/web/mappings/MappingsEndpointTests.java index b0d95504e090..91ff146d15df 100644 --- a/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/web/mappings/MappingsEndpointTests.java +++ b/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/web/mappings/MappingsEndpointTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2019 the original author or authors. + * Copyright 2012-2021 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. @@ -56,6 +56,9 @@ import org.springframework.web.reactive.function.server.ServerResponse; import org.springframework.web.servlet.DispatcherServlet; import org.springframework.web.servlet.config.annotation.EnableWebMvc; +import org.springframework.web.servlet.config.annotation.PathMatchConfigurer; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; +import org.springframework.web.util.pattern.PathPatternParser; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.BDDMockito.given; @@ -94,6 +97,28 @@ void servletWebMappings() { }); } + @Test + void servletWebMappingsWithPathPatternParser() { + Supplier contextSupplier = prepareContextSupplier(); + new WebApplicationContextRunner(contextSupplier).withUserConfiguration(EndpointConfiguration.class, + ServletWebConfiguration.class, PathPatternParserConfiguration.class).run((context) -> { + ContextMappings contextMappings = contextMappings(context); + assertThat(contextMappings.getParentId()).isNull(); + assertThat(contextMappings.getMappings()).containsOnlyKeys("dispatcherServlets", "servletFilters", + "servlets"); + Map> dispatcherServlets = mappings( + contextMappings, "dispatcherServlets"); + assertThat(dispatcherServlets).containsOnlyKeys("dispatcherServlet"); + List handlerMappings = dispatcherServlets + .get("dispatcherServlet"); + assertThat(handlerMappings).hasSize(1); + List servlets = mappings(contextMappings, "servlets"); + assertThat(servlets).hasSize(1); + List filters = mappings(contextMappings, "servletFilters"); + assertThat(filters).hasSize(1); + }); + } + @Test void servletWebMappingsWithAdditionalDispatcherServlets() { Supplier contextSupplier = prepareContextSupplier(); @@ -260,4 +285,21 @@ private DispatcherServlet createTestDispatcherServlet(WebApplicationContext cont } + @Configuration + static class PathPatternParserConfiguration { + + @Bean + WebMvcConfigurer pathPatternParserConfigurer() { + return new WebMvcConfigurer() { + + @Override + public void configurePathMatch(PathMatchConfigurer configurer) { + configurer.setPatternParser(new PathPatternParser()); + } + + }; + } + + } + }