From ea51cfabcad13b3b1bff63d899ec4f2ebba76078 Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Mon, 4 Jun 2018 15:43:38 +0100 Subject: [PATCH] Avoid uri tag explosion when use of path variable is undetected MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Previously, WebMvcTags would fall back to using the request’s path info if Spring MVC’s best matching path pattern attribute was not available. For non-Spring MVC web frameworks that support path variables, such as Jersey, this led to an explosion of URI tags that could exhaust the heap. Closes gh-12447 --- .../metrics/web/servlet/WebMvcTags.java | 6 ++--- .../endpoint/web/servlet/WebMvcTagsTests.java | 23 ++++++++++++++----- 2 files changed, 20 insertions(+), 9 deletions(-) diff --git a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/web/servlet/WebMvcTags.java b/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/web/servlet/WebMvcTags.java index b3218fd31e..f469b6ba72 100644 --- a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/web/servlet/WebMvcTags.java +++ b/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/web/servlet/WebMvcTags.java @@ -77,8 +77,9 @@ public final class WebMvcTags { /** * Creates a {@code uri} tag based on the URI of the given {@code request}. Uses the * {@link HandlerMapping#BEST_MATCHING_PATTERN_ATTRIBUTE} best matching pattern if - * available, falling back to the request's {@link HttpServletRequest#getPathInfo() - * path info} if necessary. + * available. Falling back to {@code REDIRECTION} for 3xx responses, {@code NOT_FOUND} + * for 404 responses, {@code root} for requests with no path info, and {@code UNKNOWN} + * for all other requests. * @param request the request * @param response the response * @return the uri tag derived from the request @@ -102,7 +103,6 @@ public final class WebMvcTags { if (pathInfo.isEmpty()) { return URI_ROOT; } - return Tag.of("uri", pathInfo); } return URI_UNKNOWN; } diff --git a/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/web/servlet/WebMvcTagsTests.java b/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/web/servlet/WebMvcTagsTests.java index c85b453762..f871b918a0 100644 --- a/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/web/servlet/WebMvcTagsTests.java +++ b/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/web/servlet/WebMvcTagsTests.java @@ -38,12 +38,6 @@ public class WebMvcTagsTests { private final MockHttpServletResponse response = new MockHttpServletResponse(); - @Test - public void uriTrailingSlashesAreSuppressed() { - this.request.setPathInfo("//spring/"); - assertThat(WebMvcTags.uri(this.request, null).getValue()).isEqualTo("/spring"); - } - @Test public void uriTagValueIsBestMatchingPatternWhenAvailable() { this.request.setAttribute(HandlerMapping.BEST_MATCHING_PATTERN_ATTRIBUTE, @@ -53,6 +47,23 @@ public class WebMvcTagsTests { assertThat(tag.getValue()).isEqualTo("/spring"); } + @Test + public void uriTagValueIsRootWhenRequestHasNoPatternOrPathInfo() { + assertThat(WebMvcTags.uri(this.request, null).getValue()).isEqualTo("root"); + } + + @Test + public void uriTagValueIsRootWhenRequestHasNoPatternAndSlashPathInfo() { + this.request.setPathInfo("/"); + assertThat(WebMvcTags.uri(this.request, null).getValue()).isEqualTo("root"); + } + + @Test + public void uriTagValueIsUnknownWhenRequestHasNoPatternAndNonRootPathInfo() { + this.request.setPathInfo("/example"); + assertThat(WebMvcTags.uri(this.request, null).getValue()).isEqualTo("UNKNOWN"); + } + @Test public void uriTagValueIsRedirectionWhenResponseStatusIs3xx() { this.response.setStatus(301);