Don’t return 404 when metric or env regex matches entry with null value
Previously, if a regular expression was used when calling the metrics or environment endpoints, a metric or property with a null value would result in a 404 response. This commit updates the two affected endpoints so that any metric or property whose name matches the regular expression but has a null value is ignored. This allows all of the matching metrics or properties with non-null values to be returned in a 200 OK response. Closes gh-4552
This commit is contained in:
@@ -92,6 +92,15 @@ public class EnvironmentMvcEndpoint extends EndpointMvcAdapter
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object getOptionalValue(Environment source, String name) {
|
||||
Object result = source.getProperty(name);
|
||||
if (result != null) {
|
||||
result = ((EnvironmentEndpoint) getDelegate()).sanitize(name, result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object getValue(Environment source, String name) {
|
||||
String result = source.getProperty(name);
|
||||
|
||||
@@ -67,13 +67,23 @@ public class MetricsMvcEndpoint extends EndpointMvcAdapter {
|
||||
@Override
|
||||
protected void getNames(Map<String, ?> source, NameCallback callback) {
|
||||
for (String name : source.keySet()) {
|
||||
callback.addName(name);
|
||||
try {
|
||||
callback.addName(name);
|
||||
}
|
||||
catch (NoSuchMetricException ex) {
|
||||
// Metric with null value. Continue.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object getOptionalValue(Map<String, ?> source, String name) {
|
||||
return source.get(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object getValue(Map<String, ?> source, String name) {
|
||||
Object value = source.get(name);
|
||||
Object value = getOptionalValue(source, name);
|
||||
if (value == null) {
|
||||
throw new NoSuchMetricException("No such metric: " + name);
|
||||
}
|
||||
|
||||
@@ -71,6 +71,8 @@ abstract class NamePatternFilter<T> {
|
||||
|
||||
protected abstract Object getValue(T source, String name);
|
||||
|
||||
protected abstract Object getOptionalValue(T source, String name);
|
||||
|
||||
/**
|
||||
* Callback used to add a name.
|
||||
*/
|
||||
@@ -96,7 +98,10 @@ abstract class NamePatternFilter<T> {
|
||||
@Override
|
||||
public void addName(String name) {
|
||||
if (this.pattern.matcher(name).matches()) {
|
||||
this.results.put(name, getValue(NamePatternFilter.this.source, name));
|
||||
Object value = getOptionalValue(NamePatternFilter.this.source, name);
|
||||
if (value != null) {
|
||||
this.results.put(name, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -16,6 +16,9 @@
|
||||
|
||||
package org.springframework.boot.actuate.endpoint.mvc;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
@@ -34,6 +37,8 @@ import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.core.env.ConfigurableEnvironment;
|
||||
import org.springframework.core.env.MapPropertySource;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
import org.springframework.test.context.web.WebAppConfiguration;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
@@ -89,6 +94,10 @@ public class EnvironmentMvcEndpointTests {
|
||||
|
||||
@Test
|
||||
public void regex() throws Exception {
|
||||
Map<String, Object> map = new HashMap<String, Object>();
|
||||
map.put("food", null);
|
||||
((ConfigurableEnvironment) this.context.getEnvironment()).getPropertySources()
|
||||
.addFirst(new MapPropertySource("null-value", map));
|
||||
this.mvc.perform(get("/env/foo.*")).andExpect(status().isOk())
|
||||
.andExpect(content().string(containsString("\"foo\":\"bar\"")))
|
||||
.andExpect(content().string(containsString("\"fool\":\"baz\"")));
|
||||
|
||||
@@ -126,7 +126,6 @@ public class MetricsMvcEndpointTests {
|
||||
public void specificMetricWithDot() throws Exception {
|
||||
this.mvc.perform(get("/metrics/group2.a")).andExpect(status().isOk())
|
||||
.andExpect(content().string(containsString("1")));
|
||||
|
||||
}
|
||||
|
||||
@Import({ JacksonAutoConfiguration.class,
|
||||
@@ -148,6 +147,7 @@ public class MetricsMvcEndpointTests {
|
||||
metrics.add(new Metric<Integer>("group1.b", 1));
|
||||
metrics.add(new Metric<Integer>("group2.a", 1));
|
||||
metrics.add(new Metric<Integer>("group2_a", 1));
|
||||
metrics.add(new Metric<Integer>("baz", null));
|
||||
return Collections.unmodifiableList(metrics);
|
||||
}
|
||||
|
||||
|
||||
@@ -95,6 +95,11 @@ public class NamePatternFilterTests {
|
||||
|
||||
private boolean getNamesCalled;
|
||||
|
||||
@Override
|
||||
protected Object getOptionalValue(Object source, String name) {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object getValue(Object source, String name) {
|
||||
return name;
|
||||
|
||||
Reference in New Issue
Block a user