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
pull/4511/merge
Andy Wilkinson 9 years ago
parent f25a5e3b77
commit 8e0d3ed0eb

@ -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()) {
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;

Loading…
Cancel
Save