diff --git a/spring-boot-project/spring-boot-test/src/main/java/org/springframework/boot/test/web/client/TestRestTemplate.java b/spring-boot-project/spring-boot-test/src/main/java/org/springframework/boot/test/web/client/TestRestTemplate.java index 435e22a46a94..18ba59787bce 100644 --- a/spring-boot-project/spring-boot-test/src/main/java/org/springframework/boot/test/web/client/TestRestTemplate.java +++ b/spring-boot-project/spring-boot-test/src/main/java/org/springframework/boot/test/web/client/TestRestTemplate.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2020 the original author or authors. + * Copyright 2012-2021 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. @@ -41,6 +41,7 @@ import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; import org.springframework.http.RequestEntity; +import org.springframework.http.RequestEntity.UriTemplateRequestEntity; import org.springframework.http.ResponseEntity; import org.springframework.http.client.ClientHttpRequestFactory; import org.springframework.http.client.ClientHttpResponse; @@ -965,7 +966,7 @@ public TestRestTemplate withBasicAuth(String username, String password) { @SuppressWarnings({ "rawtypes", "unchecked" }) private RequestEntity createRequestEntityWithRootAppliedUri(RequestEntity requestEntity) { return new RequestEntity(requestEntity.getBody(), requestEntity.getHeaders(), requestEntity.getMethod(), - applyRootUriIfNecessary(requestEntity.getUrl()), requestEntity.getType()); + applyRootUriIfNecessary(resolveUri(requestEntity)), requestEntity.getType()); } private URI applyRootUriIfNecessary(URI uri) { @@ -976,6 +977,23 @@ private URI applyRootUriIfNecessary(URI uri) { return uri; } + private URI resolveUri(RequestEntity entity) { + if (entity instanceof UriTemplateRequestEntity) { + UriTemplateRequestEntity templatedUriEntity = (UriTemplateRequestEntity) entity; + if (templatedUriEntity.getVars() != null) { + return this.restTemplate.getUriTemplateHandler().expand(templatedUriEntity.getUriTemplate(), + templatedUriEntity.getVars()); + } + else if (templatedUriEntity.getVarsMap() != null) { + return this.restTemplate.getUriTemplateHandler().expand(templatedUriEntity.getUriTemplate(), + templatedUriEntity.getVarsMap()); + } + throw new IllegalStateException( + "No variables specified for URI template: " + templatedUriEntity.getUriTemplate()); + } + return entity.getUrl(); + } + /** * Options used to customize the Apache HTTP Client. */ diff --git a/spring-boot-project/spring-boot-test/src/test/java/org/springframework/boot/test/web/client/TestRestTemplateTests.java b/spring-boot-project/spring-boot-test/src/test/java/org/springframework/boot/test/web/client/TestRestTemplateTests.java index 341e9fef59ba..fe945952548e 100644 --- a/spring-boot-project/spring-boot-test/src/test/java/org/springframework/boot/test/web/client/TestRestTemplateTests.java +++ b/spring-boot-project/spring-boot-test/src/test/java/org/springframework/boot/test/web/client/TestRestTemplateTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2019 the original author or authors. + * Copyright 2012-2021 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. @@ -233,6 +233,36 @@ void withBasicAuthShouldUseNoOpErrorHandler() throws Exception { Class.forName("org.springframework.boot.test.web.client.TestRestTemplate$NoOpResponseErrorHandler")); } + @Test + void exchangeWithRelativeTemplatedUrlRequestEntity() throws Exception { + RequestEntity entity = RequestEntity.get("/a/b/c.{ext}", "txt").build(); + TestRestTemplate template = new TestRestTemplate(); + ClientHttpRequestFactory requestFactory = mock(ClientHttpRequestFactory.class); + MockClientHttpRequest request = new MockClientHttpRequest(); + request.setResponse(new MockClientHttpResponse(new byte[0], HttpStatus.OK)); + URI absoluteUri = URI.create("http://localhost:8080/a/b/c.txt"); + given(requestFactory.createRequest(eq(absoluteUri), eq(HttpMethod.GET))).willReturn(request); + template.getRestTemplate().setRequestFactory(requestFactory); + LocalHostUriTemplateHandler uriTemplateHandler = new LocalHostUriTemplateHandler(new MockEnvironment()); + template.setUriTemplateHandler(uriTemplateHandler); + template.exchange(entity, String.class); + verify(requestFactory).createRequest(eq(absoluteUri), eq(HttpMethod.GET)); + } + + @Test + void exchangeWithAbsoluteTemplatedUrlRequestEntity() throws Exception { + RequestEntity entity = RequestEntity.get("https://api.example.com/a/b/c.{ext}", "txt").build(); + TestRestTemplate template = new TestRestTemplate(); + ClientHttpRequestFactory requestFactory = mock(ClientHttpRequestFactory.class); + MockClientHttpRequest request = new MockClientHttpRequest(); + request.setResponse(new MockClientHttpResponse(new byte[0], HttpStatus.OK)); + URI absoluteUri = URI.create("https://api.example.com/a/b/c.txt"); + given(requestFactory.createRequest(eq(absoluteUri), eq(HttpMethod.GET))).willReturn(request); + template.getRestTemplate().setRequestFactory(requestFactory); + template.exchange(entity, String.class); + verify(requestFactory).createRequest(eq(absoluteUri), eq(HttpMethod.GET)); + } + @Test void deleteHandlesRelativeUris() throws IOException { verifyRelativeUriHandling(TestRestTemplate::delete);