From 2f50d515a1de8b5e3621eb003ef2acae1832a5b3 Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Thu, 2 Feb 2017 13:28:52 +0000 Subject: [PATCH] Apply root to URIs directly rather than relying on expansion Previously, TestRestTemplate applied the root URI to URIs by converting them to a String and then passing the String to the RestTemplate delegate. Being a String, meant that the URI passed through RestTemplate's standard URI template expansion processing using the configured UriTemplateHandler. While this caused the root URI to be applied, it also had the unwanted side-effect of encoding the URI for a second time. This commit updates TestRestTemplate so that, when configured with a RootUriTemplateHandler, it applies the root URI directly and then passes a modified URI to the RestTemplate delegate. Being a URI means that no template expansion is performed and the possible double encoding is avoided. Closes gh-8163 --- .../test/web/client/TestRestTemplate.java | 57 ++++++++++++------- .../web/client/TestRestTemplateTests.java | 14 ++--- 2 files changed, 42 insertions(+), 29 deletions(-) diff --git a/spring-boot-test/src/main/java/org/springframework/boot/test/web/client/TestRestTemplate.java b/spring-boot-test/src/main/java/org/springframework/boot/test/web/client/TestRestTemplate.java index 85bfe8e3146..f205f4414f3 100644 --- a/spring-boot-test/src/main/java/org/springframework/boot/test/web/client/TestRestTemplate.java +++ b/spring-boot-test/src/main/java/org/springframework/boot/test/web/client/TestRestTemplate.java @@ -39,6 +39,7 @@ import org.apache.http.protocol.HttpContext; import org.apache.http.ssl.SSLContextBuilder; import org.springframework.boot.web.client.RestTemplateBuilder; +import org.springframework.boot.web.client.RootUriTemplateHandler; import org.springframework.core.ParameterizedTypeReference; import org.springframework.http.HttpEntity; import org.springframework.http.HttpHeaders; @@ -217,7 +218,7 @@ public class TestRestTemplate { * @see RestTemplate#getForObject(java.net.URI, java.lang.Class) */ public T getForObject(URI url, Class responseType) throws RestClientException { - return this.restTemplate.getForObject(url.toString(), responseType); + return this.restTemplate.getForObject(applyRootUriIfNecessary(url), responseType); } /** @@ -269,7 +270,7 @@ public class TestRestTemplate { */ public ResponseEntity getForEntity(URI url, Class responseType) throws RestClientException { - return this.restTemplate.getForEntity(url.toString(), responseType); + return this.restTemplate.getForEntity(applyRootUriIfNecessary(url), responseType); } /** @@ -310,7 +311,7 @@ public class TestRestTemplate { * @see RestTemplate#headForHeaders(java.net.URI) */ public HttpHeaders headForHeaders(URI url) throws RestClientException { - return this.restTemplate.headForHeaders(url.toString()); + return this.restTemplate.headForHeaders(applyRootUriIfNecessary(url)); } /** @@ -374,7 +375,7 @@ public class TestRestTemplate { * @see RestTemplate#postForLocation(java.net.URI, java.lang.Object) */ public URI postForLocation(URI url, Object request) throws RestClientException { - return this.restTemplate.postForLocation(url.toString(), request); + return this.restTemplate.postForLocation(applyRootUriIfNecessary(url), request); } /** @@ -442,7 +443,8 @@ public class TestRestTemplate { */ public T postForObject(URI url, Object request, Class responseType) throws RestClientException { - return this.restTemplate.postForObject(url.toString(), request, responseType); + return this.restTemplate.postForObject(applyRootUriIfNecessary(url), request, + responseType); } /** @@ -511,7 +513,8 @@ public class TestRestTemplate { */ public ResponseEntity postForEntity(URI url, Object request, Class responseType) throws RestClientException { - return this.restTemplate.postForEntity(url.toString(), request, responseType); + return this.restTemplate.postForEntity(applyRootUriIfNecessary(url), request, + responseType); } /** @@ -564,7 +567,7 @@ public class TestRestTemplate { * @see RestTemplate#put(java.net.URI, java.lang.Object) */ public void put(URI url, Object request) throws RestClientException { - this.restTemplate.put(url.toString(), request); + this.restTemplate.put(applyRootUriIfNecessary(url), request); } /** @@ -630,7 +633,8 @@ public class TestRestTemplate { */ public T patchForObject(URI url, Object request, Class responseType) throws RestClientException { - return this.restTemplate.patchForObject(url.toString(), request, responseType); + return this.restTemplate.patchForObject(applyRootUriIfNecessary(url), request, + responseType); } @@ -668,7 +672,7 @@ public class TestRestTemplate { * @see RestTemplate#delete(java.net.URI) */ public void delete(URI url) throws RestClientException { - this.restTemplate.delete(url.toString()); + this.restTemplate.delete(applyRootUriIfNecessary(url)); } /** @@ -709,7 +713,7 @@ public class TestRestTemplate { * @see RestTemplate#optionsForAllow(java.net.URI) */ public Set optionsForAllow(URI url) throws RestClientException { - return this.restTemplate.optionsForAllow(url.toString()); + return this.restTemplate.optionsForAllow(applyRootUriIfNecessary(url)); } /** @@ -777,8 +781,8 @@ public class TestRestTemplate { public ResponseEntity exchange(URI url, HttpMethod method, HttpEntity requestEntity, Class responseType) throws RestClientException { - return this.restTemplate.exchange(url.toString(), method, requestEntity, - responseType); + return this.restTemplate.exchange(applyRootUriIfNecessary(url), method, + requestEntity, responseType); } /** @@ -860,8 +864,8 @@ public class TestRestTemplate { public ResponseEntity exchange(URI url, HttpMethod method, HttpEntity requestEntity, ParameterizedTypeReference responseType) throws RestClientException { - return this.restTemplate.exchange(url.toString(), method, requestEntity, - responseType); + return this.restTemplate.exchange(applyRootUriIfNecessary(url), method, + requestEntity, responseType); } /** @@ -882,7 +886,7 @@ public class TestRestTemplate { public ResponseEntity exchange(RequestEntity requestEntity, Class responseType) throws RestClientException { return this.restTemplate.exchange( - createRequestEntityWithExpandedUri(requestEntity), responseType); + createRequestEntityWithRootAppliedUri(requestEntity), responseType); } /** @@ -905,7 +909,7 @@ public class TestRestTemplate { public ResponseEntity exchange(RequestEntity requestEntity, ParameterizedTypeReference responseType) throws RestClientException { return this.restTemplate.exchange( - createRequestEntityWithExpandedUri(requestEntity), responseType); + createRequestEntityWithRootAppliedUri(requestEntity), responseType); } /** @@ -972,8 +976,8 @@ public class TestRestTemplate { */ public T execute(URI url, HttpMethod method, RequestCallback requestCallback, ResponseExtractor responseExtractor) throws RestClientException { - return this.restTemplate.execute(url.toString(), method, requestCallback, - responseExtractor); + return this.restTemplate.execute(applyRootUriIfNecessary(url), method, + requestCallback, responseExtractor); } /** @@ -1008,12 +1012,21 @@ public class TestRestTemplate { } @SuppressWarnings({ "rawtypes", "unchecked" }) - private RequestEntity createRequestEntityWithExpandedUri( + private RequestEntity createRequestEntityWithRootAppliedUri( RequestEntity requestEntity) { - URI expandedUri = this.restTemplate.getUriTemplateHandler() - .expand(requestEntity.getUrl().toString()); return new RequestEntity(requestEntity.getBody(), requestEntity.getHeaders(), - requestEntity.getMethod(), expandedUri, requestEntity.getType()); + requestEntity.getMethod(), + applyRootUriIfNecessary(requestEntity.getUrl()), requestEntity.getType()); + } + + private URI applyRootUriIfNecessary(URI uri) { + UriTemplateHandler uriTemplateHandler = this.restTemplate.getUriTemplateHandler(); + if ((uriTemplateHandler instanceof RootUriTemplateHandler) + && uri.toString().startsWith("/")) { + return URI.create(((RootUriTemplateHandler) uriTemplateHandler).getRootUri() + + uri.toString()); + } + return uri; } /** diff --git a/spring-boot-test/src/test/java/org/springframework/boot/test/web/client/TestRestTemplateTests.java b/spring-boot-test/src/test/java/org/springframework/boot/test/web/client/TestRestTemplateTests.java index a0ca1c99551..f586107341f 100644 --- a/spring-boot-test/src/test/java/org/springframework/boot/test/web/client/TestRestTemplateTests.java +++ b/spring-boot-test/src/test/java/org/springframework/boot/test/web/client/TestRestTemplateTests.java @@ -38,6 +38,7 @@ import org.springframework.http.client.ClientHttpRequestInterceptor; import org.springframework.http.client.HttpComponentsClientHttpRequestFactory; import org.springframework.http.client.InterceptingClientHttpRequestFactory; import org.springframework.http.client.support.BasicAuthorizationInterceptor; +import org.springframework.mock.env.MockEnvironment; import org.springframework.mock.http.client.MockClientHttpRequest; import org.springframework.mock.http.client.MockClientHttpResponse; import org.springframework.test.util.ReflectionTestUtils; @@ -47,7 +48,6 @@ import org.springframework.web.client.ResponseErrorHandler; import org.springframework.web.client.RestOperations; import org.springframework.web.client.RestTemplate; import org.springframework.web.util.DefaultUriTemplateHandler; -import org.springframework.web.util.UriTemplateHandler; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.BDDMockito.given; @@ -427,18 +427,18 @@ public class TestRestTemplateTests { ClientHttpRequestFactory requestFactory = mock(ClientHttpRequestFactory.class); MockClientHttpRequest request = new MockClientHttpRequest(); request.setResponse(new MockClientHttpResponse(new byte[0], HttpStatus.OK)); - URI relativeUri = URI.create("a/b/c.txt"); - URI absoluteUri = URI.create("http://localhost:8080/" + relativeUri.toString()); + URI absoluteUri = URI + .create("http://localhost:8080/a/b/c.txt?param=%7Bsomething%7D"); given(requestFactory.createRequest(eq(absoluteUri), (HttpMethod) any())) .willReturn(request); RestTemplate delegate = new RestTemplate(); TestRestTemplate template = new TestRestTemplate(delegate); delegate.setRequestFactory(requestFactory); - UriTemplateHandler uriTemplateHandler = mock(UriTemplateHandler.class); - given(uriTemplateHandler.expand(relativeUri.toString(), new Object[0])) - .willReturn(absoluteUri); + LocalHostUriTemplateHandler uriTemplateHandler = new LocalHostUriTemplateHandler( + new MockEnvironment()); template.setUriTemplateHandler(uriTemplateHandler); - callback.doWithTestRestTemplate(template, relativeUri); + callback.doWithTestRestTemplate(template, + URI.create("/a/b/c.txt?param=%7Bsomething%7D")); verify(requestFactory).createRequest(eq(absoluteUri), (HttpMethod) any()); }