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
This commit is contained in:
Rossen Stoyanchev 2020-05-19 07:38:56 +01:00
parent 92f7587a40
commit 23233c3041
11 changed files with 83 additions and 66 deletions

View File

@ -83,9 +83,6 @@ import org.springframework.web.util.UrlPathHelper;
public class MockHttpServletRequestBuilder public class MockHttpServletRequestBuilder
implements ConfigurableSmartRequestBuilder<MockHttpServletRequestBuilder>, Mergeable { implements ConfigurableSmartRequestBuilder<MockHttpServletRequestBuilder>, Mergeable {
private static final UrlPathHelper urlPathHelper = new UrlPathHelper();
private final String method; private final String method;
private final URI url; private final URI url;
@ -781,7 +778,7 @@ public class MockHttpServletRequestBuilder
} }
String extraPath = requestUri.substring(this.contextPath.length() + this.servletPath.length()); String extraPath = requestUri.substring(this.contextPath.length() + this.servletPath.length());
this.pathInfo = (StringUtils.hasText(extraPath) ? this.pathInfo = (StringUtils.hasText(extraPath) ?
urlPathHelper.decodeRequestString(request, extraPath) : null); UrlPathHelper.defaultInstance.decodeRequestString(request, extraPath) : null);
} }
request.setPathInfo(this.pathInfo); request.setPathInfo(this.pathInfo);
} }

View File

@ -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"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with 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 String PATH_MAPPING_PATTERN = "/*";
private static final UrlPathHelper urlPathHelper = new UrlPathHelper();
private final Filter delegate; private final Filter delegate;
/** Patterns that require an exact match, e.g. "/test" */ /** Patterns that require an exact match, e.g. "/test" */
@ -96,7 +94,7 @@ final class PatternMappingFilterProxy implements Filter {
throws IOException, ServletException { throws IOException, ServletException {
HttpServletRequest httpRequest = (HttpServletRequest) request; HttpServletRequest httpRequest = (HttpServletRequest) request;
String requestPath = urlPathHelper.getPathWithinApplication(httpRequest); String requestPath = UrlPathHelper.defaultInstance.getPathWithinApplication(httpRequest);
if (matches(requestPath)) { if (matches(requestPath)) {
this.delegate.doFilter(request, response, filterChain); this.delegate.doFilter(request, response, filterChain);

View File

@ -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"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -626,4 +626,36 @@ public class UrlPathHelper {
return !flagToUse; return !flagToUse;
} }
/**
* Shared, read-only instance of {@code UrlPathHelper}. Uses default settings:
* <ul>
* <li>{@code alwaysUseFullPath=false}
* <li>{@code urlDecode=true}
* <li>{@code removeSemicolon=true}
* <li>{@code defaultEncoding=}{@link WebUtils#DEFAULT_CHARACTER_ENCODING}
* </ul>
*/
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();
}
};
} }

View File

@ -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"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -16,8 +16,6 @@
package org.springframework.web.util; package org.springframework.web.util;
import java.io.UnsupportedEncodingException;
import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
@ -46,7 +44,7 @@ public class UrlPathHelperTests {
request.setContextPath("/petclinic"); request.setContextPath("/petclinic");
request.setRequestURI("/petclinic/welcome.html"); request.setRequestURI("/petclinic/welcome.html");
assertThat(helper.getPathWithinApplication(request)).as("Incorrect path returned").isEqualTo("/welcome.html"); assertThat(helper.getPathWithinApplication(request)).isEqualTo("/welcome.html");
} }
@Test @Test
@ -62,7 +60,7 @@ public class UrlPathHelperTests {
request.setContextPath("/"); request.setContextPath("/");
request.setRequestURI("/welcome.html"); request.setRequestURI("/welcome.html");
assertThat(helper.getPathWithinApplication(request)).as("Incorrect path returned").isEqualTo("/welcome.html"); assertThat(helper.getPathWithinApplication(request)).isEqualTo("/welcome.html");
} }
@Test @Test
@ -71,7 +69,7 @@ public class UrlPathHelperTests {
request.setServletPath("/main"); request.setServletPath("/main");
request.setRequestURI("/petclinic/main/welcome.html"); 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 @Test
@ -81,12 +79,10 @@ public class UrlPathHelperTests {
request.setServletPath("/main"); request.setServletPath("/main");
request.setRequestURI("/petclinic/main/welcome.html"); 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 // SPR-11101
@Test
public void getPathWithinServletWithoutUrlDecoding() { public void getPathWithinServletWithoutUrlDecoding() {
request.setContextPath("/SPR-11101"); request.setContextPath("/SPR-11101");
request.setServletPath("/test_url_decoding/a/b"); request.setServletPath("/test_url_decoding/a/b");
@ -101,32 +97,29 @@ public class UrlPathHelperTests {
@Test @Test
public void getRequestUri() { public void getRequestUri() {
request.setRequestURI("/welcome.html"); 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"); 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"); request.setRequestURI("/foo+bar");
assertThat(helper.getRequestUri(request)).as("Incorrect path returned").isEqualTo("/foo+bar"); assertThat(helper.getRequestUri(request)).isEqualTo("/foo+bar");
} }
@Test @Test
public void getRequestRemoveSemicolonContent() throws UnsupportedEncodingException { public void getRequestRemoveSemicolonContent() {
helper.setRemoveSemicolonContent(true); helper.setRemoveSemicolonContent(true);
request.setRequestURI("/foo;f=F;o=O;o=O/bar;b=B;a=A;r=R"); request.setRequestURI("/foo;f=F;o=O;o=O/bar;b=B;a=A;r=R");
assertThat(helper.getRequestUri(request)).isEqualTo("/foo/bar"); assertThat(helper.getRequestUri(request)).isEqualTo("/foo/bar");
// SPR-13455 // SPR-13455
request.setServletPath("/foo/1");
request.setRequestURI("/foo/;test/1"); request.setRequestURI("/foo/;test/1");
request.setServletPath("/foo/1");
assertThat(helper.getRequestUri(request)).isEqualTo("/foo/1"); assertThat(helper.getRequestUri(request)).isEqualTo("/foo/1");
} }
@Test @Test
public void getRequestKeepSemicolonContent() throws UnsupportedEncodingException { public void getRequestKeepSemicolonContent() {
helper.setRemoveSemicolonContent(false); helper.setRemoveSemicolonContent(false);
request.setRequestURI("/foo;a=b;c=d"); 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"); assertThat(helper.getRequestUri(request)).as("jsessionid should always be removed").isEqualTo("/foo;a=b;c=d");
// SPR-10398 // SPR-10398
request.setRequestURI("/foo;a=b;JSESSIONID=c0o7fszeb1;c=d"); 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"); assertThat(helper.getRequestUri(request)).as("JSESSIONID should always be removed").isEqualTo("/foo;a=b;c=d");
} }
@ -178,37 +170,36 @@ public class UrlPathHelperTests {
// //
@Test @Test
public void tomcatDefaultServletRoot() throws Exception { public void tomcatDefaultServletRoot() {
request.setContextPath("/test"); request.setContextPath("/test");
request.setPathInfo(null);
request.setServletPath("/"); request.setServletPath("/");
request.setPathInfo(null);
request.setRequestURI("/test/"); request.setRequestURI("/test/");
assertThat(helper.getLookupPathForRequest(request)).isEqualTo("/"); assertThat(helper.getLookupPathForRequest(request)).isEqualTo("/");
} }
@Test @Test
public void tomcatDefaultServletFile() throws Exception { public void tomcatDefaultServletFile() {
request.setContextPath("/test"); request.setContextPath("/test");
request.setPathInfo(null);
request.setServletPath("/foo"); request.setServletPath("/foo");
request.setPathInfo(null);
request.setRequestURI("/test/foo"); request.setRequestURI("/test/foo");
assertThat(helper.getLookupPathForRequest(request)).isEqualTo("/foo"); assertThat(helper.getLookupPathForRequest(request)).isEqualTo("/foo");
} }
@Test @Test
public void tomcatDefaultServletFolder() throws Exception { public void tomcatDefaultServletFolder() {
request.setContextPath("/test"); request.setContextPath("/test");
request.setPathInfo(null);
request.setServletPath("/foo/"); request.setServletPath("/foo/");
request.setPathInfo(null);
request.setRequestURI("/test/foo/"); request.setRequestURI("/test/foo/");
assertThat(helper.getLookupPathForRequest(request)).isEqualTo("/foo/"); assertThat(helper.getLookupPathForRequest(request)).isEqualTo("/foo/");
} }
//SPR-12372 & SPR-13455 @Test //SPR-12372, SPR-13455
@Test public void removeDuplicateSlashesInPath() {
public void removeDuplicateSlashesInPath() throws Exception {
request.setContextPath("/SPR-12372"); request.setContextPath("/SPR-12372");
request.setPathInfo(null); request.setPathInfo(null);
request.setServletPath("/foo/bar/"); request.setServletPath("/foo/bar/");
@ -229,7 +220,7 @@ public class UrlPathHelperTests {
} }
@Test @Test
public void wasDefaultServletRoot() throws Exception { public void wasDefaultServletRoot() {
request.setContextPath("/test"); request.setContextPath("/test");
request.setPathInfo("/"); request.setPathInfo("/");
request.setServletPath(""); request.setServletPath("");
@ -240,13 +231,13 @@ public class UrlPathHelperTests {
} }
@Test @Test
public void wasDefaultServletRootWithCompliantSetting() throws Exception { public void wasDefaultServletRootWithCompliantSetting() {
request.setAttribute(WEBSPHERE_URI_ATTRIBUTE, "/test/"); request.setAttribute(WEBSPHERE_URI_ATTRIBUTE, "/test/");
tomcatDefaultServletRoot(); tomcatDefaultServletRoot();
} }
@Test @Test
public void wasDefaultServletFile() throws Exception { public void wasDefaultServletFile() {
request.setContextPath("/test"); request.setContextPath("/test");
request.setPathInfo("/foo"); request.setPathInfo("/foo");
request.setServletPath(""); request.setServletPath("");
@ -257,13 +248,13 @@ public class UrlPathHelperTests {
} }
@Test @Test
public void wasDefaultServletFileWithCompliantSetting() throws Exception { public void wasDefaultServletFileWithCompliantSetting() {
request.setAttribute(WEBSPHERE_URI_ATTRIBUTE, "/test/foo"); request.setAttribute(WEBSPHERE_URI_ATTRIBUTE, "/test/foo");
tomcatDefaultServletFile(); tomcatDefaultServletFile();
} }
@Test @Test
public void wasDefaultServletFolder() throws Exception { public void wasDefaultServletFolder() {
request.setContextPath("/test"); request.setContextPath("/test");
request.setPathInfo("/foo/"); request.setPathInfo("/foo/");
request.setServletPath(""); request.setServletPath("");
@ -274,7 +265,7 @@ public class UrlPathHelperTests {
} }
@Test @Test
public void wasDefaultServletFolderWithCompliantSetting() throws Exception { public void wasDefaultServletFolderWithCompliantSetting() {
UrlPathHelper.websphereComplianceFlag = true; UrlPathHelper.websphereComplianceFlag = true;
try { try {
request.setAttribute(WEBSPHERE_URI_ATTRIBUTE, "/test/foo/"); request.setAttribute(WEBSPHERE_URI_ATTRIBUTE, "/test/foo/");
@ -291,7 +282,7 @@ public class UrlPathHelperTests {
// //
@Test @Test
public void tomcatCasualServletRoot() throws Exception { public void tomcatCasualServletRoot() {
request.setContextPath("/test"); request.setContextPath("/test");
request.setPathInfo("/"); request.setPathInfo("/");
request.setServletPath("/foo"); request.setServletPath("/foo");
@ -303,7 +294,7 @@ public class UrlPathHelperTests {
@Disabled @Disabled
// test the root mapping for /foo/* w/o a trailing slash - <host>/<context>/foo // test the root mapping for /foo/* w/o a trailing slash - <host>/<context>/foo
@Test @Test
public void tomcatCasualServletRootWithMissingSlash() throws Exception { public void tomcatCasualServletRootWithMissingSlash() {
request.setContextPath("/test"); request.setContextPath("/test");
request.setPathInfo(null); request.setPathInfo(null);
request.setServletPath("/foo"); request.setServletPath("/foo");
@ -313,7 +304,7 @@ public class UrlPathHelperTests {
} }
@Test @Test
public void tomcatCasualServletFile() throws Exception { public void tomcatCasualServletFile() {
request.setContextPath("/test"); request.setContextPath("/test");
request.setPathInfo("/foo"); request.setPathInfo("/foo");
request.setServletPath("/foo"); request.setServletPath("/foo");
@ -323,7 +314,7 @@ public class UrlPathHelperTests {
} }
@Test @Test
public void tomcatCasualServletFolder() throws Exception { public void tomcatCasualServletFolder() {
request.setContextPath("/test"); request.setContextPath("/test");
request.setPathInfo("/foo/"); request.setPathInfo("/foo/");
request.setServletPath("/foo"); request.setServletPath("/foo");
@ -333,7 +324,7 @@ public class UrlPathHelperTests {
} }
@Test @Test
public void wasCasualServletRoot() throws Exception { public void wasCasualServletRoot() {
request.setContextPath("/test"); request.setContextPath("/test");
request.setPathInfo(null); request.setPathInfo(null);
request.setServletPath("/foo/"); request.setServletPath("/foo/");
@ -344,7 +335,7 @@ public class UrlPathHelperTests {
} }
@Test @Test
public void wasCasualServletRootWithCompliantSetting() throws Exception { public void wasCasualServletRootWithCompliantSetting() {
request.setAttribute(WEBSPHERE_URI_ATTRIBUTE, "/test/foo/"); request.setAttribute(WEBSPHERE_URI_ATTRIBUTE, "/test/foo/");
tomcatCasualServletRoot(); tomcatCasualServletRoot();
} }
@ -352,7 +343,7 @@ public class UrlPathHelperTests {
@Disabled @Disabled
// test the root mapping for /foo/* w/o a trailing slash - <host>/<context>/foo // test the root mapping for /foo/* w/o a trailing slash - <host>/<context>/foo
@Test @Test
public void wasCasualServletRootWithMissingSlash() throws Exception { public void wasCasualServletRootWithMissingSlash() {
request.setContextPath("/test"); request.setContextPath("/test");
request.setPathInfo(null); request.setPathInfo(null);
request.setServletPath("/foo"); request.setServletPath("/foo");
@ -364,13 +355,13 @@ public class UrlPathHelperTests {
@Disabled @Disabled
@Test @Test
public void wasCasualServletRootWithMissingSlashWithCompliantSetting() throws Exception { public void wasCasualServletRootWithMissingSlashWithCompliantSetting() {
request.setAttribute(WEBSPHERE_URI_ATTRIBUTE, "/test/foo"); request.setAttribute(WEBSPHERE_URI_ATTRIBUTE, "/test/foo");
tomcatCasualServletRootWithMissingSlash(); tomcatCasualServletRootWithMissingSlash();
} }
@Test @Test
public void wasCasualServletFile() throws Exception { public void wasCasualServletFile() {
request.setContextPath("/test"); request.setContextPath("/test");
request.setPathInfo("/foo"); request.setPathInfo("/foo");
request.setServletPath("/foo"); request.setServletPath("/foo");
@ -381,13 +372,13 @@ public class UrlPathHelperTests {
} }
@Test @Test
public void wasCasualServletFileWithCompliantSetting() throws Exception { public void wasCasualServletFileWithCompliantSetting() {
request.setAttribute(WEBSPHERE_URI_ATTRIBUTE, "/test/foo/foo"); request.setAttribute(WEBSPHERE_URI_ATTRIBUTE, "/test/foo/foo");
tomcatCasualServletFile(); tomcatCasualServletFile();
} }
@Test @Test
public void wasCasualServletFolder() throws Exception { public void wasCasualServletFolder() {
request.setContextPath("/test"); request.setContextPath("/test");
request.setPathInfo("/foo/"); request.setPathInfo("/foo/");
request.setServletPath("/foo"); request.setServletPath("/foo");
@ -398,7 +389,7 @@ public class UrlPathHelperTests {
} }
@Test @Test
public void wasCasualServletFolderWithCompliantSetting() throws Exception { public void wasCasualServletFolderWithCompliantSetting() {
request.setAttribute(WEBSPHERE_URI_ATTRIBUTE, "/test/foo/foo/"); request.setAttribute(WEBSPHERE_URI_ATTRIBUTE, "/test/foo/foo/");
tomcatCasualServletFolder(); tomcatCasualServletFolder();
} }

View File

@ -132,8 +132,7 @@ class DefaultServerRequest implements ServerRequest {
public String path() { public String path() {
String path = (String) servletRequest().getAttribute(HandlerMapping.LOOKUP_PATH); String path = (String) servletRequest().getAttribute(HandlerMapping.LOOKUP_PATH);
if (path == null) { if (path == null) {
UrlPathHelper helper = new UrlPathHelper(); path = UrlPathHelper.defaultInstance.getLookupPathForRequest(servletRequest());
path = helper.getLookupPathForRequest(servletRequest());
} }
return path; return path;
} }

View File

@ -129,7 +129,7 @@ public final class PatternsRequestCondition extends AbstractRequestCondition<Pat
boolean useTrailingSlashMatch, @Nullable List<String> fileExtensions) { boolean useTrailingSlashMatch, @Nullable List<String> fileExtensions) {
this.patterns = Collections.unmodifiableSet(prependLeadingSlash(patterns)); 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.pathMatcher = pathMatcher != null ? pathMatcher : new AntPathMatcher();
this.useSuffixPatternMatch = useSuffixPatternMatch; this.useSuffixPatternMatch = useSuffixPatternMatch;
this.useTrailingSlashMatch = useTrailingSlashMatch; this.useTrailingSlashMatch = useTrailingSlashMatch;

View File

@ -91,7 +91,7 @@ public abstract class AbstractMessageConverterMethodProcessor extends AbstractMe
new ParameterizedTypeReference<List<ResourceRegion>>() { }.getType(); new ParameterizedTypeReference<List<ResourceRegion>>() { }.getType();
private static final UrlPathHelper decodingUrlPathHelper = new UrlPathHelper(); private static final UrlPathHelper decodingUrlPathHelper = UrlPathHelper.defaultInstance;
private static final UrlPathHelper rawUrlPathHelper = new UrlPathHelper(); private static final UrlPathHelper rawUrlPathHelper = new UrlPathHelper();

View File

@ -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"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with 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 { public class ServletCookieValueMethodArgumentResolver extends AbstractCookieValueMethodArgumentResolver {
private UrlPathHelper urlPathHelper = new UrlPathHelper(); private UrlPathHelper urlPathHelper = UrlPathHelper.defaultInstance;
public ServletCookieValueMethodArgumentResolver(@Nullable ConfigurableBeanFactory beanFactory) { public ServletCookieValueMethodArgumentResolver(@Nullable ConfigurableBeanFactory beanFactory) {

View File

@ -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"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -54,7 +54,7 @@ public class ResourceUrlProvider implements ApplicationListener<ContextRefreshed
protected final Log logger = LogFactory.getLog(getClass()); protected final Log logger = LogFactory.getLog(getClass());
private UrlPathHelper urlPathHelper = new UrlPathHelper(); private UrlPathHelper urlPathHelper = UrlPathHelper.defaultInstance;
private PathMatcher pathMatcher = new AntPathMatcher(); private PathMatcher pathMatcher = new AntPathMatcher();

View File

@ -54,7 +54,7 @@ public abstract class AbstractFlashMapManager implements FlashMapManager {
private int flashMapTimeout = 180; private int flashMapTimeout = 180;
private UrlPathHelper urlPathHelper = new UrlPathHelper(); private UrlPathHelper urlPathHelper = UrlPathHelper.defaultInstance;
/** /**

View File

@ -92,7 +92,7 @@ public class ServletUriComponentsBuilder extends UriComponentsBuilder {
*/ */
public static ServletUriComponentsBuilder fromServletMapping(HttpServletRequest request) { public static ServletUriComponentsBuilder fromServletMapping(HttpServletRequest request) {
ServletUriComponentsBuilder builder = fromContextPath(request); ServletUriComponentsBuilder builder = fromContextPath(request);
if (StringUtils.hasText(new UrlPathHelper().getPathWithinServletMapping(request))) { if (StringUtils.hasText(UrlPathHelper.defaultInstance.getPathWithinServletMapping(request))) {
builder.path(request.getServletPath()); builder.path(request.getServletPath());
} }
return builder; return builder;