Avoid duplication of parameters when POSTing form URL encoded bodies

Previously if a request body contained form URL encoded content,
parameters would be duplicated in the request body and in the
request URL in the curl, HTTPie, and HTTP request snippets.

This commit updates the affected snippets so that parameters are not
added to the URL when they will also be represented in the request
body.

Closes gh-514
This commit is contained in:
Andy Wilkinson
2018-06-25 16:11:36 +01:00
parent 1e35e8279c
commit 86c31c96b9
6 changed files with 63 additions and 4 deletions

View File

@@ -23,6 +23,7 @@ import java.util.Map;
import java.util.Map.Entry;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.restdocs.operation.Operation;
import org.springframework.restdocs.operation.OperationRequest;
import org.springframework.restdocs.operation.OperationRequestPart;
@@ -119,7 +120,9 @@ public class CurlRequestSnippet extends TemplatedSnippet {
}
private boolean includeParametersInUri(OperationRequest request) {
return request.getMethod() == HttpMethod.GET || request.getContent().length > 0;
return request.getMethod() == HttpMethod.GET || (request.getContent().length > 0
&& !MediaType.APPLICATION_FORM_URLENCODED
.isCompatibleWith(request.getHeaders().getContentType()));
}
private String getOptions(Operation operation) {

View File

@@ -152,13 +152,22 @@ public class HttpieRequestSnippet extends TemplatedSnippet {
private void writeOptions(OperationRequest request, PrintWriter writer) {
if (!request.getParts().isEmpty()
|| (!request.getParameters().getUniqueParameters(request.getUri())
.isEmpty() && !includeParametersInUri(request))) {
.isEmpty() && !includeParametersInUri(request)
&& includeParametersAsFormOptions(request))) {
writer.print("--form ");
}
}
private boolean includeParametersInUri(OperationRequest request) {
return request.getMethod() == HttpMethod.GET || request.getContent().length > 0;
return request.getMethod() == HttpMethod.GET || (request.getContent().length > 0
&& !MediaType.APPLICATION_FORM_URLENCODED
.isCompatibleWith(request.getHeaders().getContentType()));
}
private boolean includeParametersAsFormOptions(OperationRequest request) {
return request.getMethod() != HttpMethod.GET && (request.getContent().length == 0
|| !MediaType.APPLICATION_FORM_URLENCODED
.isCompatibleWith(request.getHeaders().getContentType()));
}
private void writeUserOptionIfNecessary(CliOperationRequest request,

View File

@@ -94,7 +94,9 @@ public class HttpRequestSnippet extends TemplatedSnippet {
}
private boolean includeParametersInUri(OperationRequest request) {
return request.getMethod() == HttpMethod.GET || request.getContent().length > 0;
return request.getMethod() == HttpMethod.GET || (request.getContent().length > 0
&& !MediaType.APPLICATION_FORM_URLENCODED
.isCompatibleWith(request.getHeaders().getContentType()));
}
private List<Map<String, String>> getHeaders(OperationRequest request) {

View File

@@ -213,6 +213,20 @@ public class CurlRequestSnippetTests extends AbstractSnippetTests {
.method("POST").param("a", "alpha").param("b", "bravo").build());
}
@Test
public void postRequestWithOverlappingParametersAndFormUrlEncodedBody()
throws IOException {
this.snippets.expectCurlRequest().withContents(
codeBlock("bash").content("$ curl 'http://localhost/foo' -i -X POST "
+ "-H 'Content-Type: application/x-www-form-urlencoded' "
+ "-d 'a=alpha&b=bravo'"));
new CurlRequestSnippet(this.commandFormatter).document(this.operationBuilder
.request("http://localhost/foo").method("POST").content("a=alpha&b=bravo")
.header(HttpHeaders.CONTENT_TYPE,
MediaType.APPLICATION_FORM_URLENCODED_VALUE)
.param("a", "alpha").param("b", "bravo").build());
}
@Test
public void putRequestWithOneParameter() throws IOException {
this.snippets.expectCurlRequest().withContents(codeBlock("bash")

View File

@@ -214,6 +214,20 @@ public class HttpieRequestSnippetTests extends AbstractSnippetTests {
.method("POST").param("a", "alpha").param("b", "bravo").build());
}
@Test
public void postRequestWithOverlappingParametersAndFormUrlEncodedBody()
throws IOException {
this.snippets.expectHttpieRequest()
.withContents(codeBlock("bash").content(
"$ echo 'a=alpha&b=bravo' | http POST 'http://localhost/foo' "
+ "'Content-Type:application/x-www-form-urlencoded'"));
new HttpieRequestSnippet(this.commandFormatter).document(this.operationBuilder
.request("http://localhost/foo").method("POST").content("a=alpha&b=bravo")
.header(HttpHeaders.CONTENT_TYPE,
MediaType.APPLICATION_FORM_URLENCODED_VALUE)
.param("a", "alpha").param("b", "bravo").build());
}
@Test
public void putRequestWithOneParameter() throws IOException {
this.snippets.expectHttpieRequest().withContents(codeBlock("bash")

View File

@@ -202,6 +202,23 @@ public class HttpRequestSnippetTests extends AbstractSnippetTests {
.param("a", "alpha").param("b", "bravo").content(content).build());
}
@Test
public void postRequestWithOverlappingParametersAndFormUrlEncodedBody()
throws IOException {
String content = "a=alpha&b=bravo";
this.snippets.expectHttpRequest()
.withContents(httpRequest(RequestMethod.POST, "/foo")
.header(HttpHeaders.CONTENT_TYPE,
MediaType.APPLICATION_FORM_URLENCODED_VALUE)
.header(HttpHeaders.HOST, "localhost").content(content)
.header(HttpHeaders.CONTENT_LENGTH, content.getBytes().length));
new HttpRequestSnippet().document(this.operationBuilder
.request("http://localhost/foo").method("POST").content("a=alpha&b=bravo")
.header(HttpHeaders.CONTENT_TYPE,
MediaType.APPLICATION_FORM_URLENCODED_VALUE)
.param("a", "alpha").param("b", "bravo").build());
}
@Test
public void postRequestWithCharset() throws IOException {
String japaneseContent = "\u30b3\u30f3\u30c6\u30f3\u30c4";