Browse Source

Simplify BaseUrl code and cache resolved URLs

See gh-47680
pull/47694/head
Phillip Webb 2 months ago
parent
commit
77f207a079
  1. 10
      core/spring-boot-test/src/main/java/org/springframework/boot/test/http/client/BaseUrlUriBuilderFactory.java
  2. 69
      core/spring-boot-test/src/main/java/org/springframework/boot/test/http/server/BaseUrl.java
  3. 9
      core/spring-boot-test/src/main/java/org/springframework/boot/test/http/server/BaseUrlProviders.java
  4. 5
      core/spring-boot-test/src/test/java/org/springframework/boot/test/http/server/BaseUrlProvidersTests.java
  5. 4
      core/spring-boot-test/src/test/java/org/springframework/boot/test/http/server/BaseUrlTests.java
  6. 7
      module/spring-boot-graphql-test/src/main/java/org/springframework/boot/graphql/test/autoconfigure/tester/HttpGraphQlTesterAutoConfiguration.java
  7. 5
      module/spring-boot-resttestclient/src/main/java/org/springframework/boot/resttestclient/autoconfigure/TestRestTemplateAutoConfiguration.java
  8. 2
      module/spring-boot-webmvc-test/src/main/java/org/springframework/boot/webmvc/test/autoconfigure/MockMvcWebClientAutoConfiguration.java
  9. 2
      module/spring-boot-webmvc-test/src/main/java/org/springframework/boot/webmvc/test/autoconfigure/MockMvcWebDriverAutoConfiguration.java
  10. 2
      smoke-test/spring-boot-smoke-test-actuator-custom-security/src/test/java/smoketest/actuator/customsecurity/AbstractSampleActuatorCustomSecurityTests.java
  11. 2
      smoke-test/spring-boot-smoke-test-actuator-custom-security/src/test/java/smoketest/actuator/customsecurity/CorsSampleActuatorApplicationTests.java
  12. 2
      smoke-test/spring-boot-smoke-test-actuator-extension/src/test/java/smoketest/actuator/extension/SampleActuatorExtensionApplicationTests.java
  13. 2
      smoke-test/spring-boot-smoke-test-actuator/src/test/java/smoketest/actuator/CorsSampleActuatorApplicationTests.java

10
core/spring-boot-test/src/main/java/org/springframework/boot/test/http/client/BaseUrlUriBuilderFactory.java

@ -59,7 +59,7 @@ public final class BaseUrlUriBuilderFactory implements UriBuilderFactory {
@Override @Override
public UriBuilder uriString(String uriTemplate) { public UriBuilder uriString(String uriTemplate) {
return createDelegate().uriString(uriTemplate); return this.baseUrl.getUriBuilderFactory().uriString(uriTemplate);
} }
@Override @Override
@ -69,16 +69,12 @@ public final class BaseUrlUriBuilderFactory implements UriBuilderFactory {
@Override @Override
public URI expand(String uriTemplate, Map<String, ?> uriVariables) { public URI expand(String uriTemplate, Map<String, ?> uriVariables) {
return createDelegate().expand(uriTemplate, uriVariables); return this.baseUrl.getUriBuilderFactory().expand(uriTemplate, uriVariables);
} }
@Override @Override
public URI expand(String uriTemplate, @Nullable Object... uriVariables) { public URI expand(String uriTemplate, @Nullable Object... uriVariables) {
return createDelegate().expand(uriTemplate, uriVariables); return this.baseUrl.getUriBuilderFactory().expand(uriTemplate, uriVariables);
}
private UriBuilderFactory createDelegate() {
return this.baseUrl.getUriBuilderFactory();
} }
} }

69
core/spring-boot-test/src/main/java/org/springframework/boot/test/http/server/BaseUrl.java

@ -20,6 +20,7 @@ import java.util.function.Supplier;
import org.springframework.util.Assert; import org.springframework.util.Assert;
import org.springframework.util.StringUtils; import org.springframework.util.StringUtils;
import org.springframework.util.function.SingletonSupplier;
import org.springframework.web.util.DefaultUriBuilderFactory; import org.springframework.web.util.DefaultUriBuilderFactory;
import org.springframework.web.util.UriBuilderFactory; import org.springframework.web.util.UriBuilderFactory;
@ -30,38 +31,53 @@ import org.springframework.web.util.UriBuilderFactory;
* @author Stephane Nicoll * @author Stephane Nicoll
* @since 4.0.0 * @since 4.0.0
*/ */
public interface BaseUrl { public final class BaseUrl {
/** /**
* Default base URL suitable for mock environments. * {@link BaseUrl} that resolves to {@code http://localhost}.
*/ */
BaseUrl DEFAULT = BaseUrl.of("http://localhost"); public static final BaseUrl LOCALHOST = BaseUrl.of("http://localhost");
private final boolean https;
private final Supplier<String> resolver;
private BaseUrl(boolean https, Supplier<String> resolver) {
this.https = https;
this.resolver = SingletonSupplier.of(resolver);
}
/** /**
* Return if the URL will ultimately resolve to an HTTPS address. * Return if the URL will ultimately resolve to an HTTPS address.
* @return if the URL is HTTPS * @return if the URL is HTTPS
*/ */
boolean isHttps(); public boolean isHttps() {
return this.https;
}
/** /**
* Get a {@link UriBuilderFactory} that applies the base URL. * Get a {@link UriBuilderFactory} that applies the base URL.
* @return a {@link UriBuilderFactory} * @return a {@link UriBuilderFactory}
*/ */
UriBuilderFactory getUriBuilderFactory(); public UriBuilderFactory getUriBuilderFactory() {
return new DefaultUriBuilderFactory(this.resolver.get());
}
/** /**
* Return a new instance that applies the given {@code path}. * Return a new instance that applies the given {@code path}.
* @param path a path to append * @param path a path to append
* @return a new instance with the path added * @return a new instance with the path added
*/ */
BaseUrl withPath(String path); public BaseUrl withPath(String path) {
return new BaseUrl(this.https, () -> this.resolver.get() + path);
}
/** /**
* Factory method to create a new {@link BaseUrl}. * Factory method to create a new {@link BaseUrl}.
* @param url the URL to use * @param url the URL to use
* @return a new {@link BaseUrl} instance * @return a new {@link BaseUrl} instance
*/ */
static BaseUrl of(String url) { public static BaseUrl of(String url) {
Assert.notNull(url, "'url' must not be null"); Assert.notNull(url, "'url' must not be null");
return of(StringUtils.startsWithIgnoreCase(url, "https"), () -> url); return of(StringUtils.startsWithIgnoreCase(url, "https"), () -> url);
} }
@ -72,42 +88,9 @@ public interface BaseUrl {
* @param resolver the resolver used to supply the actual URL * @param resolver the resolver used to supply the actual URL
* @return a new {@link BaseUrl} instance * @return a new {@link BaseUrl} instance
*/ */
static BaseUrl of(boolean https, Supplier<String> resolver) { public static BaseUrl of(boolean https, Supplier<String> resolver) {
return new DefaultBaseUrl(https, resolver); Assert.notNull(resolver, "'resolver' must not be null");
} return new BaseUrl(https, resolver);
final class DefaultBaseUrl implements BaseUrl {
private final boolean https;
private final Supplier<String> resolver;
private DefaultBaseUrl(boolean https, Supplier<String> resolver) {
Assert.notNull(resolver, "'resolver' must not be null");
this.https = https;
this.resolver = resolver;
}
@Override
public boolean isHttps() {
return this.https;
}
@Override
public UriBuilderFactory getUriBuilderFactory() {
return new DefaultUriBuilderFactory(resolve());
}
String resolve() {
return this.resolver.get();
}
@Override
public BaseUrl withPath(String path) {
Supplier<String> updatedResolver = () -> this.resolver.get() + path;
return new DefaultBaseUrl(this.https, updatedResolver);
}
} }
} }

9
core/spring-boot-test/src/main/java/org/springframework/boot/test/http/server/BaseUrlProviders.java

@ -47,14 +47,6 @@ public class BaseUrlProviders {
this.providers = providers; this.providers = providers;
} }
/**
* Return the provided {@link BaseUrl} or {@link BaseUrl#DEFAULT}.
* @return the base URL
*/
public BaseUrl getBaseUrlOrDefault() {
return getBaseUrl(BaseUrl.DEFAULT);
}
/** /**
* Return the provided {@link BaseUrl} or {@code null}. * Return the provided {@link BaseUrl} or {@code null}.
* @return the base URL or {@code null} * @return the base URL or {@code null}
@ -75,7 +67,6 @@ public class BaseUrlProviders {
.filter(Objects::nonNull) .filter(Objects::nonNull)
.findFirst() .findFirst()
.orElse(fallback); .orElse(fallback);
} }
} }

5
core/spring-boot-test/src/test/java/org/springframework/boot/test/http/server/BaseUrlProvidersTests.java

@ -33,11 +33,6 @@ import static org.mockito.Mockito.mock;
*/ */
class BaseUrlProvidersTests { class BaseUrlProvidersTests {
@Test
void getBaseUrlOrDefaultWhenNoProvidedBaseUrlReturnsDefault() {
assertThat(new BaseUrlProviders(Collections.emptyList()).getBaseUrlOrDefault()).isSameAs(BaseUrl.DEFAULT);
}
@Test @Test
void getBaseUrlWhenNoProvidedBaseUrlReturnsNull() { void getBaseUrlWhenNoProvidedBaseUrlReturnsNull() {
assertThat(new BaseUrlProviders(Collections.emptyList()).getBaseUrl()).isNull(); assertThat(new BaseUrlProviders(Collections.emptyList()).getBaseUrl()).isNull();

4
core/spring-boot-test/src/test/java/org/springframework/boot/test/http/server/BaseUrlTests.java

@ -70,7 +70,7 @@ class BaseUrlTests {
assertThat(atomicInteger.get()).isZero(); assertThat(atomicInteger.get()).isZero();
assertThat(baseUrl.isHttps()).isTrue(); assertThat(baseUrl.isHttps()).isTrue();
assertThat(resolve(baseUrl, "")).isEqualTo("1"); assertThat(resolve(baseUrl, "")).isEqualTo("1");
assertThat(resolve(baseUrl, "")).isEqualTo("2"); assertThat(resolve(baseUrl, "")).isEqualTo("1");
} }
@Test @Test
@ -94,7 +94,7 @@ class BaseUrlTests {
BaseUrl baseUrl = BaseUrl.of(true, () -> "https://example.com/" + atomicInteger.incrementAndGet()); BaseUrl baseUrl = BaseUrl.of(true, () -> "https://example.com/" + atomicInteger.incrementAndGet());
assertThat(resolve(baseUrl.withPath("/context"), "")).isEqualTo("https://example.com/1/context"); assertThat(resolve(baseUrl.withPath("/context"), "")).isEqualTo("https://example.com/1/context");
assertThat(resolve(baseUrl.withPath("/context").withPath("/test"), "/path")) assertThat(resolve(baseUrl.withPath("/context").withPath("/test"), "/path"))
.isEqualTo("https://example.com/2/context/test/path"); .isEqualTo("https://example.com/1/context/test/path");
} }
private String resolve(BaseUrl baseUrl, String path) { private String resolve(BaseUrl baseUrl, String path) {

7
module/spring-boot-graphql-test/src/main/java/org/springframework/boot/graphql/test/autoconfigure/tester/HttpGraphQlTesterAutoConfiguration.java

@ -60,10 +60,9 @@ public final class HttpGraphQlTesterAutoConfiguration {
private WebTestClient configureGraphQlWebTestClient(WebTestClient webTestClient, @Nullable BaseUrl baseUrl, private WebTestClient configureGraphQlWebTestClient(WebTestClient webTestClient, @Nullable BaseUrl baseUrl,
String graphQlPath) { String graphQlPath) {
WebTestClient.Builder builder = webTestClient.mutate(); WebTestClient.Builder builder = webTestClient.mutate();
if (baseUrl != null) { return (baseUrl != null)
return builder.uriBuilderFactory(BaseUrlUriBuilderFactory.get(baseUrl.withPath(graphQlPath))).build(); ? builder.uriBuilderFactory(BaseUrlUriBuilderFactory.get(baseUrl.withPath(graphQlPath))).build()
} : builder.baseUrl(graphQlPath).build();
return builder.baseUrl(graphQlPath).build();
} }
} }

5
module/spring-boot-resttestclient/src/main/java/org/springframework/boot/resttestclient/autoconfigure/TestRestTemplateAutoConfiguration.java

@ -46,10 +46,9 @@ public final class TestRestTemplateAutoConfiguration {
TestRestTemplate testRestTemplate(ObjectProvider<RestTemplateBuilder> builderProvider, TestRestTemplate testRestTemplate(ObjectProvider<RestTemplateBuilder> builderProvider,
ApplicationContext applicationContext) { ApplicationContext applicationContext) {
RestTemplateBuilder builder = builderProvider.getIfAvailable(RestTemplateBuilder::new); RestTemplateBuilder builder = builderProvider.getIfAvailable(RestTemplateBuilder::new);
BaseUrl baseUrl = new BaseUrlProviders(applicationContext).getBaseUrlOrDefault(); BaseUrl baseUrl = new BaseUrlProviders(applicationContext).getBaseUrl(BaseUrl.LOCALHOST);
boolean sslEnabled = baseUrl != null && baseUrl.isHttps();
TestRestTemplate template = new TestRestTemplate(builder, null, null, TestRestTemplate template = new TestRestTemplate(builder, null, null,
sslEnabled ? SSL_OPTIONS : DEFAULT_OPTIONS); baseUrl.isHttps() ? SSL_OPTIONS : DEFAULT_OPTIONS);
template.setUriTemplateHandler(BaseUrlUriBuilderFactory.get(baseUrl)); template.setUriTemplateHandler(BaseUrlUriBuilderFactory.get(baseUrl));
return template; return template;
} }

2
module/spring-boot-webmvc-test/src/main/java/org/springframework/boot/webmvc/test/autoconfigure/MockMvcWebClientAutoConfiguration.java

@ -46,7 +46,7 @@ public final class MockMvcWebClientAutoConfiguration {
@ConditionalOnMissingBean({ WebClient.class, MockMvcWebClientBuilder.class }) @ConditionalOnMissingBean({ WebClient.class, MockMvcWebClientBuilder.class })
@ConditionalOnBean(MockMvc.class) @ConditionalOnBean(MockMvc.class)
MockMvcWebClientBuilder mockMvcWebClientBuilder(MockMvc mockMvc, ApplicationContext applicationContext) { MockMvcWebClientBuilder mockMvcWebClientBuilder(MockMvc mockMvc, ApplicationContext applicationContext) {
BaseUrl baseUrl = new BaseUrlProviders(applicationContext).getBaseUrlOrDefault(); BaseUrl baseUrl = new BaseUrlProviders(applicationContext).getBaseUrl(BaseUrl.LOCALHOST);
return MockMvcWebClientBuilder.mockMvcSetup(mockMvc).withDelegate(new BaseUrlWebClient(baseUrl)); return MockMvcWebClientBuilder.mockMvcSetup(mockMvc).withDelegate(new BaseUrlWebClient(baseUrl));
} }

2
module/spring-boot-webmvc-test/src/main/java/org/springframework/boot/webmvc/test/autoconfigure/MockMvcWebDriverAutoConfiguration.java

@ -49,7 +49,7 @@ public final class MockMvcWebDriverAutoConfiguration {
@ConditionalOnMissingBean({ WebDriver.class, MockMvcHtmlUnitDriverBuilder.class }) @ConditionalOnMissingBean({ WebDriver.class, MockMvcHtmlUnitDriverBuilder.class })
@ConditionalOnBean(MockMvc.class) @ConditionalOnBean(MockMvc.class)
MockMvcHtmlUnitDriverBuilder mockMvcHtmlUnitDriverBuilder(MockMvc mockMvc, ApplicationContext applicationContext) { MockMvcHtmlUnitDriverBuilder mockMvcHtmlUnitDriverBuilder(MockMvc mockMvc, ApplicationContext applicationContext) {
BaseUrl baseUrl = new BaseUrlProviders(applicationContext).getBaseUrlOrDefault(); BaseUrl baseUrl = new BaseUrlProviders(applicationContext).getBaseUrl(BaseUrl.LOCALHOST);
MockMvcHtmlUnitDriverBuilder builder = MockMvcHtmlUnitDriverBuilder.mockMvcSetup(mockMvc) MockMvcHtmlUnitDriverBuilder builder = MockMvcHtmlUnitDriverBuilder.mockMvcSetup(mockMvc)
.withDelegate(new BaseUrlWebConnectionHtmlUnitDriver(baseUrl, BrowserVersion.CHROME)); .withDelegate(new BaseUrlWebConnectionHtmlUnitDriver(baseUrl, BrowserVersion.CHROME));
return builder; return builder;

2
smoke-test/spring-boot-smoke-test-actuator-custom-security/src/test/java/smoketest/actuator/customsecurity/AbstractSampleActuatorCustomSecurityTests.java

@ -202,7 +202,7 @@ abstract class AbstractSampleActuatorCustomSecurityTests {
} }
private TestRestTemplate configure(TestRestTemplate restTemplate) { private TestRestTemplate configure(TestRestTemplate restTemplate) {
BaseUrl baseUrl = new BaseUrlProviders(getApplicationContext()).getBaseUrlOrDefault(); BaseUrl baseUrl = new BaseUrlProviders(getApplicationContext()).getBaseUrl();
restTemplate.setUriTemplateHandler(BaseUrlUriBuilderFactory.get(baseUrl)); restTemplate.setUriTemplateHandler(BaseUrlUriBuilderFactory.get(baseUrl));
return restTemplate; return restTemplate;
} }

2
smoke-test/spring-boot-smoke-test-actuator-custom-security/src/test/java/smoketest/actuator/customsecurity/CorsSampleActuatorApplicationTests.java

@ -56,7 +56,7 @@ class CorsSampleActuatorApplicationTests {
@BeforeEach @BeforeEach
void setUp() { void setUp() {
RestTemplateBuilder builder = new RestTemplateBuilder(); RestTemplateBuilder builder = new RestTemplateBuilder();
BaseUrl baseUrl = new BaseUrlProviders(this.applicationContext).getBaseUrlOrDefault(); BaseUrl baseUrl = new BaseUrlProviders(this.applicationContext).getBaseUrl();
builder = builder.uriTemplateHandler(BaseUrlUriBuilderFactory.get(baseUrl)); builder = builder.uriTemplateHandler(BaseUrlUriBuilderFactory.get(baseUrl));
this.testRestTemplate = new TestRestTemplate(builder); this.testRestTemplate = new TestRestTemplate(builder);
} }

2
smoke-test/spring-boot-smoke-test-actuator-extension/src/test/java/smoketest/actuator/extension/SampleActuatorExtensionApplicationTests.java

@ -67,7 +67,7 @@ class SampleActuatorExtensionApplicationTests {
void healthExtensionWithAuthHeader() { void healthExtensionWithAuthHeader() {
TestRestTemplate restTemplate = new TestRestTemplate( TestRestTemplate restTemplate = new TestRestTemplate(
this.restTemplateBuilder.defaultHeader("Authorization", "Bearer secret")); this.restTemplateBuilder.defaultHeader("Authorization", "Bearer secret"));
BaseUrl baseUrl = new BaseUrlProviders(this.applicationContext).getBaseUrlOrDefault(); BaseUrl baseUrl = new BaseUrlProviders(this.applicationContext).getBaseUrl();
restTemplate.setUriTemplateHandler(BaseUrlUriBuilderFactory.get(baseUrl)); restTemplate.setUriTemplateHandler(BaseUrlUriBuilderFactory.get(baseUrl));
ResponseEntity<Map> entity = restTemplate.getForEntity("/myextension/health", Map.class); ResponseEntity<Map> entity = restTemplate.getForEntity("/myextension/health", Map.class);
assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.OK); assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.OK);

2
smoke-test/spring-boot-smoke-test-actuator/src/test/java/smoketest/actuator/CorsSampleActuatorApplicationTests.java

@ -56,7 +56,7 @@ class CorsSampleActuatorApplicationTests {
@BeforeEach @BeforeEach
void setUp() { void setUp() {
RestTemplateBuilder builder = new RestTemplateBuilder(); RestTemplateBuilder builder = new RestTemplateBuilder();
BaseUrl baseUrl = new BaseUrlProviders(this.applicationContext).getBaseUrlOrDefault(); BaseUrl baseUrl = new BaseUrlProviders(this.applicationContext).getBaseUrl();
builder = builder.uriTemplateHandler(BaseUrlUriBuilderFactory.get(baseUrl)); builder = builder.uriTemplateHandler(BaseUrlUriBuilderFactory.get(baseUrl));
this.testRestTemplate = new TestRestTemplate(builder); this.testRestTemplate = new TestRestTemplate(builder);
} }

Loading…
Cancel
Save