diff --git a/spring-web/src/main/java/org/springframework/web/client/RestTemplate.java b/spring-web/src/main/java/org/springframework/web/client/RestTemplate.java index df603e1857..3760750e79 100644 --- a/spring-web/src/main/java/org/springframework/web/client/RestTemplate.java +++ b/spring-web/src/main/java/org/springframework/web/client/RestTemplate.java @@ -60,6 +60,7 @@ import org.springframework.lang.Nullable; import org.springframework.util.Assert; import org.springframework.util.ClassUtils; import org.springframework.web.util.DefaultUriBuilderFactory; +import org.springframework.web.util.DefaultUriBuilderFactory.EncodingMode; import org.springframework.web.util.UriTemplateHandler; /** @@ -165,7 +166,7 @@ public class RestTemplate extends InterceptingHttpAccessor implements RestOperat private ResponseErrorHandler errorHandler = new DefaultResponseErrorHandler(); - private UriTemplateHandler uriTemplateHandler = new DefaultUriBuilderFactory(); + private UriTemplateHandler uriTemplateHandler; private final ResponseExtractor headersExtractor = new HeadersExtractor(); @@ -209,6 +210,8 @@ public class RestTemplate extends InterceptingHttpAccessor implements RestOperat if (jackson2CborPresent) { this.messageConverters.add(new MappingJackson2CborHttpMessageConverter()); } + + this.uriTemplateHandler = initUriTemplateHandler(); } /** @@ -231,6 +234,13 @@ public class RestTemplate extends InterceptingHttpAccessor implements RestOperat public RestTemplate(List> messageConverters) { Assert.notEmpty(messageConverters, "At least one HttpMessageConverter required"); this.messageConverters.addAll(messageConverters); + this.uriTemplateHandler = initUriTemplateHandler(); + } + + private static DefaultUriBuilderFactory initUriTemplateHandler() { + DefaultUriBuilderFactory uriFactory = new DefaultUriBuilderFactory(); + uriFactory.setEncodingMode(EncodingMode.URI_COMPONENT); // for backwards compatibility.. + return uriFactory; } @@ -299,16 +309,18 @@ public class RestTemplate extends InterceptingHttpAccessor implements RestOperat } /** - * Customize how URI templates are expanded into URI instances. - *

By default {@link DefaultUriBuilderFactory} with default settings is - * used. You can supply a {@code DefaultUriBuilderFactory} configured - * differently, or an entirely different implementation, for example that - * plugs in a 3rd party URI template library. + * Configure a strategy for expanding URI templates. + *

By default, {@link DefaultUriBuilderFactory} is used and for + * backwards compatibility, the encoding mode is set to + * {@link EncodingMode#URI_COMPONENT URI_COMPONENT}. As of 5.0.8, prefer + * using {@link EncodingMode#TEMPLATE_AND_VALUES TEMPLATE_AND_VALUES}. + * *

Note: in 5.0 the switch from * {@link org.springframework.web.util.DefaultUriTemplateHandler * DefaultUriTemplateHandler} (deprecated in 4.3), as the default to use, to * {@link DefaultUriBuilderFactory} brings in a different default for the * {@code parsePath} property (switching from false to true). + * * @param handler the URI template handler to use */ public void setUriTemplateHandler(UriTemplateHandler handler) { diff --git a/spring-web/src/main/java/org/springframework/web/util/DefaultUriBuilderFactory.java b/spring-web/src/main/java/org/springframework/web/util/DefaultUriBuilderFactory.java index d68dd93c28..d0cb1be195 100644 --- a/spring-web/src/main/java/org/springframework/web/util/DefaultUriBuilderFactory.java +++ b/spring-web/src/main/java/org/springframework/web/util/DefaultUriBuilderFactory.java @@ -74,6 +74,9 @@ public class DefaultUriBuilderFactory implements UriBuilderFactory { * Expand URI variables first, and then encode the expanded URI component * values, quoting only illegal characters within a given URI * component type, but not all characters with reserved meaning. + *

This is the mode historically used in the {@code RestTemplate} but + * as of 5.0.8 {@link #TEMPLATE_AND_VALUES} is the recommended encoding + * mode to use instead. * @see UriComponents#encode() */ URI_COMPONENT, @@ -88,7 +91,7 @@ public class DefaultUriBuilderFactory implements UriBuilderFactory { @Nullable private final UriComponentsBuilder baseUri; - private EncodingMode encodingMode = EncodingMode.URI_COMPONENT; + private EncodingMode encodingMode = EncodingMode.TEMPLATE_AND_VALUES; private final Map defaultUriVariables = new HashMap<>(); @@ -127,8 +130,12 @@ public class DefaultUriBuilderFactory implements UriBuilderFactory { /** * Specify the {@link EncodingMode EncodingMode} to use to encode URIs. - *

By default set to - * {@link EncodingMode#URI_COMPONENT EncodingMode.URI_COMPONENT}. + * + *

Note: in 5.1 the default value was changed from + * {@link EncodingMode#URI_COMPONENT URI_COMPONENT} to the now recommended + * {@link EncodingMode#TEMPLATE_AND_VALUES TEMPLATE_AND_VALUES} mode of + * encoding. + * * @param encodingMode the encoding mode to use */ public void setEncodingMode(EncodingMode encodingMode) { diff --git a/spring-web/src/test/java/org/springframework/web/util/DefaultUriBuilderFactoryTests.java b/spring-web/src/test/java/org/springframework/web/util/DefaultUriBuilderFactoryTests.java index 1f42b32f34..9e961d1967 100644 --- a/spring-web/src/test/java/org/springframework/web/util/DefaultUriBuilderFactoryTests.java +++ b/spring-web/src/test/java/org/springframework/web/util/DefaultUriBuilderFactoryTests.java @@ -160,6 +160,7 @@ public class DefaultUriBuilderFactoryTests { @Test public void parsePathIsTurnedOff() { DefaultUriBuilderFactory factory = new DefaultUriBuilderFactory("/foo/{bar}"); + factory.setEncodingMode(EncodingMode.URI_COMPONENT); factory.setParsePath(false); URI uri = factory.uriString("/baz/{id}").build("a/b", "c/d"); assertEquals("/foo/a/b/baz/c/d", uri.toString());