Merge branch '3.1.x' into 3.2.x

Closes gh-39122
This commit is contained in:
Andy Wilkinson
2024-01-12 17:08:23 +00:00
10 changed files with 130 additions and 16 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2012-2023 the original author or authors.
* Copyright 2012-2024 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.
@@ -91,6 +91,20 @@ class PathMappedEndpointsTests {
assertThat(mapped.getPath(EndpointId.of("xx"))).isNull();
}
@Test
void getPathWhenBasePathIsRootAndEndpointIsPathMappedToRootShouldReturnSingleSlash() {
PathMappedEndpoints mapped = new PathMappedEndpoints("/",
() -> List.of(mockEndpoint(EndpointId.of("root"), "/")));
assertThat(mapped.getPath(EndpointId.of("root"))).isEqualTo("/");
}
@Test
void getPathWhenBasePathIsRootAndEndpointIsPathMapped() {
PathMappedEndpoints mapped = new PathMappedEndpoints("/",
() -> List.of(mockEndpoint(EndpointId.of("a"), "alpha")));
assertThat(mapped.getPath(EndpointId.of("a"))).isEqualTo("/alpha");
}
@Test
void getAllRootPathsShouldReturnAllPaths() {
PathMappedEndpoints mapped = createTestMapped(null);

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2012-2023 the original author or authors.
* Copyright 2012-2024 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.
@@ -38,6 +38,7 @@ import org.springframework.boot.actuate.endpoint.annotation.ReadOperation;
import org.springframework.boot.actuate.endpoint.annotation.Selector;
import org.springframework.boot.actuate.endpoint.annotation.Selector.Match;
import org.springframework.boot.actuate.endpoint.annotation.WriteOperation;
import org.springframework.boot.actuate.endpoint.web.PathMapper;
import org.springframework.boot.actuate.endpoint.web.WebEndpointResponse;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ConfigurableApplicationContext;
@@ -108,6 +109,21 @@ public abstract class AbstractWebEndpointIntegrationTests<T extends Configurable
.isEqualTo(true));
}
@Test
void readOperationWithEndpointPathMappedToTheRoot() {
load(EndpointPathMappedToRootConfiguration.class, "", (client) -> {
client.get().uri("/").exchange().expectStatus().isOk().expectBody().jsonPath("All").isEqualTo(true);
client.get()
.uri("/some-part")
.exchange()
.expectStatus()
.isOk()
.expectBody()
.jsonPath("part")
.isEqualTo("some-part");
});
}
@Test
void readOperationWithSelector() {
load(TestEndpointConfiguration.class,
@@ -672,6 +688,17 @@ public abstract class AbstractWebEndpointIntegrationTests<T extends Configurable
}
@Configuration(proxyBeanMethods = false)
@Import(TestEndpointConfiguration.class)
protected static class EndpointPathMappedToRootConfiguration {
@Bean
PathMapper pathMapper() {
return (endpointId) -> "/";
}
}
@Configuration(proxyBeanMethods = false)
@Import(BaseConfiguration.class)
static class MatchAllRemainingEndpointConfiguration {

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2012-2023 the original author or authors.
* Copyright 2012-2024 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.
@@ -20,9 +20,11 @@ import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.boot.actuate.endpoint.invoke.ParameterValueMapper;
import org.springframework.boot.actuate.endpoint.invoke.convert.ConversionServiceParameterValueMapper;
import org.springframework.boot.actuate.endpoint.web.EndpointMediaTypes;
import org.springframework.boot.actuate.endpoint.web.PathMapper;
import org.springframework.boot.web.embedded.tomcat.TomcatEmbeddedWebappClassLoader;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
@@ -62,11 +64,11 @@ class BaseConfiguration {
@Bean
WebEndpointDiscoverer webEndpointDiscoverer(EndpointMediaTypes endpointMediaTypes,
ApplicationContext applicationContext) {
ApplicationContext applicationContext, ObjectProvider<PathMapper> pathMappers) {
ParameterValueMapper parameterMapper = new ConversionServiceParameterValueMapper(
DefaultConversionService.getSharedInstance());
return new WebEndpointDiscoverer(applicationContext, parameterMapper, endpointMediaTypes, null,
Collections.emptyList(), Collections.emptyList());
return new WebEndpointDiscoverer(applicationContext, parameterMapper, endpointMediaTypes,
pathMappers.orderedStream().toList(), Collections.emptyList(), Collections.emptyList());
}
@Bean

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2012-2023 the original author or authors.
* Copyright 2012-2024 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.
@@ -68,6 +68,13 @@ class RequestPredicateFactoryTests {
assertThat(requestPredicate.getPath()).isEqualTo("/root/{one}/{*two}");
}
@Test
void getRequestPredicateWithSlashRootReturnsPredicateWithPathWithoutDoubleSlash() {
DiscoveredOperationMethod operationMethod = getDiscoveredOperationMethod(ValidSelectors.class);
WebOperationRequestPredicate requestPredicate = this.factory.getRequestPredicate("/", operationMethod);
assertThat(requestPredicate.getPath()).isEqualTo("/{one}/{*two}");
}
private DiscoveredOperationMethod getDiscoveredOperationMethod(Class<?> source) {
Method method = source.getDeclaredMethods()[0];
AnnotationAttributes attributes = new AnnotationAttributes();