Support {/...} patterns in UriComponents(Builder)

This commit introduces support for "Path Segment URI Variable
expansion", see https://tools.ietf.org/html/rfc6570#section-3.2.6.
In practice, this means that URI template variables prefixed with a '/'
are treated like path segments and - as such - will encode any '/'
found. For example: {/foo} expanded with "bar/baz" with result in
"bar%2F".

Issue: SPR-12750
This commit is contained in:
Arjen Poutsma
2015-03-20 12:13:39 +01:00
committed by Rossen Stoyanchev
parent f926f6cb3e
commit 7668ea1549
5 changed files with 233 additions and 10 deletions

View File

@@ -27,6 +27,7 @@ import static org.junit.Assert.assertTrue;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
@@ -238,6 +239,24 @@ public class UriComponentsBuilderTests {
assertEquals("bar@baz", result.getQueryParams().getFirst("foo"));
}
//SPR-12750
@Test
public void fromUriStringWithSlashPrefixedVariable() {
UriComponents result = UriComponentsBuilder.fromUriString(
"http://example.com/part1/{/part2}/{var1}/url/{/urlvar}?foo=bar@baz&bar={barvalue}")
.build();
assertTrue(StringUtils.isEmpty(result.getUserInfo()));
assertEquals("example.com", result.getHost());
assertEquals("/part1/{/part2}/{var1}/url/{/urlvar}", result.getPath());
assertEquals(Arrays.asList("part1", "{/part2}", "{var1}", "url", "{/urlvar}"),
result.getPathSegments());
assertTrue(result.getQueryParams().containsKey("foo"));
assertEquals("bar@baz", result.getQueryParams().getFirst("foo"));
assertTrue(result.getQueryParams().containsKey("bar"));
assertEquals("{barvalue}", result.getQueryParams().getFirst("bar"));
}
@Test
public void fromHttpRequest() throws URISyntaxException {
MockHttpServletRequest request = new MockHttpServletRequest();
@@ -496,7 +515,7 @@ public class UriComponentsBuilderTests {
UriComponents result = builder.build();
assertEquals("/foo/", result.getPath());
assertEquals(Arrays.asList("foo"), result.getPathSegments());
assertEquals(Collections.singletonList("foo"), result.getPathSegments());
}
@Test

View File

@@ -23,6 +23,7 @@ import java.io.ObjectOutputStream;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Arrays;
import java.util.List;
import org.junit.Test;
@@ -165,4 +166,49 @@ public class UriComponentsTests {
assertThat(uriComponents1, not(equalTo(uriComponents3)));
}
@Test
public void partialPath() throws Exception {
List<HierarchicalUriComponents.FullPathComponent.PartialPath> l;
l = HierarchicalUriComponents.FullPathComponent.PartialPath.parse("x");
assertEquals(1, l.size());
assertEquals("x", l.get(0).value);
assertEquals(HierarchicalUriComponents.Type.PATH, l.get(0).type);
l = HierarchicalUriComponents.FullPathComponent.PartialPath.parse("/foo");
assertEquals(1, l.size());
assertEquals("/foo", l.get(0).value);
assertEquals(HierarchicalUriComponents.Type.PATH, l.get(0).type);
l = HierarchicalUriComponents.FullPathComponent.PartialPath.parse("{/foo}");
assertEquals(1, l.size());
assertEquals("{/foo}", l.get(0).value);
assertEquals(HierarchicalUriComponents.Type.PATH_SEGMENT, l.get(0).type);
l = HierarchicalUriComponents.FullPathComponent.PartialPath.parse("/foo{/bar}");
assertEquals(2, l.size());
assertEquals("/foo", l.get(0).value);
assertEquals(HierarchicalUriComponents.Type.PATH, l.get(0).type);
assertEquals("{/bar}", l.get(1).value);
assertEquals(HierarchicalUriComponents.Type.PATH_SEGMENT, l.get(1).type);
l = HierarchicalUriComponents.FullPathComponent.PartialPath.parse("{/foo}{/bar}");
assertEquals(2, l.size());
assertEquals("{/foo}", l.get(0).value);
assertEquals(HierarchicalUriComponents.Type.PATH_SEGMENT, l.get(0).type);
assertEquals("{/bar}", l.get(1).value);
assertEquals(HierarchicalUriComponents.Type.PATH_SEGMENT, l.get(1).type);
l = HierarchicalUriComponents.FullPathComponent.PartialPath.parse("foo{/bar}baz");
assertEquals(3, l.size());
assertEquals("foo", l.get(0).value);
assertEquals(HierarchicalUriComponents.Type.PATH, l.get(0).type);
assertEquals("{/bar}", l.get(1).value);
assertEquals(HierarchicalUriComponents.Type.PATH_SEGMENT, l.get(1).type);
assertEquals("baz", l.get(2).value);
assertEquals(HierarchicalUriComponents.Type.PATH, l.get(2).type);
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2015 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.
@@ -63,6 +63,49 @@ public class UriTemplateTests {
assertEquals("Invalid expanded template", new URI("http://example.com/hotels/1/bookings/42"), result);
}
//SPR-12750
@Test
public void expandSlashPrefixedVariable() throws Exception {
Map<String, String> uriVariables = new HashMap<String, String>(2);
uriVariables.put("hotel", "1");
uriVariables.put("publicpath", "pics/logo.png");
uriVariables.put("scale", "150x150");
UriTemplate template = new UriTemplate(
"http://example.com/hotels/{hotel}/pic/{/publicpath}/size/{scale}");
URI result = template.expand(uriVariables);
assertEquals("Invalid expanded template",
new URI("http://example.com/hotels/1/pic/pics%2Flogo.png/size/150x150"),
result);
}
@Test
public void expandSlashPrefixedVariableInBetween() throws Exception {
Map<String, String> uriVariables = new HashMap<String, String>(2);
uriVariables.put("var1", "foo/bar");
uriVariables.put("var2", "baz");
UriTemplate template = new UriTemplate(
"http://example.com/part1/before-{/var1}-after/{var2}");
URI result = template.expand(uriVariables);
assertEquals("Invalid expanded template",
new URI("http://example.com/part1/before-foo%2Fbar-after/baz"),
result);
}
@Test
public void expandSlashPrefixedVariableAfterNonPrefixedVariable() throws Exception {
Map<String, String> uriVariables = new HashMap<String, String>(2);
uriVariables.put("var1", "foo/bar");
uriVariables.put("var2", "baz");
uriVariables.put("var3", "qux");
UriTemplate template = new UriTemplate(
"http://example.com/part1/before-{/var1}-{var2}-after/{var3}");
URI result = template.expand(uriVariables);
assertEquals("Invalid expanded template",
new URI("http://example.com/part1/before-foo%2Fbar-baz-after/qux"),
result);
}
@Test
public void expandMapDuplicateVariables() throws Exception {
UriTemplate template = new UriTemplate("/order/{c}/{c}/{c}");