diff --git a/src/main/java/org/springframework/hateoas/client/Traverson.java b/src/main/java/org/springframework/hateoas/client/Traverson.java index 54249bdf..8f0c6119 100644 --- a/src/main/java/org/springframework/hateoas/client/Traverson.java +++ b/src/main/java/org/springframework/hateoas/client/Traverson.java @@ -59,6 +59,7 @@ import com.jayway.jsonpath.JsonPath; * @author Oliver Gierke * @author Dietrich Schulten * @author Greg Turnquist + * @author Tom Bunting * @since 0.11 */ public class Traverson { @@ -305,7 +306,7 @@ public class Traverson { public T toObject(Class type) { Assert.notNull(type, "Target type must not be null!"); - return operations.exchange(traverseToFinalUrl(true), GET, prepareRequest(headers), type).getBody(); + return operations.exchange(traverseToExpandedFinalUrl(), GET, prepareRequest(headers), type).getBody(); } /** @@ -318,7 +319,7 @@ public class Traverson { public T toObject(ParameterizedTypeReference type) { Assert.notNull(type, "Target type must not be null!"); - return operations.exchange(traverseToFinalUrl(true), GET, prepareRequest(headers), type).getBody(); + return operations.exchange(traverseToExpandedFinalUrl(), GET, prepareRequest(headers), type).getBody(); } /** @@ -332,7 +333,7 @@ public class Traverson { Assert.hasText(jsonPath, "JSON path must not be null or empty!"); - String forObject = operations.exchange(traverseToFinalUrl(true), GET, prepareRequest(headers), String.class) + String forObject = operations.exchange(traverseToExpandedFinalUrl(), GET, prepareRequest(headers), String.class) .getBody(); return JsonPath.read(forObject, jsonPath); } @@ -346,7 +347,7 @@ public class Traverson { public ResponseEntity toEntity(Class type) { Assert.notNull(type, "Target type must not be null!"); - return operations.exchange(traverseToFinalUrl(true), GET, prepareRequest(headers), type); + return operations.exchange(traverseToExpandedFinalUrl(), GET, prepareRequest(headers), type); } /** @@ -374,14 +375,20 @@ public class Traverson { private Link traverseToLink(boolean expandFinalUrl) { Assert.isTrue(rels.size() > 0, "At least one rel needs to be provided!"); - return new Link(traverseToFinalUrl(expandFinalUrl), rels.get(rels.size() - 1).getRel()); + return new Link(expandFinalUrl ? traverseToExpandedFinalUrl().toString() : traverseToFinalUrl(), + rels.get(rels.size() - 1).getRel()); } - private String traverseToFinalUrl(boolean expandFinalUrl) { + private String traverseToFinalUrl() { String uri = getAndFindLinkWithRel(baseUri.toString(), rels.iterator()); - UriTemplate uriTemplate = new UriTemplate(uri); - return expandFinalUrl ? uriTemplate.expand(templateParameters).toString() : uriTemplate.toString(); + return new UriTemplate(uri).toString(); + } + + private URI traverseToExpandedFinalUrl() { + + String uri = getAndFindLinkWithRel(baseUri.toString(), rels.iterator()); + return new UriTemplate(uri).expand(templateParameters); } private String getAndFindLinkWithRel(String uri, Iterator rels) { diff --git a/src/test/java/org/springframework/hateoas/client/Server.java b/src/test/java/org/springframework/hateoas/client/Server.java index 580b0eae..4a17fc48 100644 --- a/src/test/java/org/springframework/hateoas/client/Server.java +++ b/src/test/java/org/springframework/hateoas/client/Server.java @@ -147,6 +147,16 @@ public class Server implements Closeable { respond(). // withBody(springagramItemWithoutImageHalDocument). // withContentType(MediaTypes.HAL_JSON.toString()); + + // For Traverson URI double encoding test + + onRequest(). // + havingPathEqualTo("/springagram/items"). // + havingQueryString(equalTo("projection=no%20images")). // + respond(). // + withBody(springagramItemsHalDocument). // + withContentType(MediaTypes.HAL_JSON.toString()); + } public String rootResource() { diff --git a/src/test/java/org/springframework/hateoas/client/TraversonTest.java b/src/test/java/org/springframework/hateoas/client/TraversonTest.java index 5e9b1c9b..0f307572 100644 --- a/src/test/java/org/springframework/hateoas/client/TraversonTest.java +++ b/src/test/java/org/springframework/hateoas/client/TraversonTest.java @@ -355,6 +355,23 @@ public class TraversonTest { assertThat(item.image, equalTo(server.rootResource() + "/springagram/file/cat")); assertThat(item.description, equalTo("cat")); } + + /** + * @see #337 + */ + @Test + public void doesNotDoubleEncodeURI() { + + this.traverson = new Traverson(URI.create(server.rootResource() + "/springagram"), MediaTypes.HAL_JSON); + + Resource itemResource = traverson.// + follow(rel("items").withParameters(Collections.singletonMap("projection", "no images"))).// + toObject(Resource.class); + + assertThat(itemResource.hasLink("self"), is(true)); + assertThat(itemResource.getLink("self").expand().getHref(), + equalTo(server.rootResource() + "/springagram/items")); + } private void setUpActors() {