diff --git a/docs/src/docs/asciidoc/configuration.adoc b/docs/src/docs/asciidoc/configuration.adoc index ceb607e5..9dad1faf 100644 --- a/docs/src/docs/asciidoc/configuration.adoc +++ b/docs/src/docs/asciidoc/configuration.adoc @@ -55,9 +55,16 @@ specific preprocessor>> is provided for this purpose. [[configuration-uris-webtestclient]] ==== WebTestClient URI customization -When using WebTestClient, the documented URIs can be customized using the +When using WebTestClient, the default base for URIs documented by Spring REST +Docs is `http://localhost:8080`. This base can be customized using the {spring-framework-api}/org/springframework/test/web/reactive/server/WebTestClient.Builder.html#baseUrl-java.lang.String-[ -`baseUrl(String)` method on `WebTestClient.Builder`]. +`baseUrl(String)` method on `WebTestClient.Builder`]: + +[source,java,indent=0] +---- +include::{examples-dir}/com/example/webtestclient/CustomUriConfiguration.java[tags=custom-uri-configuration] +---- +<1> Configure the base of documented URIs to be `https://api.example.com`. diff --git a/docs/src/test/java/com/example/webtestclient/CustomUriConfiguration.java b/docs/src/test/java/com/example/webtestclient/CustomUriConfiguration.java new file mode 100644 index 00000000..6f12f4c9 --- /dev/null +++ b/docs/src/test/java/com/example/webtestclient/CustomUriConfiguration.java @@ -0,0 +1,50 @@ +/* + * Copyright 2014-2017 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.example.webtestclient; + +import org.junit.Before; +import org.junit.Rule; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.restdocs.JUnitRestDocumentation; +import org.springframework.test.web.reactive.server.WebTestClient; +import org.springframework.web.context.WebApplicationContext; + +import static org.springframework.restdocs.webtestclient.WebTestClientRestDocumentation.documentationConfiguration; + +public class CustomUriConfiguration { + + @Rule + public final JUnitRestDocumentation restDocumentation = new JUnitRestDocumentation(); + + @SuppressWarnings("unused") + private WebTestClient webTestClient; + + @Autowired + private WebApplicationContext context; + + // tag::custom-uri-configuration[] + @Before + public void setUp() { + this.webTestClient = WebTestClient.bindToApplicationContext(this.context) + .configureClient() + .baseUrl("https://api.example.com") // <1> + .filter(documentationConfiguration(this.restDocumentation)).build(); + } + // end::custom-uri-configuration[] + +} diff --git a/spring-restdocs-webtestclient/src/main/java/org/springframework/restdocs/webtestclient/WebTestClientRestDocumentationConfigurer.java b/spring-restdocs-webtestclient/src/main/java/org/springframework/restdocs/webtestclient/WebTestClientRestDocumentationConfigurer.java index d00d5d63..a31880f9 100644 --- a/spring-restdocs-webtestclient/src/main/java/org/springframework/restdocs/webtestclient/WebTestClientRestDocumentationConfigurer.java +++ b/spring-restdocs-webtestclient/src/main/java/org/springframework/restdocs/webtestclient/WebTestClientRestDocumentationConfigurer.java @@ -16,6 +16,8 @@ package org.springframework.restdocs.webtestclient; +import java.net.URI; +import java.net.URISyntaxException; import java.util.HashMap; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; @@ -27,6 +29,7 @@ import org.springframework.restdocs.RestDocumentationContext; import org.springframework.restdocs.RestDocumentationContextProvider; import org.springframework.restdocs.config.RestDocumentationConfigurer; import org.springframework.test.web.reactive.server.WebTestClient; +import org.springframework.util.StringUtils; import org.springframework.web.reactive.function.client.ClientRequest; import org.springframework.web.reactive.function.client.ClientResponse; import org.springframework.web.reactive.function.client.ExchangeFilterFunction; @@ -52,7 +55,8 @@ public class WebTestClientRestDocumentationConfigurer extends private final RestDocumentationContextProvider contextProvider; - WebTestClientRestDocumentationConfigurer(RestDocumentationContextProvider contextProvider) { + WebTestClientRestDocumentationConfigurer( + RestDocumentationContextProvider contextProvider) { this.contextProvider = contextProvider; } @@ -83,7 +87,23 @@ public class WebTestClientRestDocumentationConfigurer extends public Mono filter(ClientRequest request, ExchangeFunction next) { String index = request.headers().getFirst(WebTestClient.WEBTESTCLIENT_REQUEST_ID); configurations.put(index, createConfiguration()); - return next.exchange(request); + return next.exchange(applyUriDefaults(request)); + } + + private ClientRequest applyUriDefaults(ClientRequest request) { + URI requestUri = request.url(); + if (!StringUtils.isEmpty(requestUri.getHost())) { + return request; + } + try { + requestUri = new URI("http", requestUri.getUserInfo(), "localhost", 8080, + requestUri.getPath(), requestUri.getQuery(), + requestUri.getFragment()); + return ClientRequest.from(request).url(requestUri).build(); + } + catch (URISyntaxException ex) { + throw new IllegalStateException(ex); + } } } diff --git a/spring-restdocs-webtestclient/src/test/java/org/springframework/restdocs/webtestclient/WebTestClientRestDocumentationConfigurerTests.java b/spring-restdocs-webtestclient/src/test/java/org/springframework/restdocs/webtestclient/WebTestClientRestDocumentationConfigurerTests.java index ae186cf1..1f4e67b2 100644 --- a/spring-restdocs-webtestclient/src/test/java/org/springframework/restdocs/webtestclient/WebTestClientRestDocumentationConfigurerTests.java +++ b/spring-restdocs-webtestclient/src/test/java/org/springframework/restdocs/webtestclient/WebTestClientRestDocumentationConfigurerTests.java @@ -16,22 +16,26 @@ package org.springframework.restdocs.webtestclient; +import java.net.URI; import java.util.Map; import org.junit.Rule; import org.junit.Test; +import org.mockito.ArgumentCaptor; -import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; import org.springframework.restdocs.JUnitRestDocumentation; import org.springframework.test.web.reactive.server.WebTestClient; import org.springframework.web.reactive.function.client.ClientRequest; import org.springframework.web.reactive.function.client.ExchangeFunction; +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.CoreMatchers.notNullValue; import static org.hamcrest.CoreMatchers.nullValue; import static org.junit.Assert.assertThat; -import static org.mockito.BDDMockito.given; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; /** * Tests for {@link WebTestClientRestDocumentationConfigurer}. @@ -48,17 +52,43 @@ public class WebTestClientRestDocumentationConfigurerTests { @Test public void configurationCanBeRetrievedButOnlyOnce() { - ClientRequest request = mock(ClientRequest.class); - HttpHeaders headers = new HttpHeaders(); - headers.add(WebTestClient.WEBTESTCLIENT_REQUEST_ID, "1"); - given(request.headers()).willReturn(headers); + ClientRequest request = ClientRequest.method(HttpMethod.GET, URI.create("/test")) + .header(WebTestClient.WEBTESTCLIENT_REQUEST_ID, "1").build(); this.configurer.filter(request, mock(ExchangeFunction.class)); Map configuration = WebTestClientRestDocumentationConfigurer - .retrieveConfiguration(headers); + .retrieveConfiguration(request.headers()); assertThat(configuration, notNullValue()); - assertThat( - WebTestClientRestDocumentationConfigurer.retrieveConfiguration(headers), - nullValue()); + assertThat(WebTestClientRestDocumentationConfigurer + .retrieveConfiguration(request.headers()), nullValue()); + } + + @Test + public void requestUriHasDefaultsAppliedWhenItHasNoHost() { + ClientRequest request = ClientRequest + .method(HttpMethod.GET, URI.create("/test?foo=bar#baz")) + .header(WebTestClient.WEBTESTCLIENT_REQUEST_ID, "1").build(); + ExchangeFunction exchangeFunction = mock(ExchangeFunction.class); + this.configurer.filter(request, exchangeFunction); + ArgumentCaptor requestCaptor = ArgumentCaptor + .forClass(ClientRequest.class); + verify(exchangeFunction).exchange(requestCaptor.capture()); + assertThat(requestCaptor.getValue().url(), + is(equalTo(URI.create("http://localhost:8080/test?foo=bar#baz")))); + } + + @Test + public void requestUriIsNotChangedWhenItHasAHost() { + ClientRequest request = ClientRequest + .method(HttpMethod.GET, + URI.create("https://api.example.com:4567/test?foo=bar#baz")) + .header(WebTestClient.WEBTESTCLIENT_REQUEST_ID, "1").build(); + ExchangeFunction exchangeFunction = mock(ExchangeFunction.class); + this.configurer.filter(request, exchangeFunction); + ArgumentCaptor requestCaptor = ArgumentCaptor + .forClass(ClientRequest.class); + verify(exchangeFunction).exchange(requestCaptor.capture()); + assertThat(requestCaptor.getValue().url(), + is(equalTo(URI.create("https://api.example.com:4567/test?foo=bar#baz")))); } }