Handle form and query parameters separately
Previously, form and query parameters were handled together as request parameters. Howeer, request parameters are a server-side construct that's specific to the servlet specification. As such they're not appropriate for the client-side documentation that Spring REST Docs aims to produce. This commit replaces support for documenting request parameters with support for documenting query paramters found in the query string of the request's URI and for documenting form parameters found in the form URL encoded body of the request. Closes gh-832
This commit is contained in:
@@ -30,9 +30,7 @@ import org.springframework.core.io.buffer.DataBufferUtils;
|
||||
import org.springframework.core.io.buffer.DefaultDataBuffer;
|
||||
import org.springframework.core.io.buffer.DefaultDataBufferFactory;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ReactiveHttpInputMessage;
|
||||
import org.springframework.http.codec.FormHttpMessageReader;
|
||||
import org.springframework.http.codec.HttpMessageReader;
|
||||
import org.springframework.http.codec.multipart.DefaultPartHttpMessageReader;
|
||||
import org.springframework.http.codec.multipart.FilePart;
|
||||
@@ -42,14 +40,11 @@ import org.springframework.restdocs.operation.OperationRequest;
|
||||
import org.springframework.restdocs.operation.OperationRequestFactory;
|
||||
import org.springframework.restdocs.operation.OperationRequestPart;
|
||||
import org.springframework.restdocs.operation.OperationRequestPartFactory;
|
||||
import org.springframework.restdocs.operation.Parameters;
|
||||
import org.springframework.restdocs.operation.QueryStringParser;
|
||||
import org.springframework.restdocs.operation.RequestConverter;
|
||||
import org.springframework.restdocs.operation.RequestCookie;
|
||||
import org.springframework.test.web.reactive.server.ExchangeResult;
|
||||
import org.springframework.test.web.reactive.server.WebTestClient;
|
||||
import org.springframework.util.LinkedMultiValueMap;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
|
||||
/**
|
||||
* A {@link RequestConverter} for creating an {@link OperationRequest} derived from an
|
||||
@@ -59,18 +54,11 @@ import org.springframework.util.MultiValueMap;
|
||||
*/
|
||||
class WebTestClientRequestConverter implements RequestConverter<ExchangeResult> {
|
||||
|
||||
private static final ResolvableType FORM_DATA_TYPE = ResolvableType.forClassWithGenerics(MultiValueMap.class,
|
||||
String.class, String.class);
|
||||
|
||||
private final QueryStringParser queryStringParser = new QueryStringParser();
|
||||
|
||||
private final FormHttpMessageReader formDataReader = new FormHttpMessageReader();
|
||||
|
||||
@Override
|
||||
public OperationRequest convert(ExchangeResult result) {
|
||||
HttpHeaders headers = extractRequestHeaders(result);
|
||||
return new OperationRequestFactory().create(result.getUrl(), result.getMethod(), result.getRequestBodyContent(),
|
||||
headers, extractParameters(result), extractRequestParts(result), extractCookies(headers));
|
||||
headers, extractRequestParts(result), extractCookies(headers));
|
||||
}
|
||||
|
||||
private HttpHeaders extractRequestHeaders(ExchangeResult result) {
|
||||
@@ -80,16 +68,6 @@ class WebTestClientRequestConverter implements RequestConverter<ExchangeResult>
|
||||
return extracted;
|
||||
}
|
||||
|
||||
private Parameters extractParameters(ExchangeResult result) {
|
||||
Parameters parameters = new Parameters();
|
||||
parameters.addAll(this.queryStringParser.parse(result.getUrl()));
|
||||
if (MediaType.APPLICATION_FORM_URLENCODED.isCompatibleWith(result.getRequestHeaders().getContentType())) {
|
||||
parameters.addAll(this.formDataReader
|
||||
.readMono(FORM_DATA_TYPE, new ExchangeResultReactiveHttpInputMessage(result), null).block());
|
||||
}
|
||||
return parameters;
|
||||
}
|
||||
|
||||
private List<OperationRequestPart> extractRequestParts(ExchangeResult result) {
|
||||
HttpMessageReader<Part> partHttpMessageReader = new DefaultPartHttpMessageReader();
|
||||
return new MultipartHttpMessageReader(partHttpMessageReader)
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
package org.springframework.restdocs.webtestclient;
|
||||
|
||||
import java.net.URI;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.junit.Test;
|
||||
@@ -103,15 +104,12 @@ public class WebTestClientRequestConverterTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getRequestWithQueryStringPopulatesParameters() {
|
||||
public void getRequestWithQueryString() {
|
||||
ExchangeResult result = WebTestClient.bindToRouterFunction(RouterFunctions.route(GET("/foo"), (req) -> null))
|
||||
.configureClient().baseUrl("http://localhost").build().get().uri("/foo?a=alpha&b=bravo").exchange()
|
||||
.expectBody().returnResult();
|
||||
OperationRequest request = this.converter.convert(result);
|
||||
assertThat(request.getUri()).isEqualTo(URI.create("http://localhost/foo?a=alpha&b=bravo"));
|
||||
assertThat(request.getParameters()).hasSize(2);
|
||||
assertThat(request.getParameters()).containsEntry("a", Arrays.asList("alpha"));
|
||||
assertThat(request.getParameters()).containsEntry("b", Arrays.asList("bravo"));
|
||||
assertThat(request.getMethod()).isEqualTo(HttpMethod.GET);
|
||||
}
|
||||
|
||||
@@ -128,9 +126,9 @@ public class WebTestClientRequestConverterTests {
|
||||
OperationRequest request = this.converter.convert(result);
|
||||
assertThat(request.getUri()).isEqualTo(URI.create("http://localhost/foo"));
|
||||
assertThat(request.getMethod()).isEqualTo(HttpMethod.POST);
|
||||
assertThat(request.getParameters()).hasSize(2);
|
||||
assertThat(request.getParameters()).containsEntry("a", Arrays.asList("alpha", "apple"));
|
||||
assertThat(request.getParameters()).containsEntry("b", Arrays.asList("br&vo"));
|
||||
assertThat(request.getContentAsString()).isEqualTo("a=alpha&a=apple&b=br%26vo");
|
||||
assertThat(request.getHeaders().getContentType())
|
||||
.isEqualTo(new MediaType(MediaType.APPLICATION_FORM_URLENCODED, StandardCharsets.UTF_8));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -144,9 +142,6 @@ public class WebTestClientRequestConverterTests {
|
||||
OperationRequest request = this.converter.convert(result);
|
||||
assertThat(request.getUri()).isEqualTo(URI.create("http://localhost/foo?a=alpha&a=apple&b=br%26vo"));
|
||||
assertThat(request.getMethod()).isEqualTo(HttpMethod.POST);
|
||||
assertThat(request.getParameters()).hasSize(2);
|
||||
assertThat(request.getParameters()).containsEntry("a", Arrays.asList("alpha", "apple"));
|
||||
assertThat(request.getParameters()).containsEntry("b", Arrays.asList("br&vo"));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -162,9 +157,9 @@ public class WebTestClientRequestConverterTests {
|
||||
OperationRequest request = this.converter.convert(result);
|
||||
assertThat(request.getUri()).isEqualTo(URI.create("http://localhost/foo?a=alpha&b=br%26vo"));
|
||||
assertThat(request.getMethod()).isEqualTo(HttpMethod.POST);
|
||||
assertThat(request.getParameters()).hasSize(2);
|
||||
assertThat(request.getParameters()).containsEntry("a", Arrays.asList("alpha", "apple"));
|
||||
assertThat(request.getParameters()).containsEntry("b", Arrays.asList("br&vo"));
|
||||
assertThat(request.getContentAsString()).isEqualTo("a=apple");
|
||||
assertThat(request.getHeaders().getContentType())
|
||||
.isEqualTo(new MediaType(MediaType.APPLICATION_FORM_URLENCODED, StandardCharsets.UTF_8));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -64,7 +64,7 @@ import static org.assertj.core.api.Assertions.fail;
|
||||
import static org.springframework.restdocs.request.RequestDocumentation.parameterWithName;
|
||||
import static org.springframework.restdocs.request.RequestDocumentation.partWithName;
|
||||
import static org.springframework.restdocs.request.RequestDocumentation.pathParameters;
|
||||
import static org.springframework.restdocs.request.RequestDocumentation.requestParameters;
|
||||
import static org.springframework.restdocs.request.RequestDocumentation.queryParameters;
|
||||
import static org.springframework.restdocs.request.RequestDocumentation.requestParts;
|
||||
import static org.springframework.restdocs.webtestclient.WebTestClientRestDocumentation.document;
|
||||
import static org.springframework.restdocs.webtestclient.WebTestClientRestDocumentation.documentationConfiguration;
|
||||
@@ -122,12 +122,11 @@ public class WebTestClientRestDocumentationIntegrationTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestParametersSnippet() {
|
||||
this.webTestClient.get().uri("/?a=alpha&b=bravo").exchange().expectStatus().isOk().expectBody()
|
||||
.consumeWith(document("request-parameters",
|
||||
requestParameters(parameterWithName("a").description("Alpha description"),
|
||||
parameterWithName("b").description("Bravo description"))));
|
||||
assertThat(new File("build/generated-snippets/request-parameters/request-parameters.adoc"))
|
||||
public void queryParametersSnippet() {
|
||||
this.webTestClient.get().uri("/?a=alpha&b=bravo").exchange().expectStatus().isOk().expectBody().consumeWith(
|
||||
document("query-parameters", queryParameters(parameterWithName("a").description("Alpha description"),
|
||||
parameterWithName("b").description("Bravo description"))));
|
||||
assertThat(new File("build/generated-snippets/query-parameters/query-parameters.adoc"))
|
||||
.has(content(tableWithHeader(TemplateFormats.asciidoctor(), "Parameter", "Description")
|
||||
.row("`a`", "Alpha description").row("`b`", "Bravo description")));
|
||||
}
|
||||
@@ -204,7 +203,7 @@ public class WebTestClientRestDocumentationIntegrationTests {
|
||||
}
|
||||
|
||||
private Condition<File> content(final Condition<String> delegate) {
|
||||
return new Condition<File>() {
|
||||
return new Condition<>() {
|
||||
|
||||
@Override
|
||||
public boolean matches(File value) {
|
||||
|
||||
Reference in New Issue
Block a user