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 dbfff83176..d68dd93c28 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 @@ -17,7 +17,6 @@ package org.springframework.web.util; import java.net.URI; -import java.nio.charset.Charset; import java.util.Collections; import java.util.HashMap; import java.util.Map; @@ -49,16 +48,33 @@ public class DefaultUriBuilderFactory implements UriBuilderFactory { public enum EncodingMode { /** - * Apply strict encoding to URI variables at the time of expanding, - * quoting both illegal characters and characters with reserved meaning - * via {@link UriUtils#encode(String, Charset)}. + * Encode the URI template first, and URI variables later when expanded, + * applying the following to each: + *
For most cases this should be the preferred encoding mode. + * @since 5.0.8 + * @see UriComponentsBuilder#encode() + */ + TEMPLATE_AND_VALUES, + + /** + * Encode only URI variables strictly quoting both illegal characters + * and characters with reserved meaning. + * @see UriUtils#encodeUriVariables(Object...) + * @see UriUtils#encodeUriVariables(Map) */ VALUES_ONLY, /** - * Expand URI variables first, then encode the resulting URI component + * 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. + * @see UriComponents#encode() */ URI_COMPONENT, @@ -110,7 +126,7 @@ public class DefaultUriBuilderFactory implements UriBuilderFactory { /** - * Specify the {@link EncodingMode EncodingMode} to use when building URIs. + * Specify the {@link EncodingMode EncodingMode} to use to encode URIs. *
By default set to
* {@link EncodingMode#URI_COMPONENT EncodingMode.URI_COMPONENT}.
* @param encodingMode the encoding mode to use
@@ -216,13 +232,17 @@ public class DefaultUriBuilderFactory implements UriBuilderFactory {
result = UriComponentsBuilder.fromUriString(uriTemplate);
}
+ if (encodingMode.equals(EncodingMode.TEMPLATE_AND_VALUES)) {
+ result.encode();
+ }
+
parsePathIfNecessary(result);
return result;
}
private void parsePathIfNecessary(UriComponentsBuilder result) {
- if (shouldParsePath() && encodingMode.equals(EncodingMode.URI_COMPONENT)) {
+ if (parsePath && encodingMode.equals(EncodingMode.URI_COMPONENT)) {
UriComponents uric = result.build();
String path = uric.getPath();
result.replacePath(null);
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 af2fbae915..1f42b32f34 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
@@ -97,6 +97,22 @@ public class DefaultUriBuilderFactoryTests {
assertEquals("https://api.example.com:443/v42/customers/123", uri.toString());
}
+ @Test
+ public void encodeTemplateAndValues() {
+ DefaultUriBuilderFactory factory = new DefaultUriBuilderFactory();
+ factory.setEncodingMode(EncodingMode.TEMPLATE_AND_VALUES);
+ UriBuilder uriBuilder = factory.uriString("/hotel list/{city} specials?q={value}");
+
+ String expected = "/hotel%20list/Z%C3%BCrich%20specials?q=a%2Bb";
+
+ Map