diff --git a/docs/build.gradle b/docs/build.gradle
index 68c54bcb..92d3a897 100644
--- a/docs/build.gradle
+++ b/docs/build.gradle
@@ -18,4 +18,5 @@ asciidoctor {
}
attributes 'revnumber': project.version,
'branch-or-tag': project.version.endsWith('SNAPSHOT') ? 'master': "v${project.version}"
+ inputs.files(sourceSets.test.java)
}
\ No newline at end of file
diff --git a/docs/src/docs/asciidoc/documenting-your-api.adoc b/docs/src/docs/asciidoc/documenting-your-api.adoc
index 3915fecb..8a526df7 100644
--- a/docs/src/docs/asciidoc/documenting-your-api.adoc
+++ b/docs/src/docs/asciidoc/documenting-your-api.adoc
@@ -196,6 +196,32 @@ is not found in the request.
+[[documenting-your-api-path-parameters]]
+=== Path parameters
+
+A request's path parameters can be documented using `withPathParameters`
+
+[source,java,indent=0]
+----
+include::{examples-dir}/com/example/PathParameters.java[tags=path-parameters]
+----
+<1> Build the request. Uses the static `get` method on `RestDocumentationRequestBuilders`.
+<2> Use `withPathParameters` to describe the path parameters.
+<3> Document a parameter named `longitude`. Uses the static `parameterWithName` method on
+`org.springframework.restdocs.request.RequestDocumentation`.
+<4> Document a parameter named `latitude`.
+
+The result is a snippet named `path-parameters.adoc` that contains a table describing
+the path parameters that are supported by the resource.
+
+When documenting path parameters, the test will fail if an undocumented path parameter
+is used in the request. Similarly, the test will also fail if a documented path parameter
+is not found in the request.
+
+TIP: To make the path parameters available for documentation, the request must be
+built using one of the methods on `RestDocumentationRequestBuilders` rather than
+`MockMvcRequestBuilders`.
+
[[documenting-your-api-default-snippets]]
=== Default snippets
@@ -286,8 +312,8 @@ override the template for the `curl-request.adoc` snippet, create a template nam
There are two ways to provide extra information for inclusion in a generated snippet:
-. Use the `attributes` method on a field, link or query parameter descriptor to add one or
- more attributes to an individual descriptor
+. Use the `attributes` method on a field, link or parameter descriptor to add one or more
+ attributes to an individual descriptor.
. Pass in some attributes when calling `withCurlRequest`, `withHttpRequest`,
`withHttpResponse`, etc on `RestDocumentationResultHandler`. Such attributes will be
associated with the snippet as a whole.
diff --git a/docs/src/test/java/com/example/Hypermedia.java b/docs/src/test/java/com/example/Hypermedia.java
index a9e0de17..09b8e2d2 100644
--- a/docs/src/test/java/com/example/Hypermedia.java
+++ b/docs/src/test/java/com/example/Hypermedia.java
@@ -17,7 +17,7 @@
package com.example;
import static org.springframework.restdocs.RestDocumentation.document;
-import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
+import static org.springframework.restdocs.RestDocumentationRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import static org.springframework.restdocs.hypermedia.HypermediaDocumentation.linkWithRel;
import static org.springframework.restdocs.hypermedia.LinkExtractors.halLinks;
diff --git a/docs/src/test/java/com/example/InvokeService.java b/docs/src/test/java/com/example/InvokeService.java
index 18fc8508..32fdaf65 100644
--- a/docs/src/test/java/com/example/InvokeService.java
+++ b/docs/src/test/java/com/example/InvokeService.java
@@ -17,7 +17,7 @@
package com.example;
import static org.springframework.restdocs.RestDocumentation.document;
-import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
+import static org.springframework.restdocs.RestDocumentationRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import org.springframework.http.MediaType;
diff --git a/docs/src/test/java/com/example/PathParameters.java b/docs/src/test/java/com/example/PathParameters.java
new file mode 100644
index 00000000..4260b6d7
--- /dev/null
+++ b/docs/src/test/java/com/example/PathParameters.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2014-2015 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;
+
+import static org.springframework.restdocs.RestDocumentation.document;
+import static org.springframework.restdocs.request.RequestDocumentation.parameterWithName;
+import static org.springframework.restdocs.RestDocumentationRequestBuilders.get;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
+
+import org.springframework.test.web.servlet.MockMvc;
+
+public class PathParameters {
+
+ private MockMvc mockMvc;
+
+ public void pathParameters() throws Exception {
+ // tag::path-parameters[]
+ this.mockMvc.perform(get("/locations/{latitude}/{longitude}", 51.5072, 0.1275)) // <1>
+ .andExpect(status().isOk())
+ .andDo(document("locations").withPathParameters( // <2>
+ parameterWithName("latitude").description("The location's latitude"), // <3>
+ parameterWithName("longitude").description("The location's longitude") // <4>
+ ));
+ // end::path-parameters[]
+ }
+
+}
diff --git a/docs/src/test/java/com/example/Payload.java b/docs/src/test/java/com/example/Payload.java
index 7dc57552..121dd114 100644
--- a/docs/src/test/java/com/example/Payload.java
+++ b/docs/src/test/java/com/example/Payload.java
@@ -20,8 +20,8 @@ import static org.springframework.restdocs.RestDocumentation.document;
import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath;
import static org.springframework.restdocs.snippet.Attributes.attributes;
import static org.springframework.restdocs.snippet.Attributes.key;
-import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
-import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
+import static org.springframework.restdocs.RestDocumentationRequestBuilders.get;
+import static org.springframework.restdocs.RestDocumentationRequestBuilders.post;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import org.springframework.http.MediaType;
diff --git a/docs/src/test/java/com/example/QueryParameters.java b/docs/src/test/java/com/example/QueryParameters.java
index ca81142c..f4af6037 100644
--- a/docs/src/test/java/com/example/QueryParameters.java
+++ b/docs/src/test/java/com/example/QueryParameters.java
@@ -18,7 +18,7 @@ package com.example;
import static org.springframework.restdocs.RestDocumentation.document;
import static org.springframework.restdocs.request.RequestDocumentation.parameterWithName;
-import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
+import static org.springframework.restdocs.RestDocumentationRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import org.springframework.test.web.servlet.MockMvc;
diff --git a/docs/src/test/java/com/example/ResponsePostProcessing.java b/docs/src/test/java/com/example/ResponsePostProcessing.java
index c9a6bcb0..a0c8d8ae 100644
--- a/docs/src/test/java/com/example/ResponsePostProcessing.java
+++ b/docs/src/test/java/com/example/ResponsePostProcessing.java
@@ -17,7 +17,7 @@
package com.example;
import static org.springframework.restdocs.RestDocumentation.modifyResponseTo;
-import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
+import static org.springframework.restdocs.RestDocumentationRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import org.springframework.test.web.servlet.MockMvc;
diff --git a/samples/rest-notes-spring-data-rest/src/test/java/com/example/notes/ApiDocumentation.java b/samples/rest-notes-spring-data-rest/src/test/java/com/example/notes/ApiDocumentation.java
index 80a762ad..5fa7364a 100644
--- a/samples/rest-notes-spring-data-rest/src/test/java/com/example/notes/ApiDocumentation.java
+++ b/samples/rest-notes-spring-data-rest/src/test/java/com/example/notes/ApiDocumentation.java
@@ -22,9 +22,9 @@ import static org.springframework.restdocs.RestDocumentation.documentationConfig
import static org.springframework.restdocs.RestDocumentation.document;
import static org.springframework.restdocs.hypermedia.HypermediaDocumentation.linkWithRel;
import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath;
-import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
-import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.patch;
-import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
+import static org.springframework.restdocs.RestDocumentationRequestBuilders.get;
+import static org.springframework.restdocs.RestDocumentationRequestBuilders.patch;
+import static org.springframework.restdocs.RestDocumentationRequestBuilders.post;
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
@@ -279,7 +279,7 @@ public class ApiDocumentation {
fieldWithPath("title").description("The title of the note").type(FieldType.STRING).optional(),
fieldWithPath("body").description("The body of the note").type(FieldType.STRING).optional(),
fieldWithPath("tags").description("An array of tag resource URIs").optional()));
-
+
}
@Test
diff --git a/samples/rest-notes-spring-data-rest/src/test/java/com/example/notes/GettingStartedDocumentation.java b/samples/rest-notes-spring-data-rest/src/test/java/com/example/notes/GettingStartedDocumentation.java
index aca7a580..a6afc59f 100644
--- a/samples/rest-notes-spring-data-rest/src/test/java/com/example/notes/GettingStartedDocumentation.java
+++ b/samples/rest-notes-spring-data-rest/src/test/java/com/example/notes/GettingStartedDocumentation.java
@@ -21,9 +21,9 @@ import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.notNullValue;
import static org.springframework.restdocs.RestDocumentation.document;
import static org.springframework.restdocs.RestDocumentation.documentationConfiguration;
-import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
-import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.patch;
-import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
+import static org.springframework.restdocs.RestDocumentationRequestBuilders.get;
+import static org.springframework.restdocs.RestDocumentationRequestBuilders.patch;
+import static org.springframework.restdocs.RestDocumentationRequestBuilders.post;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.header;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
@@ -155,7 +155,7 @@ public class GettingStartedDocumentation {
return noteLocation;
}
- void getTags(String noteTagsLocation) throws Exception {
+ void getTags(String noteTagsLocation) throws Exception {
this.mockMvc.perform(get(noteTagsLocation))
.andExpect(status().isOk())
.andExpect(jsonPath("_embedded.tags", hasSize(1)));
@@ -177,7 +177,7 @@ public class GettingStartedDocumentation {
.andReturn();
}
- void getTagsForExistingNote(String noteTagsLocation) throws Exception {
+ void getTagsForExistingNote(String noteTagsLocation) throws Exception {
this.mockMvc.perform(get(noteTagsLocation))
.andExpect(status().isOk())
.andExpect(jsonPath("_embedded.tags", hasSize(1)));
diff --git a/samples/rest-notes-spring-hateoas/src/test/java/com/example/notes/ApiDocumentation.java b/samples/rest-notes-spring-hateoas/src/test/java/com/example/notes/ApiDocumentation.java
index 4f397569..1901ea85 100644
--- a/samples/rest-notes-spring-hateoas/src/test/java/com/example/notes/ApiDocumentation.java
+++ b/samples/rest-notes-spring-hateoas/src/test/java/com/example/notes/ApiDocumentation.java
@@ -22,9 +22,9 @@ import static org.springframework.restdocs.RestDocumentation.document;
import static org.springframework.restdocs.RestDocumentation.documentationConfiguration;
import static org.springframework.restdocs.hypermedia.HypermediaDocumentation.linkWithRel;
import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath;
-import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
-import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.patch;
-import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
+import static org.springframework.restdocs.RestDocumentationRequestBuilders.get;
+import static org.springframework.restdocs.RestDocumentationRequestBuilders.patch;
+import static org.springframework.restdocs.RestDocumentationRequestBuilders.post;
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
diff --git a/samples/rest-notes-spring-hateoas/src/test/java/com/example/notes/GettingStartedDocumentation.java b/samples/rest-notes-spring-hateoas/src/test/java/com/example/notes/GettingStartedDocumentation.java
index 2ca0d48b..79b78051 100644
--- a/samples/rest-notes-spring-hateoas/src/test/java/com/example/notes/GettingStartedDocumentation.java
+++ b/samples/rest-notes-spring-hateoas/src/test/java/com/example/notes/GettingStartedDocumentation.java
@@ -21,9 +21,9 @@ import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.notNullValue;
import static org.springframework.restdocs.RestDocumentation.document;
import static org.springframework.restdocs.RestDocumentation.documentationConfiguration;
-import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
-import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.patch;
-import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
+import static org.springframework.restdocs.RestDocumentationRequestBuilders.get;
+import static org.springframework.restdocs.RestDocumentationRequestBuilders.patch;
+import static org.springframework.restdocs.RestDocumentationRequestBuilders.post;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.header;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
@@ -155,7 +155,7 @@ public class GettingStartedDocumentation {
return noteLocation;
}
- void getTags(String noteTagsLocation) throws Exception {
+ void getTags(String noteTagsLocation) throws Exception {
this.mockMvc.perform(get(noteTagsLocation))
.andExpect(status().isOk())
.andExpect(jsonPath("_embedded.tags", hasSize(1)));
@@ -177,7 +177,7 @@ public class GettingStartedDocumentation {
.andReturn();
}
- void getTagsForExistingNote(String noteTagsLocation) throws Exception {
+ void getTagsForExistingNote(String noteTagsLocation) throws Exception {
this.mockMvc.perform(get(noteTagsLocation))
.andExpect(status().isOk())
.andExpect(jsonPath("_embedded.tags", hasSize(1)));
diff --git a/spring-restdocs/src/main/java/org/springframework/restdocs/RestDocumentationRequestBuilders.java b/spring-restdocs/src/main/java/org/springframework/restdocs/RestDocumentationRequestBuilders.java
new file mode 100644
index 00000000..e702fdaf
--- /dev/null
+++ b/spring-restdocs/src/main/java/org/springframework/restdocs/RestDocumentationRequestBuilders.java
@@ -0,0 +1,265 @@
+/*
+ * Copyright 2014-2015 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 org.springframework.restdocs;
+
+import java.net.URI;
+
+import org.springframework.http.HttpMethod;
+import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;
+import org.springframework.test.web.servlet.request.MockMultipartHttpServletRequestBuilder;
+import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
+
+/**
+ * A drop-in replacement for {@link MockMvcRequestBuilders} that captures a request's URL
+ * template and makes it available for documentation. Required when
+ * {@link RestDocumentationResultHandler#withPathParameters(org.springframework.restdocs .request.ParameterDescriptor...)
+ * documenting path parameters} and recommended for general usage.
+ *
+ * @author Andy Wilkinson
+ * @see MockMvcRequestBuilders
+ * @see RestDocumentationResultHandler#withPathParameters(org.springframework.restdocs.request.ParameterDescriptor...)
+ * @see RestDocumentationResultHandler#withPathParameters(java.util.Map,
+ * org.springframework.restdocs.request.ParameterDescriptor...)
+ */
+public abstract class RestDocumentationRequestBuilders {
+
+ private static final String ATTRIBUTE_NAME_URL_TEMPLATE = "org.springframework.restdocs.urlTemplate";
+
+ private RestDocumentationRequestBuilders() {
+
+ }
+
+ /**
+ * Create a {@link MockHttpServletRequestBuilder} for a GET request. The url template
+ * will be captured and made available for documentation.
+ *
+ * @param urlTemplate a URL template; the resulting URL will be encoded
+ * @param urlVariables zero or more URL variables
+ * @return the builder for the GET request
+ */
+ public static MockHttpServletRequestBuilder get(String urlTemplate,
+ Object... urlVariables) {
+ return MockMvcRequestBuilders.get(urlTemplate, urlVariables).requestAttr(
+ ATTRIBUTE_NAME_URL_TEMPLATE, urlTemplate);
+ }
+
+ /**
+ * Create a {@link MockHttpServletRequestBuilder} for a GET request.
+ *
+ * @param uri the URL
+ * @return the builder for the GET request
+ */
+ public static MockHttpServletRequestBuilder get(URI uri) {
+ return MockMvcRequestBuilders.get(uri);
+ }
+
+ /**
+ * Create a {@link MockHttpServletRequestBuilder} for a POST request. The url template
+ * will be captured and made available for documentation.
+ *
+ * @param urlTemplate a URL template; the resulting URL will be encoded
+ * @param urlVariables zero or more URL variables
+ * @return the builder for the POST request
+ */
+ public static MockHttpServletRequestBuilder post(String urlTemplate,
+ Object... urlVariables) {
+ return MockMvcRequestBuilders.post(urlTemplate, urlVariables).requestAttr(
+ ATTRIBUTE_NAME_URL_TEMPLATE, urlTemplate);
+ }
+
+ /**
+ * Create a {@link MockHttpServletRequestBuilder} for a POST request.
+ *
+ * @param uri the URL
+ * @return the builder for the POST request
+ */
+ public static MockHttpServletRequestBuilder post(URI uri) {
+ return MockMvcRequestBuilders.post(uri);
+ }
+
+ /**
+ * Create a {@link MockHttpServletRequestBuilder} for a PUT request. The url template
+ * will be captured and made available for documentation.
+ *
+ * @param urlTemplate a URL template; the resulting URL will be encoded
+ * @param urlVariables zero or more URL variables
+ * @return the builder for the PUT request
+ */
+ public static MockHttpServletRequestBuilder put(String urlTemplate,
+ Object... urlVariables) {
+ return MockMvcRequestBuilders.put(urlTemplate, urlVariables).requestAttr(
+ ATTRIBUTE_NAME_URL_TEMPLATE, urlTemplate);
+ }
+
+ /**
+ * Create a {@link MockHttpServletRequestBuilder} for a PUT request.
+ *
+ * @param uri the URL
+ * @return the builder for the PUT request
+ */
+ public static MockHttpServletRequestBuilder put(URI uri) {
+ return MockMvcRequestBuilders.put(uri);
+ }
+
+ /**
+ * Create a {@link MockHttpServletRequestBuilder} for a PATCH request. The url
+ * template will be captured and made available for documentation.
+ *
+ * @param urlTemplate a URL template; the resulting URL will be encoded
+ * @param urlVariables zero or more URL variables
+ * @return the builder for the PATCH request
+ */
+ public static MockHttpServletRequestBuilder patch(String urlTemplate,
+ Object... urlVariables) {
+ return MockMvcRequestBuilders.patch(urlTemplate, urlVariables).requestAttr(
+ ATTRIBUTE_NAME_URL_TEMPLATE, urlTemplate);
+ }
+
+ /**
+ * Create a {@link MockHttpServletRequestBuilder} for a PATCH request.
+ *
+ * @param uri the URL
+ * @return the builder for the PATCH request
+ */
+ public static MockHttpServletRequestBuilder patch(URI uri) {
+ return MockMvcRequestBuilders.patch(uri);
+ }
+
+ /**
+ * Create a {@link MockHttpServletRequestBuilder} for a DELETE request. The url
+ * template will be captured and made available for documentation.
+ *
+ * @param urlTemplate a URL template; the resulting URL will be encoded
+ * @param urlVariables zero or more URL variables
+ * @return the builder for the DELETE request
+ */
+ public static MockHttpServletRequestBuilder delete(String urlTemplate,
+ Object... urlVariables) {
+ return MockMvcRequestBuilders.delete(urlTemplate, urlVariables).requestAttr(
+ ATTRIBUTE_NAME_URL_TEMPLATE, urlTemplate);
+ }
+
+ /**
+ * Create a {@link MockHttpServletRequestBuilder} for a DELETE request.
+ *
+ * @param uri the URL
+ * @return the builder for the DELETE request
+ */
+ public static MockHttpServletRequestBuilder delete(URI uri) {
+ return MockMvcRequestBuilders.delete(uri);
+ }
+
+ /**
+ * Create a {@link MockHttpServletRequestBuilder} for an OPTIONS request. The url
+ * template will be captured and made available for documentation.
+ *
+ * @param urlTemplate a URL template; the resulting URL will be encoded
+ * @param urlVariables zero or more URL variables
+ * @return the builder for the OPTIONS request
+ */
+ public static MockHttpServletRequestBuilder options(String urlTemplate,
+ Object... urlVariables) {
+ return MockMvcRequestBuilders.options(urlTemplate, urlVariables).requestAttr(
+ ATTRIBUTE_NAME_URL_TEMPLATE, urlTemplate);
+ }
+
+ /**
+ * Create a {@link MockHttpServletRequestBuilder} for an OPTIONS request.
+ *
+ * @param uri the URL
+ * @return the builder for the OPTIONS request
+ */
+ public static MockHttpServletRequestBuilder options(URI uri) {
+ return MockMvcRequestBuilders.options(uri);
+ }
+
+ /**
+ * Create a {@link MockHttpServletRequestBuilder} for a HEAD request. The url template
+ * will be captured and made available for documentation.
+ *
+ * @param urlTemplate a URL template; the resulting URL will be encoded
+ * @param urlVariables zero or more URL variables
+ * @return the builder for the HEAD request
+ */
+ public static MockHttpServletRequestBuilder head(String urlTemplate,
+ Object... urlVariables) {
+ return MockMvcRequestBuilders.head(urlTemplate, urlVariables).requestAttr(
+ ATTRIBUTE_NAME_URL_TEMPLATE, urlTemplate);
+ }
+
+ /**
+ * Create a {@link MockHttpServletRequestBuilder} for a HEAD request.
+ *
+ * @param uri the URL
+ * @return the builder for the HEAD request
+ */
+ public static MockHttpServletRequestBuilder head(URI uri) {
+ return MockMvcRequestBuilders.head(uri);
+ }
+
+ /**
+ * Create a {@link MockHttpServletRequestBuilder} for a request with the given HTTP
+ * method. The url template will be captured and made available for documentation.
+ *
+ * @param httpMethod the HTTP method
+ * @param urlTemplate a URL template; the resulting URL will be encoded
+ * @param urlVariables zero or more URL variables
+ * @return the builder for the request
+ */
+ public static MockHttpServletRequestBuilder request(HttpMethod httpMethod,
+ String urlTemplate, Object... urlVariables) {
+ return MockMvcRequestBuilders.request(httpMethod, urlTemplate, urlVariables)
+ .requestAttr(ATTRIBUTE_NAME_URL_TEMPLATE, urlTemplate);
+ }
+
+ /**
+ * Create a {@link MockHttpServletRequestBuilder} for a request with the given HTTP
+ * method.
+ * @param httpMethod the HTTP method (GET, POST, etc)
+ * @param uri the URL
+ * @return the builder for the request
+ */
+ public static MockHttpServletRequestBuilder request(HttpMethod httpMethod, URI uri) {
+ return MockMvcRequestBuilders.request(httpMethod, uri);
+ }
+
+ /**
+ * Create a {@link MockHttpServletRequestBuilder} for a multipart request. The url
+ * template will be captured and made available for documentation.
+ *
+ * @param urlTemplate a URL template; the resulting URL will be encoded
+ * @param urlVariables zero or more URL variables
+ * @return the builder for the file upload request
+ */
+ public static MockMultipartHttpServletRequestBuilder fileUpload(String urlTemplate,
+ Object... urlVariables) {
+ return (MockMultipartHttpServletRequestBuilder) MockMvcRequestBuilders
+ .fileUpload(urlTemplate, urlVariables).requestAttr(
+ ATTRIBUTE_NAME_URL_TEMPLATE, urlTemplate);
+ }
+
+ /**
+ * Create a {@link MockHttpServletRequestBuilder} for a multipart request.
+ *
+ * @param uri the URL
+ * @return the builder for the file upload request
+ */
+ public static MockMultipartHttpServletRequestBuilder fileUpload(URI uri) {
+ return MockMvcRequestBuilders.fileUpload(uri);
+ }
+
+}
diff --git a/spring-restdocs/src/main/java/org/springframework/restdocs/RestDocumentationResultHandler.java b/spring-restdocs/src/main/java/org/springframework/restdocs/RestDocumentationResultHandler.java
index 1d8a0445..a8134f87 100644
--- a/spring-restdocs/src/main/java/org/springframework/restdocs/RestDocumentationResultHandler.java
+++ b/spring-restdocs/src/main/java/org/springframework/restdocs/RestDocumentationResultHandler.java
@@ -22,6 +22,7 @@ import static org.springframework.restdocs.http.HttpDocumentation.documentHttpRe
import static org.springframework.restdocs.hypermedia.HypermediaDocumentation.documentLinks;
import static org.springframework.restdocs.payload.PayloadDocumentation.documentRequestFields;
import static org.springframework.restdocs.payload.PayloadDocumentation.documentResponseFields;
+import static org.springframework.restdocs.request.RequestDocumentation.documentPathParameters;
import static org.springframework.restdocs.request.RequestDocumentation.documentQueryParameters;
import java.util.ArrayList;
@@ -309,6 +310,45 @@ public class RestDocumentationResultHandler implements ResultHandler {
return this;
}
+ /**
+ * Documents the parameters in the request's path using the given {@code descriptors}.
+ *
+ * If a parameter is present in the path but is not described by one of the
+ * descriptors a failure will occur when this handler is invoked. Similarly, if a
+ * parameter is described but is not present in the request a failure will also occur
+ * when this handler is invoked.
+ *
+ * @param descriptors the parameter descriptors
+ * @return {@code this}
+ * @see RequestDocumentation#parameterWithName(String)
+ */
+ public RestDocumentationResultHandler withPathParameters(
+ ParameterDescriptor... descriptors) {
+ return this.withQueryParameters(null, descriptors);
+ }
+
+ /**
+ * Documents the parameters in the request's path using the given {@code descriptors}.
+ * The given {@code attributes} are made available during the generation of the path
+ * parameters snippet.
+ *
+ * If a parameter is present in the path but is not described by one of the
+ * descriptors a failure will occur when this handler is invoked. Similarly, if a
+ * parameter is described but is not present in the request a failure will also occur
+ * when this handler is invoked.
+ *
+ * @param descriptors the parameter descriptors
+ * @param attributes the attributes
+ * @return {@code this}
+ * @see RequestDocumentation#parameterWithName(String)
+ */
+ public RestDocumentationResultHandler withPathParameters(
+ Map attributes, ParameterDescriptor... descriptors) {
+ this.delegates.add(documentPathParameters(this.identifier, attributes,
+ descriptors));
+ return this;
+ }
+
@Override
public void handle(MvcResult result) throws Exception {
this.curlRequest.handle(result);
diff --git a/spring-restdocs/src/main/java/org/springframework/restdocs/request/AbstractParametersSnippetResultHandler.java b/spring-restdocs/src/main/java/org/springframework/restdocs/request/AbstractParametersSnippetResultHandler.java
new file mode 100644
index 00000000..cc4e630b
--- /dev/null
+++ b/spring-restdocs/src/main/java/org/springframework/restdocs/request/AbstractParametersSnippetResultHandler.java
@@ -0,0 +1,67 @@
+package org.springframework.restdocs.request;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+
+import org.springframework.restdocs.snippet.SnippetWritingResultHandler;
+import org.springframework.test.web.servlet.MvcResult;
+import org.springframework.util.Assert;
+
+public abstract class AbstractParametersSnippetResultHandler extends
+ SnippetWritingResultHandler {
+
+ private final Map descriptorsByName = new LinkedHashMap<>();
+
+ protected AbstractParametersSnippetResultHandler(String identifier,
+ String snippetName, Map attributes,
+ ParameterDescriptor... descriptors) {
+ super(identifier, snippetName, attributes);
+ for (ParameterDescriptor descriptor : descriptors) {
+ Assert.hasText(descriptor.getName());
+ Assert.hasText(descriptor.getDescription());
+ this.descriptorsByName.put(descriptor.getName(), descriptor);
+ }
+ }
+
+ @Override
+ protected Map doHandle(MvcResult result) throws IOException {
+ verifyParameterDescriptors(result);
+
+ Map model = new HashMap<>();
+ List