From 756bd890ebaf9d0a2c66d838f90d7938750431d6 Mon Sep 17 00:00:00 2001 From: Dmytro Nosan Date: Mon, 18 Mar 2019 16:00:51 +0200 Subject: [PATCH 1/2] Fix request factory used with TestRestTemplate withBasicAuth This commit updates the behavior of withBasicAuth on TestRestTemplate by trying to use the same request factory type as the underlying restTemplate. If creation of a new instance of the configured request factory class fails, it falls back to the `ClientHttpRequestFactorySupplier`. See gh-15982 --- .../test/web/client/TestRestTemplate.java | 24 +++++++++++++++++-- .../web/client/TestRestTemplateTests.java | 16 ++++++++++++- 2 files changed, 37 insertions(+), 3 deletions(-) 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 a3194465e39..3395f510162 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-2018 the original author or authors. + * Copyright 2012-2019 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. @@ -26,6 +26,7 @@ import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; +import java.util.function.Supplier; import org.apache.http.client.HttpClient; import org.apache.http.client.config.CookieSpecs; @@ -38,6 +39,9 @@ import org.apache.http.impl.client.HttpClients; import org.apache.http.protocol.HttpContext; import org.apache.http.ssl.SSLContextBuilder; +import org.springframework.beans.BeanInstantiationException; +import org.springframework.beans.BeanUtils; +import org.springframework.boot.web.client.ClientHttpRequestFactorySupplier; import org.springframework.boot.web.client.RestTemplateBuilder; import org.springframework.boot.web.client.RootUriTemplateHandler; import org.springframework.core.ParameterizedTypeReference; @@ -1023,7 +1027,10 @@ public class TestRestTemplate { /** * Creates a new {@code TestRestTemplate} with the same configuration as this one, * except that it will send basic authorization headers using the given - * {@code username} and {@code password}. + * {@code username} and {@code password}. Note, that a new instance of + * {@link ClientHttpRequestFactory} will be created (if possible) based on the current + * factory class, otherwise {@link ClientHttpRequestFactorySupplier} will be used to + * instantiate a {@link ClientHttpRequestFactory}. * @param username the username * @param password the password * @return the new template @@ -1031,6 +1038,7 @@ public class TestRestTemplate { */ public TestRestTemplate withBasicAuth(String username, String password) { RestTemplate restTemplate = new RestTemplateBuilder() + .requestFactory(getRequestFactorySupplier()) .messageConverters(getRestTemplate().getMessageConverters()) .interceptors(getRestTemplate().getInterceptors()) .uriTemplateHandler(getRestTemplate().getUriTemplateHandler()).build(); @@ -1041,6 +1049,18 @@ public class TestRestTemplate { return testRestTemplate; } + private Supplier getRequestFactorySupplier() { + return () -> { + try { + return BeanUtils + .instantiateClass(getRequestFactoryClass(getRestTemplate())); + } + catch (BeanInstantiationException ex) { + return new ClientHttpRequestFactorySupplier().get(); + } + }; + } + @SuppressWarnings({ "rawtypes", "unchecked" }) private RequestEntity createRequestEntityWithRootAppliedUri( RequestEntity requestEntity) { 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 e83355dd5a0..423dbd8286e 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-2018 the original author or authors. + * Copyright 2012-2019 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. @@ -93,6 +93,20 @@ public class TestRestTemplateTests { .isInstanceOf(OkHttp3ClientHttpRequestFactory.class); } + @Test + public void useTheSameRequestFactoryClassWithBasicAuth() { + OkHttp3ClientHttpRequestFactory customFactory = new OkHttp3ClientHttpRequestFactory(); + RestTemplateBuilder builder = new RestTemplateBuilder() + .requestFactory(OkHttp3ClientHttpRequestFactory::new); + TestRestTemplate testRestTemplate = new TestRestTemplate(builder) + .withBasicAuth("test", "test"); + RestTemplate restTemplate = testRestTemplate.getRestTemplate(); + Object requestFactory = ReflectionTestUtils + .getField(restTemplate.getRequestFactory(), "requestFactory"); + assertThat(requestFactory).isNotEqualTo(customFactory) + .hasSameClassAs(customFactory); + } + @Test public void getRootUriRootUriSetViaRestTemplateBuilder() { String rootUri = "http://example.com"; From 7ea87705246d47ae2286aab2b713849c38324589 Mon Sep 17 00:00:00 2001 From: Madhura Bhave Date: Mon, 18 Mar 2019 17:49:41 -0700 Subject: [PATCH 2/2] Polish "Fix request factory used with withBasicAuth" Fixes gh-15982 --- .../test/web/client/TestRestTemplate.java | 6 ++-- .../web/client/TestRestTemplateTests.java | 31 ++++++++++++++++++- 2 files changed, 32 insertions(+), 5 deletions(-) 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 3395f510162..4c975e2c554 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 @@ -1027,10 +1027,8 @@ public class TestRestTemplate { /** * Creates a new {@code TestRestTemplate} with the same configuration as this one, * except that it will send basic authorization headers using the given - * {@code username} and {@code password}. Note, that a new instance of - * {@link ClientHttpRequestFactory} will be created (if possible) based on the current - * factory class, otherwise {@link ClientHttpRequestFactorySupplier} will be used to - * instantiate a {@link ClientHttpRequestFactory}. + * {@code username} and {@code password}. The request factory used is a new instance + * of the underlying {@link RestTemplate}'s request factory type (when possible). * @param username the username * @param password the password * @return the new template 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 423dbd8286e..ef57a8d2dc2 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 @@ -33,6 +33,7 @@ import org.springframework.http.HttpEntity; import org.springframework.http.HttpMethod; import org.springframework.http.HttpStatus; import org.springframework.http.RequestEntity; +import org.springframework.http.client.ClientHttpRequest; import org.springframework.http.client.ClientHttpRequestFactory; import org.springframework.http.client.ClientHttpRequestInterceptor; import org.springframework.http.client.HttpComponentsClientHttpRequestFactory; @@ -97,7 +98,7 @@ public class TestRestTemplateTests { public void useTheSameRequestFactoryClassWithBasicAuth() { OkHttp3ClientHttpRequestFactory customFactory = new OkHttp3ClientHttpRequestFactory(); RestTemplateBuilder builder = new RestTemplateBuilder() - .requestFactory(OkHttp3ClientHttpRequestFactory::new); + .requestFactory(() -> customFactory); TestRestTemplate testRestTemplate = new TestRestTemplate(builder) .withBasicAuth("test", "test"); RestTemplate restTemplate = testRestTemplate.getRestTemplate(); @@ -107,6 +108,21 @@ public class TestRestTemplateTests { .hasSameClassAs(customFactory); } + @Test + public void withBasicAuthWhenRequestFactoryTypeCannotBeInstantiatedShouldFallback() { + TestClientHttpRequestFactory customFactory = new TestClientHttpRequestFactory( + "my-request-factory"); + RestTemplateBuilder builder = new RestTemplateBuilder() + .requestFactory(() -> customFactory); + TestRestTemplate testRestTemplate = new TestRestTemplate(builder) + .withBasicAuth("test", "test"); + RestTemplate restTemplate = testRestTemplate.getRestTemplate(); + Object requestFactory = ReflectionTestUtils + .getField(restTemplate.getRequestFactory(), "requestFactory"); + assertThat(requestFactory).isNotEqualTo(customFactory) + .isInstanceOf(CustomHttpComponentsClientHttpRequestFactory.class); + } + @Test public void getRootUriRootUriSetViaRestTemplateBuilder() { String rootUri = "http://example.com"; @@ -397,4 +413,17 @@ public class TestRestTemplateTests { } + static class TestClientHttpRequestFactory implements ClientHttpRequestFactory { + + TestClientHttpRequestFactory(String value) { + } + + @Override + public ClientHttpRequest createRequest(URI uri, HttpMethod httpMethod) + throws IOException { + return null; + } + + } + }