From c3efc4128f7ba585004458fa20e4cf42b5f9a4d2 Mon Sep 17 00:00:00 2001 From: Yann Le Guern Date: Fri, 6 Mar 2015 18:56:42 +0100 Subject: [PATCH] Use request parameters to create query string for GET requests Previously, only the request's query string was considered when creating the curl command's request URI. This meant that query parameters configured via request.addParameter where not included in the URI. This commit enhances CurlRequestDocumentationAction so that, in the absence of a query string, it will use a GET request's parameters to produce the query string include in the curl command's URI. Closes gh-26 Closes gh-30 --- .../restdocs/curl/CurlDocumentation.java | 57 +++++++++++++++++-- .../restdocs/curl/CurlDocumentationTests.java | 33 +++++++++++ 2 files changed, 85 insertions(+), 5 deletions(-) diff --git a/spring-restdocs/src/main/java/org/springframework/restdocs/curl/CurlDocumentation.java b/spring-restdocs/src/main/java/org/springframework/restdocs/curl/CurlDocumentation.java index bb9a3ee2..cd738df7 100644 --- a/spring-restdocs/src/main/java/org/springframework/restdocs/curl/CurlDocumentation.java +++ b/spring-restdocs/src/main/java/org/springframework/restdocs/curl/CurlDocumentation.java @@ -20,6 +20,9 @@ import static org.springframework.restdocs.util.IterableEnumeration.iterable; import java.io.IOException; import java.io.StringWriter; +import java.io.UnsupportedEncodingException; +import java.net.URLEncoder; +import java.util.Map; import javax.servlet.http.HttpServletRequest; @@ -29,6 +32,7 @@ import org.springframework.restdocs.snippet.DocumentationWriter; import org.springframework.restdocs.snippet.DocumentationWriter.DocumentationAction; import org.springframework.test.web.servlet.MvcResult; import org.springframework.util.FileCopyUtils; +import org.springframework.util.StringUtils; import org.springframework.web.bind.annotation.RequestMethod; /** @@ -36,6 +40,7 @@ import org.springframework.web.bind.annotation.RequestMethod; * the cURL command-line utility. * * @author Andy Wilkinson + * @author Yann Le Guern */ public abstract class CurlDocumentation { @@ -141,9 +146,8 @@ public abstract class CurlDocumentation { this.writer.print(" -i"); } - RequestMethod requestMethod = RequestMethod.valueOf(request.getMethod()); - if (requestMethod != RequestMethod.GET) { - this.writer.print(String.format(" -X %s", requestMethod.toString())); + if (!isGetRequest(request)) { + this.writer.print(String.format(" -X %s", request.getMethod())); } for (String headerName : iterable(request.getHeaderNames())) { @@ -160,6 +164,10 @@ public abstract class CurlDocumentation { this.writer.println(); } + private boolean isGetRequest(HttpServletRequest request) { + return RequestMethod.GET == RequestMethod.valueOf(request.getMethod()); + } + private boolean isNonStandardPort(HttpServletRequest request) { return (SCHEME_HTTP.equals(request.getScheme()) && request.getRemotePort() != STANDARD_PORT_HTTP) || (SCHEME_HTTPS.equals(request.getScheme()) && request @@ -167,8 +175,47 @@ public abstract class CurlDocumentation { } private String getRequestUriWithQueryString(HttpServletRequest request) { - return request.getQueryString() != null ? request.getRequestURI() + "?" - + request.getQueryString() : request.getRequestURI(); + StringBuilder sb = new StringBuilder(); + sb.append(request.getRequestURI()); + String queryString = getQueryString(request); + if (StringUtils.hasText(queryString)) { + sb.append('?').append(queryString); + } + return sb.toString(); + } + + private String getQueryString(HttpServletRequest request) { + if (request.getQueryString() != null) { + return request.getQueryString(); + } + if (isGetRequest(request)) { + return toQueryString(request.getParameterMap()); + } + return null; + } + + private static String toQueryString(Map map) { + StringBuilder sb = new StringBuilder(); + for (Map.Entry entry : map.entrySet()) { + for (String value : entry.getValue()) { + if (sb.length() > 0) { + sb.append("&"); + } + sb.append(urlEncodeUTF8(entry.getKey())).append('=') + .append(urlEncodeUTF8(value)); + } + } + return sb.toString(); + } + + private static String urlEncodeUTF8(String s) { + try { + return URLEncoder.encode(s, "UTF-8"); + } + catch (UnsupportedEncodingException ex) { + throw new IllegalStateException("Unable to URL encode " + s + + " using UTF-8", ex); + } } private String getContent(MockHttpServletRequest request) throws IOException { diff --git a/spring-restdocs/src/test/java/org/springframework/restdocs/curl/CurlDocumentationTests.java b/spring-restdocs/src/test/java/org/springframework/restdocs/curl/CurlDocumentationTests.java index 8b590ec5..caaa90e6 100644 --- a/spring-restdocs/src/test/java/org/springframework/restdocs/curl/CurlDocumentationTests.java +++ b/spring-restdocs/src/test/java/org/springframework/restdocs/curl/CurlDocumentationTests.java @@ -44,6 +44,7 @@ import org.springframework.restdocs.StubMvcResult; * Tests for {@link CurlDocumentation} * * @author Andy Wilkinson + * @author Yann Le Guern */ public class CurlDocumentationTests { @@ -114,6 +115,38 @@ public class CurlDocumentationTests { hasItem("$ curl http://localhost/foo?param=value -i")); } + @Test + public void requestWithOneParameter() throws IOException { + MockHttpServletRequest request = new MockHttpServletRequest("GET", "/foo"); + request.addParameter("k1", "v1"); + documentCurlRequest("request-with-one-parameter").handle( + new StubMvcResult(request, null)); + assertThat(requestSnippetLines("request-with-one-parameter"), + hasItem("$ curl http://localhost/foo?k1=v1 -i")); + } + + @Test + public void requestWithMultipleParameters() throws IOException { + MockHttpServletRequest request = new MockHttpServletRequest("GET", "/foo"); + request.addParameter("k1", "v1"); + request.addParameter("k2", "v2"); + request.addParameter("k1", "v1-bis"); + documentCurlRequest("request-with-multiple-parameters").handle( + new StubMvcResult(request, null)); + assertThat(requestSnippetLines("request-with-multiple-parameters"), + hasItem("$ curl http://localhost/foo?k1=v1&k1=v1-bis&k2=v2 -i")); + } + + @Test + public void requestWithUrlEncodedParameter() throws IOException { + MockHttpServletRequest request = new MockHttpServletRequest("GET", "/foo"); + request.addParameter("k1", "foo bar&"); + documentCurlRequest("request-with-url-encoded-parameter").handle( + new StubMvcResult(request, null)); + assertThat(requestSnippetLines("request-with-url-encoded-parameter"), + hasItem("$ curl http://localhost/foo?k1=foo+bar%26 -i")); + } + @Test public void requestWithHeaders() throws IOException { MockHttpServletRequest request = new MockHttpServletRequest("GET", "/foo");