Skip to content

Commit

Permalink
Allow EndpointRequest to match additional paths
Browse files Browse the repository at this point in the history
Add `toAdditionalPaths(...)` methods on the servlet and reactive
`EndpointRequest` classes to support matching of additional paths.

A new `AdditionalPathsMapper` interface provides the mappings between
endpoint IDs and any additional paths that they might use. The existing
`AutoConfiguredHealthEndpointGroups` class has been updated to implement
the interface.

Auto-configurations have also been updated so that additional health
endpoint paths (typically `/livez` and `/readyz`) are permitted
when using Spring Security without any custom configuration.

Fixes gh-40962
  • Loading branch information
philwebb committed Sep 19, 2024
1 parent f5b6514 commit d72a9d9
Show file tree
Hide file tree
Showing 26 changed files with 900 additions and 200 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ public CloudFoundryWebEndpointDiscoverer(ApplicationContext applicationContext,
ParameterValueMapper parameterValueMapper, EndpointMediaTypes endpointMediaTypes,
List<PathMapper> endpointPathMappers, Collection<OperationInvokerAdvisor> invokerAdvisors,
Collection<EndpointFilter<ExposableWebEndpoint>> filters) {
super(applicationContext, parameterValueMapper, endpointMediaTypes, endpointPathMappers, invokerAdvisors,
super(applicationContext, parameterValueMapper, endpointMediaTypes, endpointPathMappers, null, invokerAdvisors,
filters);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import org.springframework.boot.actuate.endpoint.annotation.Endpoint;
import org.springframework.boot.actuate.endpoint.invoke.OperationInvokerAdvisor;
import org.springframework.boot.actuate.endpoint.invoke.ParameterValueMapper;
import org.springframework.boot.actuate.endpoint.web.AdditionalPathsMapper;
import org.springframework.boot.actuate.endpoint.web.EndpointMediaTypes;
import org.springframework.boot.actuate.endpoint.web.ExposableWebEndpoint;
import org.springframework.boot.actuate.endpoint.web.PathMappedEndpoints;
Expand Down Expand Up @@ -81,11 +82,12 @@ public EndpointMediaTypes endpointMediaTypes() {
@ConditionalOnMissingBean(WebEndpointsSupplier.class)
public WebEndpointDiscoverer webEndpointDiscoverer(ParameterValueMapper parameterValueMapper,
EndpointMediaTypes endpointMediaTypes, ObjectProvider<PathMapper> endpointPathMappers,
ObjectProvider<AdditionalPathsMapper> additionalPathsMappers,
ObjectProvider<OperationInvokerAdvisor> invokerAdvisors,
ObjectProvider<EndpointFilter<ExposableWebEndpoint>> filters) {
return new WebEndpointDiscoverer(this.applicationContext, parameterValueMapper, endpointMediaTypes,
endpointPathMappers.orderedStream().toList(), invokerAdvisors.orderedStream().toList(),
filters.orderedStream().toList());
endpointPathMappers.orderedStream().toList(), additionalPathsMappers.orderedStream().toList(),
invokerAdvisors.orderedStream().toList(), filters.orderedStream().toList());
}

@Bean
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2012-2022 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.
Expand All @@ -21,9 +21,11 @@
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.function.Predicate;
import java.util.function.Supplier;
import java.util.stream.Stream;

import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryUtils;
Expand All @@ -32,8 +34,12 @@
import org.springframework.beans.factory.annotation.BeanFactoryAnnotationUtils;
import org.springframework.boot.actuate.autoconfigure.health.HealthEndpointProperties.Group;
import org.springframework.boot.actuate.autoconfigure.health.HealthProperties.Status;
import org.springframework.boot.actuate.endpoint.EndpointId;
import org.springframework.boot.actuate.endpoint.Show;
import org.springframework.boot.actuate.endpoint.web.AdditionalPathsMapper;
import org.springframework.boot.actuate.endpoint.web.WebServerNamespace;
import org.springframework.boot.actuate.health.AdditionalHealthEndpointPath;
import org.springframework.boot.actuate.health.HealthEndpoint;
import org.springframework.boot.actuate.health.HealthEndpointGroup;
import org.springframework.boot.actuate.health.HealthEndpointGroups;
import org.springframework.boot.actuate.health.HttpCodeStatusMapper;
Expand All @@ -51,7 +57,7 @@
* @author Phillip Webb
* @author Madhura Bhave
*/
class AutoConfiguredHealthEndpointGroups implements HealthEndpointGroups {
class AutoConfiguredHealthEndpointGroups implements HealthEndpointGroups, AdditionalPathsMapper {

private static final Predicate<String> ALL = (name) -> true;

Expand Down Expand Up @@ -159,4 +165,20 @@ public HealthEndpointGroup get(String name) {
return this.groups.get(name);
}

@Override
public List<String> getAdditionalPaths(EndpointId endpointId, WebServerNamespace webServerNamespace) {
if (!HealthEndpoint.ID.equals(endpointId)) {
return null;
}
return streamAllGroups().map(HealthEndpointGroup::getAdditionalPath)
.filter(Objects::nonNull)
.filter((additionalPath) -> additionalPath.hasNamespace(webServerNamespace))
.map(AdditionalHealthEndpointPath::getValue)
.toList();
}

private Stream<HealthEndpointGroup> streamAllGroups() {
return Stream.concat(Stream.of(this.primaryGroup), this.groups.values().stream());
}

}
Original file line number Diff line number Diff line change
@@ -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.
Expand Down Expand Up @@ -73,8 +73,8 @@ HttpCodeStatusMapper healthHttpCodeStatusMapper(HealthEndpointProperties propert
}

@Bean
@ConditionalOnMissingBean
HealthEndpointGroups healthEndpointGroups(ApplicationContext applicationContext,
@ConditionalOnMissingBean(HealthEndpointGroups.class)
AutoConfiguredHealthEndpointGroups healthEndpointGroups(ApplicationContext applicationContext,
HealthEndpointProperties properties) {
return new AutoConfiguredHealthEndpointGroups(applicationContext, properties);
}
Expand Down
Loading

0 comments on commit d72a9d9

Please sign in to comment.