diff --git a/org.springframework.web/src/main/java/org/springframework/web/util/UriTemplate.java b/org.springframework.web/src/main/java/org/springframework/web/util/UriTemplate.java index 1e280a993e8..612b09d89bb 100644 --- a/org.springframework.web/src/main/java/org/springframework/web/util/UriTemplate.java +++ b/org.springframework.web/src/main/java/org/springframework/web/util/UriTemplate.java @@ -33,9 +33,9 @@ import org.springframework.util.Assert; * ({, }), which can be expanded to produce a URI. *

* See {@link #expand(Map)}, {@link #expand(String[])}, and {@link #match(String)} for example usages. - * * @author Arjen Poutsma * @see URI Templates + * @since 3.0 */ public final class UriTemplate { @@ -57,7 +57,6 @@ public final class UriTemplate { /** * Constructs a new {@link UriTemplate} with the given string. - * * @param uriTemplate the uri template string */ public UriTemplate(String uriTemplate) { @@ -69,7 +68,6 @@ public final class UriTemplate { /** * Returns the names of the variables in the template, in order. - * * @return the template variable names */ public List getVariableNames() { @@ -89,7 +87,6 @@ public final class UriTemplate { * System.out.println(template.expand(uriVariables)); * * will print:

http://example.com/hotels/1/bookings/42
- * * @param uriVariables the map of uri variables * @return the expanded uri * @throws IllegalArgumentException if uriVariables is null; or if it does not contain @@ -116,7 +113,6 @@ public final class UriTemplate { * System.out.println(template.expand("1", "42)); * * will print:
http://example.com/hotels/1/bookings/42
- * * @param uriVariableValues the array of uri variables * @return the expanded uri * @throws IllegalArgumentException if uriVariables is null; or if it does not contain @@ -137,12 +133,11 @@ public final class UriTemplate { m.appendReplacement(buffer, uriVariable); } m.appendTail(buffer); - return URI.create(buffer.toString()); + return encodeUri(buffer.toString()); } /** * Indicates whether the given URI matches this template. - * * @param uri the URI to match to * @return true if it matches; false otherwise */ @@ -164,7 +159,6 @@ public final class UriTemplate { * System.out.println(template.match("http://example.com/hotels/1/bookings/42")); * * will print:
{hotel=1, booking=42}
- * * @param uri the URI to match to * @return a map of variable values */ @@ -182,6 +176,26 @@ public final class UriTemplate { return result; } + private static URI encodeUri(String uri) { + try { + int idx = uri.indexOf(':'); + URI result; + if (idx != -1) { + String scheme = uri.substring(0, idx); + String ssp = uri.substring(idx + 1); + result = new URI(scheme, ssp, null); + } + else { + result = new URI(null, null, uri, null); + } + return result; + } + catch (URISyntaxException e) { + throw new IllegalArgumentException("Could not create URI from [" + uri + "]"); + } + } + + @Override public String toString() { return uriTemplate; @@ -218,17 +232,11 @@ public final class UriTemplate { if (start == end) { return ""; } - String result = fullPath.substring(start, end); - try { - URI uri = new URI(null, null, result, null); - result = uri.toASCIIString(); - } - catch (URISyntaxException e) { - throw new IllegalArgumentException("Could not create URI from [" + fullPath + "]"); - } + String result = encodeUri(fullPath.substring(start, end)).toASCIIString(); return Pattern.quote(result); } + private List getVariableNames() { return Collections.unmodifiableList(variableNames); } diff --git a/org.springframework.web/src/test/java/org/springframework/web/util/UriTemplateTests.java b/org.springframework.web/src/test/java/org/springframework/web/util/UriTemplateTests.java index a8bae28e419..a1f2b1b0056 100644 --- a/org.springframework.web/src/test/java/org/springframework/web/util/UriTemplateTests.java +++ b/org.springframework.web/src/test/java/org/springframework/web/util/UriTemplateTests.java @@ -86,6 +86,16 @@ public class UriTemplateTests { template.expand(uriVariables); } + @Test + public void expandEncoded() throws Exception { + template = new UriTemplate("http://example.com/hotel list/{hotel}"); + URI result = template.expand(Collections.singletonMap("hotel", "foo bar \u20AC")); + assertEquals("Invalid expanded template", new URI("http", "//example.com/hotel list/foo bar \u20AC", null), + result); + assertEquals("Invalid expanded template", "http://example.com/hotel%20list/foo%20bar%20%E2%82%AC", + result.toASCIIString()); + } + @Test public void matches() throws Exception { assertTrue("UriTemplate does not match", template.matches("http://example.com/hotels/1/bookings/42"));