Skip to content

Commit 97ddf3d

Browse files
committed
Fix handling of empty querty string parameters
Previously empty parameters in a query string were handled inconsistently such that they sometimes had a value of "" in a list and sometimes were represented as an empty list. This inconsistency lead to the parameter appearing twice in the cURL request snippet. This commit removes the inconsistency by always using an empty string to represent an empty query parameter value. Fixes gh-647
1 parent 92926d6 commit 97ddf3d

File tree

5 files changed

+52
-4
lines changed

5 files changed

+52
-4
lines changed

spring-restdocs-core/src/main/java/org/springframework/restdocs/operation/QueryStringParser.java

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -64,10 +64,8 @@ private void processParameter(String parameter, Parameters parameters) {
6464
parameters.add(decode(name), decode(value));
6565
}
6666
else {
67-
List<String> values = parameters.get(components[0]);
68-
if (values == null) {
69-
parameters.put(components[0], new LinkedList<String>());
70-
}
67+
List<String> values = parameters.computeIfAbsent(components[0], (p) -> new LinkedList<String>());
68+
values.add("");
7169
}
7270
}
7371
else {

spring-restdocs-core/src/test/java/org/springframework/restdocs/operation/QueryStringParserTests.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,4 +81,18 @@ public void malformedParameter() {
8181
this.queryStringParser.parse(URI.create("http://localhost?a=apple=avocado"));
8282
}
8383

84+
@Test
85+
public void emptyParameter() {
86+
Parameters parameters = this.queryStringParser.parse(URI.create("http://localhost?a="));
87+
assertThat(parameters.size()).isEqualTo(1);
88+
assertThat(parameters).containsEntry("a", Arrays.asList(""));
89+
}
90+
91+
@Test
92+
public void emptyAndNotEmptyParameter() {
93+
Parameters parameters = this.queryStringParser.parse(URI.create("http://localhost?a=&a=alpha"));
94+
assertThat(parameters.size()).isEqualTo(1);
95+
assertThat(parameters).containsEntry("a", Arrays.asList("", "alpha"));
96+
}
97+
8498
}

spring-restdocs-mockmvc/src/test/java/org/springframework/restdocs/mockmvc/MockMvcRestDocumentationIntegrationTests.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,19 @@ public void curlSnippetWithQueryStringOnPost() throws Exception {
185185
+ " -H 'Accept: application/json' \\%n" + " -d 'a=alpha'"))));
186186
}
187187

188+
@Test
189+
public void curlSnippetWithEmptyParameterQueryString() throws Exception {
190+
MockMvc mockMvc = MockMvcBuilders.webAppContextSetup(this.context)
191+
.apply(documentationConfiguration(this.restDocumentation)).build();
192+
mockMvc.perform(get("/").param("a", "").accept(MediaType.APPLICATION_JSON)).andExpect(status().isOk())
193+
.andDo(document("curl-snippet-with-empty-parameter-query-string"));
194+
assertThat(
195+
new File("build/generated-snippets/curl-snippet-with-empty-parameter-query-string/curl-request.adoc"))
196+
.has(content(codeBlock(TemplateFormats.asciidoctor(), "bash")
197+
.withContent(String.format("$ curl 'http://localhost:8080/?a=' -i -X GET \\%n"
198+
+ " -H 'Accept: application/json'"))));
199+
}
200+
188201
@Test
189202
public void curlSnippetWithContentAndParametersOnPost() throws Exception {
190203
MockMvc mockMvc = MockMvcBuilders.webAppContextSetup(this.context)

spring-restdocs-restassured/src/test/java/org/springframework/restdocs/restassured3/RestAssuredRestDocumentationIntegrationTests.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,18 @@ public void curlSnippetWithCookies() throws Exception {
120120
+ " -H 'Content-Type: " + contentType + "' \\%n" + " --cookie 'cookieName=cookieVal'"))));
121121
}
122122

123+
@Test
124+
public void curlSnippetWithEmptyParameterQueryString() throws Exception {
125+
given().port(tomcat.getPort()).filter(documentationConfiguration(this.restDocumentation))
126+
.filter(document("curl-snippet-with-empty-parameter-query-string")).accept("application/json")
127+
.param("a", "").get("/").then().statusCode(200);
128+
assertThat(
129+
new File("build/generated-snippets/curl-snippet-with-empty-parameter-query-string/curl-request.adoc"))
130+
.has(content(codeBlock(TemplateFormats.asciidoctor(), "bash")
131+
.withContent(String.format("$ curl 'http://localhost:" + tomcat.getPort()
132+
+ "/?a=' -i -X GET \\%n -H 'Accept: application/json'"))));
133+
}
134+
123135
@Test
124136
public void curlSnippetWithQueryStringOnPost() throws Exception {
125137
given().port(tomcat.getPort()).filter(documentationConfiguration(this.restDocumentation))

spring-restdocs-webtestclient/src/test/java/org/springframework/restdocs/webtestclient/WebTestClientRestDocumentationIntegrationTests.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,17 @@ public void curlSnippetWithCookies() throws Exception {
165165
+ " -H 'Accept: application/json' \\%n" + " --cookie 'cookieName=cookieVal'"))));
166166
}
167167

168+
@Test
169+
public void curlSnippetWithEmptyParameterQueryString() throws Exception {
170+
this.webTestClient.get().uri("/?a=").accept(MediaType.APPLICATION_JSON).exchange().expectStatus().isOk()
171+
.expectBody().consumeWith(document("curl-snippet-with-empty-parameter-query-string"));
172+
assertThat(
173+
new File("build/generated-snippets/curl-snippet-with-empty-parameter-query-string/curl-request.adoc"))
174+
.has(content(codeBlock(TemplateFormats.asciidoctor(), "bash")
175+
.withContent(String.format("$ curl 'https://api.example.com/?a=' -i -X GET \\%n"
176+
+ " -H 'Accept: application/json'"))));
177+
}
178+
168179
@Test
169180
public void httpieSnippetWithCookies() throws Exception {
170181
this.webTestClient.get().uri("/").cookie("cookieName", "cookieVal").accept(MediaType.APPLICATION_JSON)

0 commit comments

Comments
 (0)