From 23233c3041c103b26b02c0f2cc05a8fb252abfb7 Mon Sep 17 00:00:00 2001 From: Rossen Stoyanchev Date: Tue, 19 May 2020 07:38:56 +0100 Subject: [PATCH] Shared read-only instance of UrlPathHelper In many places UrlPathHelper is created and used without any customizations, in some cases repeatedly. This commit adds a shared read-only UrlPathHelper instance with default settings. See gh-25100 --- .../MockHttpServletRequestBuilder.java | 5 +- .../setup/PatternMappingFilterProxy.java | 6 +- .../web/util/UrlPathHelper.java | 34 +++++++- .../web/util/UrlPathHelperTests.java | 85 +++++++++---------- .../function/DefaultServerRequest.java | 3 +- .../condition/PatternsRequestCondition.java | 2 +- ...stractMessageConverterMethodProcessor.java | 2 +- ...vletCookieValueMethodArgumentResolver.java | 4 +- .../servlet/resource/ResourceUrlProvider.java | 4 +- .../support/AbstractFlashMapManager.java | 2 +- .../support/ServletUriComponentsBuilder.java | 2 +- 11 files changed, 83 insertions(+), 66 deletions(-) diff --git a/spring-test/src/main/java/org/springframework/test/web/servlet/request/MockHttpServletRequestBuilder.java b/spring-test/src/main/java/org/springframework/test/web/servlet/request/MockHttpServletRequestBuilder.java index e315c948a8a..8b844e5b1d3 100644 --- a/spring-test/src/main/java/org/springframework/test/web/servlet/request/MockHttpServletRequestBuilder.java +++ b/spring-test/src/main/java/org/springframework/test/web/servlet/request/MockHttpServletRequestBuilder.java @@ -83,9 +83,6 @@ import org.springframework.web.util.UrlPathHelper; public class MockHttpServletRequestBuilder implements ConfigurableSmartRequestBuilder, Mergeable { - private static final UrlPathHelper urlPathHelper = new UrlPathHelper(); - - private final String method; private final URI url; @@ -781,7 +778,7 @@ public class MockHttpServletRequestBuilder } String extraPath = requestUri.substring(this.contextPath.length() + this.servletPath.length()); this.pathInfo = (StringUtils.hasText(extraPath) ? - urlPathHelper.decodeRequestString(request, extraPath) : null); + UrlPathHelper.defaultInstance.decodeRequestString(request, extraPath) : null); } request.setPathInfo(this.pathInfo); } diff --git a/spring-test/src/main/java/org/springframework/test/web/servlet/setup/PatternMappingFilterProxy.java b/spring-test/src/main/java/org/springframework/test/web/servlet/setup/PatternMappingFilterProxy.java index fdf0594536e..314f8ada3c0 100644 --- a/spring-test/src/main/java/org/springframework/test/web/servlet/setup/PatternMappingFilterProxy.java +++ b/spring-test/src/main/java/org/springframework/test/web/servlet/setup/PatternMappingFilterProxy.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2019 the original author or authors. + * Copyright 2002-2020 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. @@ -45,8 +45,6 @@ final class PatternMappingFilterProxy implements Filter { private static final String PATH_MAPPING_PATTERN = "/*"; - private static final UrlPathHelper urlPathHelper = new UrlPathHelper(); - private final Filter delegate; /** Patterns that require an exact match, e.g. "/test" */ @@ -96,7 +94,7 @@ final class PatternMappingFilterProxy implements Filter { throws IOException, ServletException { HttpServletRequest httpRequest = (HttpServletRequest) request; - String requestPath = urlPathHelper.getPathWithinApplication(httpRequest); + String requestPath = UrlPathHelper.defaultInstance.getPathWithinApplication(httpRequest); if (matches(requestPath)) { this.delegate.doFilter(request, response, filterChain); diff --git a/spring-web/src/main/java/org/springframework/web/util/UrlPathHelper.java b/spring-web/src/main/java/org/springframework/web/util/UrlPathHelper.java index 6b0e38bba07..5e3ed3b52ee 100644 --- a/spring-web/src/main/java/org/springframework/web/util/UrlPathHelper.java +++ b/spring-web/src/main/java/org/springframework/web/util/UrlPathHelper.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2019 the original author or authors. + * Copyright 2002-2020 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. @@ -626,4 +626,36 @@ public class UrlPathHelper { return !flagToUse; } + + /** + * Shared, read-only instance of {@code UrlPathHelper}. Uses default settings: + * + */ + public final static UrlPathHelper defaultInstance = new UrlPathHelper() { + + @Override + public void setAlwaysUseFullPath(boolean alwaysUseFullPath) { + throw new UnsupportedOperationException(); + } + + @Override + public void setUrlDecode(boolean urlDecode) { + throw new UnsupportedOperationException(); + } + + @Override + public void setRemoveSemicolonContent(boolean removeSemicolonContent) { + throw new UnsupportedOperationException(); + } + + @Override + public void setDefaultEncoding(String defaultEncoding) { + throw new UnsupportedOperationException(); + } + }; } diff --git a/spring-web/src/test/java/org/springframework/web/util/UrlPathHelperTests.java b/spring-web/src/test/java/org/springframework/web/util/UrlPathHelperTests.java index 82a069ae128..ee53ff82079 100644 --- a/spring-web/src/test/java/org/springframework/web/util/UrlPathHelperTests.java +++ b/spring-web/src/test/java/org/springframework/web/util/UrlPathHelperTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2019 the original author or authors. + * Copyright 2002-2020 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. @@ -16,8 +16,6 @@ package org.springframework.web.util; -import java.io.UnsupportedEncodingException; - import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; @@ -46,7 +44,7 @@ public class UrlPathHelperTests { request.setContextPath("/petclinic"); request.setRequestURI("/petclinic/welcome.html"); - assertThat(helper.getPathWithinApplication(request)).as("Incorrect path returned").isEqualTo("/welcome.html"); + assertThat(helper.getPathWithinApplication(request)).isEqualTo("/welcome.html"); } @Test @@ -62,7 +60,7 @@ public class UrlPathHelperTests { request.setContextPath("/"); request.setRequestURI("/welcome.html"); - assertThat(helper.getPathWithinApplication(request)).as("Incorrect path returned").isEqualTo("/welcome.html"); + assertThat(helper.getPathWithinApplication(request)).isEqualTo("/welcome.html"); } @Test @@ -71,7 +69,7 @@ public class UrlPathHelperTests { request.setServletPath("/main"); request.setRequestURI("/petclinic/main/welcome.html"); - assertThat(helper.getPathWithinServletMapping(request)).as("Incorrect path returned").isEqualTo("/welcome.html"); + assertThat(helper.getPathWithinServletMapping(request)).isEqualTo("/welcome.html"); } @Test @@ -81,12 +79,10 @@ public class UrlPathHelperTests { request.setServletPath("/main"); request.setRequestURI("/petclinic/main/welcome.html"); - assertThat(helper.getLookupPathForRequest(request)).as("Incorrect path returned").isEqualTo("/main/welcome.html"); + assertThat(helper.getLookupPathForRequest(request)).isEqualTo("/main/welcome.html"); } - // SPR-11101 - - @Test + @Test // SPR-11101 public void getPathWithinServletWithoutUrlDecoding() { request.setContextPath("/SPR-11101"); request.setServletPath("/test_url_decoding/a/b"); @@ -101,32 +97,29 @@ public class UrlPathHelperTests { @Test public void getRequestUri() { request.setRequestURI("/welcome.html"); - assertThat(helper.getRequestUri(request)).as("Incorrect path returned").isEqualTo("/welcome.html"); + assertThat(helper.getRequestUri(request)).isEqualTo("/welcome.html"); request.setRequestURI("/foo%20bar"); - assertThat(helper.getRequestUri(request)).as("Incorrect path returned").isEqualTo("/foo bar"); + assertThat(helper.getRequestUri(request)).isEqualTo("/foo bar"); request.setRequestURI("/foo+bar"); - assertThat(helper.getRequestUri(request)).as("Incorrect path returned").isEqualTo("/foo+bar"); + assertThat(helper.getRequestUri(request)).isEqualTo("/foo+bar"); } @Test - public void getRequestRemoveSemicolonContent() throws UnsupportedEncodingException { + public void getRequestRemoveSemicolonContent() { helper.setRemoveSemicolonContent(true); - request.setRequestURI("/foo;f=F;o=O;o=O/bar;b=B;a=A;r=R"); assertThat(helper.getRequestUri(request)).isEqualTo("/foo/bar"); // SPR-13455 - - request.setServletPath("/foo/1"); request.setRequestURI("/foo/;test/1"); - + request.setServletPath("/foo/1"); assertThat(helper.getRequestUri(request)).isEqualTo("/foo/1"); } @Test - public void getRequestKeepSemicolonContent() throws UnsupportedEncodingException { + public void getRequestKeepSemicolonContent() { helper.setRemoveSemicolonContent(false); request.setRequestURI("/foo;a=b;c=d"); @@ -139,7 +132,6 @@ public class UrlPathHelperTests { assertThat(helper.getRequestUri(request)).as("jsessionid should always be removed").isEqualTo("/foo;a=b;c=d"); // SPR-10398 - request.setRequestURI("/foo;a=b;JSESSIONID=c0o7fszeb1;c=d"); assertThat(helper.getRequestUri(request)).as("JSESSIONID should always be removed").isEqualTo("/foo;a=b;c=d"); } @@ -178,37 +170,36 @@ public class UrlPathHelperTests { // @Test - public void tomcatDefaultServletRoot() throws Exception { + public void tomcatDefaultServletRoot() { request.setContextPath("/test"); - request.setPathInfo(null); request.setServletPath("/"); + request.setPathInfo(null); request.setRequestURI("/test/"); assertThat(helper.getLookupPathForRequest(request)).isEqualTo("/"); } @Test - public void tomcatDefaultServletFile() throws Exception { + public void tomcatDefaultServletFile() { request.setContextPath("/test"); - request.setPathInfo(null); request.setServletPath("/foo"); + request.setPathInfo(null); request.setRequestURI("/test/foo"); assertThat(helper.getLookupPathForRequest(request)).isEqualTo("/foo"); } @Test - public void tomcatDefaultServletFolder() throws Exception { + public void tomcatDefaultServletFolder() { request.setContextPath("/test"); - request.setPathInfo(null); request.setServletPath("/foo/"); + request.setPathInfo(null); request.setRequestURI("/test/foo/"); assertThat(helper.getLookupPathForRequest(request)).isEqualTo("/foo/"); } - //SPR-12372 & SPR-13455 - @Test - public void removeDuplicateSlashesInPath() throws Exception { + @Test //SPR-12372, SPR-13455 + public void removeDuplicateSlashesInPath() { request.setContextPath("/SPR-12372"); request.setPathInfo(null); request.setServletPath("/foo/bar/"); @@ -229,7 +220,7 @@ public class UrlPathHelperTests { } @Test - public void wasDefaultServletRoot() throws Exception { + public void wasDefaultServletRoot() { request.setContextPath("/test"); request.setPathInfo("/"); request.setServletPath(""); @@ -240,13 +231,13 @@ public class UrlPathHelperTests { } @Test - public void wasDefaultServletRootWithCompliantSetting() throws Exception { + public void wasDefaultServletRootWithCompliantSetting() { request.setAttribute(WEBSPHERE_URI_ATTRIBUTE, "/test/"); tomcatDefaultServletRoot(); } @Test - public void wasDefaultServletFile() throws Exception { + public void wasDefaultServletFile() { request.setContextPath("/test"); request.setPathInfo("/foo"); request.setServletPath(""); @@ -257,13 +248,13 @@ public class UrlPathHelperTests { } @Test - public void wasDefaultServletFileWithCompliantSetting() throws Exception { + public void wasDefaultServletFileWithCompliantSetting() { request.setAttribute(WEBSPHERE_URI_ATTRIBUTE, "/test/foo"); tomcatDefaultServletFile(); } @Test - public void wasDefaultServletFolder() throws Exception { + public void wasDefaultServletFolder() { request.setContextPath("/test"); request.setPathInfo("/foo/"); request.setServletPath(""); @@ -274,7 +265,7 @@ public class UrlPathHelperTests { } @Test - public void wasDefaultServletFolderWithCompliantSetting() throws Exception { + public void wasDefaultServletFolderWithCompliantSetting() { UrlPathHelper.websphereComplianceFlag = true; try { request.setAttribute(WEBSPHERE_URI_ATTRIBUTE, "/test/foo/"); @@ -291,7 +282,7 @@ public class UrlPathHelperTests { // @Test - public void tomcatCasualServletRoot() throws Exception { + public void tomcatCasualServletRoot() { request.setContextPath("/test"); request.setPathInfo("/"); request.setServletPath("/foo"); @@ -303,7 +294,7 @@ public class UrlPathHelperTests { @Disabled // test the root mapping for /foo/* w/o a trailing slash - //foo @Test - public void tomcatCasualServletRootWithMissingSlash() throws Exception { + public void tomcatCasualServletRootWithMissingSlash() { request.setContextPath("/test"); request.setPathInfo(null); request.setServletPath("/foo"); @@ -313,7 +304,7 @@ public class UrlPathHelperTests { } @Test - public void tomcatCasualServletFile() throws Exception { + public void tomcatCasualServletFile() { request.setContextPath("/test"); request.setPathInfo("/foo"); request.setServletPath("/foo"); @@ -323,7 +314,7 @@ public class UrlPathHelperTests { } @Test - public void tomcatCasualServletFolder() throws Exception { + public void tomcatCasualServletFolder() { request.setContextPath("/test"); request.setPathInfo("/foo/"); request.setServletPath("/foo"); @@ -333,7 +324,7 @@ public class UrlPathHelperTests { } @Test - public void wasCasualServletRoot() throws Exception { + public void wasCasualServletRoot() { request.setContextPath("/test"); request.setPathInfo(null); request.setServletPath("/foo/"); @@ -344,7 +335,7 @@ public class UrlPathHelperTests { } @Test - public void wasCasualServletRootWithCompliantSetting() throws Exception { + public void wasCasualServletRootWithCompliantSetting() { request.setAttribute(WEBSPHERE_URI_ATTRIBUTE, "/test/foo/"); tomcatCasualServletRoot(); } @@ -352,7 +343,7 @@ public class UrlPathHelperTests { @Disabled // test the root mapping for /foo/* w/o a trailing slash - //foo @Test - public void wasCasualServletRootWithMissingSlash() throws Exception { + public void wasCasualServletRootWithMissingSlash() { request.setContextPath("/test"); request.setPathInfo(null); request.setServletPath("/foo"); @@ -364,13 +355,13 @@ public class UrlPathHelperTests { @Disabled @Test - public void wasCasualServletRootWithMissingSlashWithCompliantSetting() throws Exception { + public void wasCasualServletRootWithMissingSlashWithCompliantSetting() { request.setAttribute(WEBSPHERE_URI_ATTRIBUTE, "/test/foo"); tomcatCasualServletRootWithMissingSlash(); } @Test - public void wasCasualServletFile() throws Exception { + public void wasCasualServletFile() { request.setContextPath("/test"); request.setPathInfo("/foo"); request.setServletPath("/foo"); @@ -381,13 +372,13 @@ public class UrlPathHelperTests { } @Test - public void wasCasualServletFileWithCompliantSetting() throws Exception { + public void wasCasualServletFileWithCompliantSetting() { request.setAttribute(WEBSPHERE_URI_ATTRIBUTE, "/test/foo/foo"); tomcatCasualServletFile(); } @Test - public void wasCasualServletFolder() throws Exception { + public void wasCasualServletFolder() { request.setContextPath("/test"); request.setPathInfo("/foo/"); request.setServletPath("/foo"); @@ -398,7 +389,7 @@ public class UrlPathHelperTests { } @Test - public void wasCasualServletFolderWithCompliantSetting() throws Exception { + public void wasCasualServletFolderWithCompliantSetting() { request.setAttribute(WEBSPHERE_URI_ATTRIBUTE, "/test/foo/foo/"); tomcatCasualServletFolder(); } diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/function/DefaultServerRequest.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/function/DefaultServerRequest.java index d5405ef9e89..fca3dbe9d64 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/function/DefaultServerRequest.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/function/DefaultServerRequest.java @@ -132,8 +132,7 @@ class DefaultServerRequest implements ServerRequest { public String path() { String path = (String) servletRequest().getAttribute(HandlerMapping.LOOKUP_PATH); if (path == null) { - UrlPathHelper helper = new UrlPathHelper(); - path = helper.getLookupPathForRequest(servletRequest()); + path = UrlPathHelper.defaultInstance.getLookupPathForRequest(servletRequest()); } return path; } diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/condition/PatternsRequestCondition.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/condition/PatternsRequestCondition.java index 846e4f64629..419c7697911 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/condition/PatternsRequestCondition.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/condition/PatternsRequestCondition.java @@ -129,7 +129,7 @@ public final class PatternsRequestCondition extends AbstractRequestCondition fileExtensions) { this.patterns = Collections.unmodifiableSet(prependLeadingSlash(patterns)); - this.pathHelper = urlPathHelper != null ? urlPathHelper : new UrlPathHelper(); + this.pathHelper = urlPathHelper != null ? urlPathHelper : UrlPathHelper.defaultInstance; this.pathMatcher = pathMatcher != null ? pathMatcher : new AntPathMatcher(); this.useSuffixPatternMatch = useSuffixPatternMatch; this.useTrailingSlashMatch = useTrailingSlashMatch; diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/AbstractMessageConverterMethodProcessor.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/AbstractMessageConverterMethodProcessor.java index 4e83bab4f83..fddc3e93294 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/AbstractMessageConverterMethodProcessor.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/AbstractMessageConverterMethodProcessor.java @@ -91,7 +91,7 @@ public abstract class AbstractMessageConverterMethodProcessor extends AbstractMe new ParameterizedTypeReference>() { }.getType(); - private static final UrlPathHelper decodingUrlPathHelper = new UrlPathHelper(); + private static final UrlPathHelper decodingUrlPathHelper = UrlPathHelper.defaultInstance; private static final UrlPathHelper rawUrlPathHelper = new UrlPathHelper(); diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/ServletCookieValueMethodArgumentResolver.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/ServletCookieValueMethodArgumentResolver.java index d1928fb9f65..97c66a581a3 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/ServletCookieValueMethodArgumentResolver.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/ServletCookieValueMethodArgumentResolver.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2017 the original author or authors. + * Copyright 2002-2020 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. @@ -37,7 +37,7 @@ import org.springframework.web.util.WebUtils; */ public class ServletCookieValueMethodArgumentResolver extends AbstractCookieValueMethodArgumentResolver { - private UrlPathHelper urlPathHelper = new UrlPathHelper(); + private UrlPathHelper urlPathHelper = UrlPathHelper.defaultInstance; public ServletCookieValueMethodArgumentResolver(@Nullable ConfigurableBeanFactory beanFactory) { diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/resource/ResourceUrlProvider.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/resource/ResourceUrlProvider.java index 8abd1b5ef97..690de8df2ee 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/resource/ResourceUrlProvider.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/resource/ResourceUrlProvider.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2019 the original author or authors. + * Copyright 2002-2020 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. @@ -54,7 +54,7 @@ public class ResourceUrlProvider implements ApplicationListener