Files
spring-restdocs/docs/src/docs/asciidoc/documenting-your-api.adoc
2020-08-24 16:57:51 +01:00

1475 lines
51 KiB
Plaintext

[[documenting-your-api]]
== Documenting your API
This section provides more details about using Spring REST Docs to document your API.
[[documenting-your-api-hypermedia]]
=== Hypermedia
Spring REST Docs provides support for documenting the links in a
https://en.wikipedia.org/wiki/HATEOAS[hypermedia-based] API.
The following examples show how to use it:
====
[source,java,indent=0,role="primary"]
.MockMvc
----
include::{examples-dir}/com/example/mockmvc/Hypermedia.java[tag=links]
----
<1> Configure Spring REST docs to produce a snippet describing the response's links.
Uses the static `links` method on
`org.springframework.restdocs.hypermedia.HypermediaDocumentation`.
<2> Expect a link whose `rel` is `alpha`. Uses the static `linkWithRel` method on
`org.springframework.restdocs.hypermedia.HypermediaDocumentation`.
<3> Expect a link whose `rel` is `bravo`.
[source,java,indent=0,role="secondary"]
.WebTestClient
----
include::{examples-dir}/com/example/webtestclient/Hypermedia.java[tag=links]
----
<1> Configure Spring REST docs to produce a snippet describing the response's links.
Uses the static `links` method on
`org.springframework.restdocs.hypermedia.HypermediaDocumentation`.
<2> Expect a link whose `rel` is `alpha`. Uses the static `linkWithRel` method on
`org.springframework.restdocs.hypermedia.HypermediaDocumentation`.
<3> Expect a link whose `rel` is `bravo`.
[source,java,indent=0,role="secondary"]
.REST Assured
----
include::{examples-dir}/com/example/restassured/Hypermedia.java[tag=links]
----
<1> Configure Spring REST docs to produce a snippet describing the response's links.
Uses the static `links` method on
`org.springframework.restdocs.hypermedia.HypermediaDocumentation`.
<2> Expect a link whose `rel` is `alpha`. Uses the static `linkWithRel` method on
`org.springframework.restdocs.hypermedia.HypermediaDocumentation`.
<3> Expect a link whose `rel` is `bravo`.
====
The result is a snippet named `links.adoc` that contains a table describing the resource's
links.
TIP: If a link in the response has a `title`, you can omit the description from its
descriptor and the `title` is used. If you omit the description and the link does
not have a `title`, a failure occurs.
When documenting links, the test fails if an undocumented link is found in the
response. Similarly, the test also fails if a documented link is not found in the
response and the link has not been marked as optional.
If you do not want to document a link, you can mark it as ignored. Doing so prevents it
from appearing in the generated snippet while avoiding the failure described above.
You can also document links in a relaxed mode, where any undocumented links do not cause
a test failure. To do so, use the `relaxedLinks` method on
`org.springframework.restdocs.hypermedia.HypermediaDocumentation`. This can be useful when
documenting a particular scenario where you only want to focus on a subset of the links.
[[documenting-your-api-hypermedia-link-formats]]
==== Hypermedia Link Formats
Two link formats are understood by default:
* Atom: Links are expected to be in an array named `links`. This is used by default when
the content type of the response is compatible with `application/json`.
* HAL: Links are expected to be in a map named `_links`. This is used by default when the
content type of the response is compatible with `application/hal+json`.
If you use Atom- or HAL-format links but with a different content type, you can provide
one of the built-in `LinkExtractor` implementations to `links`. The following examples
show how to do so:
====
[source,java,indent=0,role="primary"]
.MockMvc
----
include::{examples-dir}/com/example/mockmvc/Hypermedia.java[tag=explicit-extractor]
----
<1> Indicate that the links are in HAL format. Uses the static `halLinks` method on
`org.springframework.restdocs.hypermedia.HypermediaDocumentation`.
[source,java,indent=0,role="secondary"]
.WebTestClient
----
include::{examples-dir}/com/example/webtestclient/Hypermedia.java[tag=explicit-extractor]
----
<1> Indicate that the links are in HAL format. Uses the static `halLinks` method on
`org.springframework.restdocs.hypermedia.HypermediaDocumentation`.
[source,java,indent=0,role="secondary"]
.REST Assured
----
include::{examples-dir}/com/example/restassured/Hypermedia.java[tag=explicit-extractor]
----
<1> Indicate that the links are in HAL format. Uses the static `halLinks` method on
`org.springframework.restdocs.hypermedia.HypermediaDocumentation`.
====
If your API represents its links in a format other than Atom or HAL, you can provide your
own implementation of the `LinkExtractor` interface to extract the links from the
response.
[[documenting-your-api-hypermedia-ignoring-common-links]]
==== Ignoring Common Links
Rather than documenting links that are common to every response, such as `self` and
`curies` when using HAL, you may want to document them once in an overview section and
then ignore them in the rest of your API's documentation. To do so, you can build on the
<<documenting-your-api-reusing-snippets,support for reusing snippets>> to add link
descriptors to a snippet that is preconfigured to ignore certain links. The following
example shows how to do so:
====
[source,java,indent=0]
----
include::{examples-dir}/com/example/Hypermedia.java[tags=ignore-links]
----
====
[[documenting-your-api-request-response-payloads]]
=== Request and Response Payloads
In addition to the hypermedia-specific support <<documenting-your-api-hypermedia,described
earlier>>, support for general documentation of request and response payloads is also
provided.
By default, Spring REST Docs automatically generates snippets for the body of the request
and the body of the response. These snippets are named `request-body.adoc` and
`response-body.adoc` respectively.
[[documenting-your-api-request-response-payloads-fields]]
==== Request and Response Fields
To provide more detailed documentation of a request or response payload, support for
documenting the payload's fields is provided.
Consider the following payload:
====
[source,json,indent=0]
----
{
"contact": {
"name": "Jane Doe",
"email": "jane.doe@example.com"
}
}
----
====
You can document the previous example's fields as follows:
====
[source,java,indent=0,role="primary"]
.MockMvc
----
include::{examples-dir}/com/example/mockmvc/Payload.java[tags=response]
----
<1> Configure Spring REST docs to produce a snippet describing the fields in the response
payload. To document a request, you can use `requestFields`. Both are static methods
on `org.springframework.restdocs.payload.PayloadDocumentation`.
<2> Expect a field with the path `contact.email`. Uses the static `fieldWithPath` method
on `org.springframework.restdocs.payload.PayloadDocumentation`.
<3> Expect a field with the path `contact.name`.
[source,java,indent=0,role="secondary"]
.WebTestClient
----
include::{examples-dir}/com/example/webtestclient/Payload.java[tags=response]
----
<1> Configure Spring REST docs to produce a snippet describing the fields in the response
payload. To document a request, you can use `requestFields`. Both are static methods
on `org.springframework.restdocs.payload.PayloadDocumentation`.
<2> Expect a field with the path `contact.email`. Uses the static `fieldWithPath` method
on `org.springframework.restdocs.payload.PayloadDocumentation`.
<3> Expect a field with the path `contact.name`.
[source,java,indent=0,role="secondary"]
.REST Assured
----
include::{examples-dir}/com/example/restassured/Payload.java[tags=response]
----
<1> Configure Spring REST docs to produce a snippet describing the fields in the response
payload. To document a request, you can use `requestFields`. Both are static methods
on `org.springframework.restdocs.payload.PayloadDocumentation`.
<2> Expect a field with the path `contact.email`. Uses the static `fieldWithPath` method
on `org.springframework.restdocs.payload.PayloadDocumentation`.
<3> Expect a field with the path `contact.name`.
====
The result is a snippet that contains a table describing the fields. For requests, this
snippet is named `request-fields.adoc`. For responses, this snippet is named
`response-fields.adoc`.
When documenting fields, the test fails if an undocumented field is found in the payload.
Similarly, the test also fails if a documented field is not found in the payload and the
field has not been marked as optional.
If you do not want to provide detailed documentation for all of the fields, an entire
subsection of a payload can be documented. The following examples show how to do so:
====
[source,java,indent=0,role="primary"]
.MockMvc
----
include::{examples-dir}/com/example/mockmvc/Payload.java[tags=subsection]
----
<1> Document the subsection with the path `contact`. `contact.email` and `contact.name`
are now seen as having also been documented. Uses the static `subsectionWithPath`
method on `org.springframework.restdocs.payload.PayloadDocumentation`.
[source,java,indent=0,role="secondary"]
.WebTestClient
----
include::{examples-dir}/com/example/webtestclient/Payload.java[tags=subsection]
----
<1> Document the subsection with the path `contact`. `contact.email` and `contact.name`
are now seen as having also been documented. Uses the static `subsectionWithPath`
method on `org.springframework.restdocs.payload.PayloadDocumentation`.
[source,java,indent=0,role="secondary"]
.REST Assured
----
include::{examples-dir}/com/example/restassured/Payload.java[tags=subsection]
----
<1> Document the subsection with the path `contact`. `contact.email` and `contact.name`
are now seen as having also been documented. Uses the static `subsectionWithPath`
method on `org.springframework.restdocs.payload.PayloadDocumentation`.
====
`subsectionWithPath` can be useful for providing a high-level overview of a particular
section of a payload. You can then produce separate, more detailed documentation for a
subsection. See <<documenting-your-api-request-response-payloads-subsections>>.
If you do not want to document a field or subsection at all, you can mark it as ignored.
This prevents it from appearing in the generated snippet while avoiding the failure
described earlier.
You can also document fields in a relaxed mode, where any undocumented fields do not
cause a test failure. To do so, use the `relaxedRequestFields` and `relaxedResponseFields`
methods on
`org.springframework.restdocs.payload.PayloadDocumentation`. This can be useful when
documenting a particular scenario where you want to focus only on a subset of the payload.
TIP: By default, Spring REST Docs assumes that the payload you are documenting is JSON.
If you want to document an XML payload, the content type of the request or response must
be compatible with `application/xml`.
[[documenting-your-api-request-response-payloads-fields-json]]
===== Fields in JSON Payloads
This section describes how to work with fields in JSON payloads.
[[documenting-your-api-request-response-payloads-fields-json-field-paths]]
====== JSON Field Paths
JSON field paths use either dot notation or bracket notation. Dot notation uses '.' to
separate each key in the path (for example, `a.b`). Bracket notation wraps each key in
square brackets and single quotation marks (for example, `['a']['b']`). In either case,
`[]` is used to identify an array. Dot notation is more concise, but using bracket
notation enables the use of `.` within a key name (for example, `['a.b']`). The two
different notations can be used in the same path (for example, `a['b']`).
Consider the following JSON payload:
====
[source,json,indent=0]
----
{
"a":{
"b":[
{
"c":"one"
},
{
"c":"two"
},
{
"d":"three"
}
],
"e.dot" : "four"
}
}
----
====
In the preceding JSON payload, the following paths are all present:
[cols="1,3"]
|===
|Path | Value
|`a`
|An object containing `b`
|`a.b`
|An array containing three objects
|`['a']['b']`
|An array containing three objects
|`a['b']`
|An array containing three objects
|`['a'].b`
|An array containing three objects
|`a.b[]`
|An array containing three objects
|`a.b[].c`
|An array containing the strings `one` and `two`
|`a.b[].d`
|The string `three`
|`a['e.dot']`
|The string `four`
|`['a']['e.dot']`
|The string `four`
|===
You can also document a payload that uses an array at its root. The path `[]` refers
to the entire array. You can then use bracket or dot notation to identify fields within
the array's entries. For example, `[].id` corresponds to the `id` field of every object
found in the following array:
====
[source,json,indent=0]
----
[
{
"id":1
},
{
"id":2
}
]
----
====
You can use `\*` as a wildcard to match fields with different names. For example,
`users.*.role` could be used to document the role of every user in the following JSON:
====
[source,json,indent=0]
----
{
"users":{
"ab12cd34":{
"role": "Administrator"
},
"12ab34cd":{
"role": "Guest"
}
}
}
----
====
[[documenting-your-api-request-response-payloads-fields-json-field-types]]
====== JSON Field Types
When a field is documented, Spring REST Docs tries to determine its type by examining the
payload. Seven different types are supported:
[cols="1,3"]
|===
| Type | Description
| `array`
| The value of each occurrence of the field is an array.
| `boolean`
| The value of each occurrence of the field is a boolean (`true` or `false`).
| `object`
| The value of each occurrence of the field is an object.
| `number`
| The value of each occurrence of the field is a number.
| `null`
| The value of each occurrence of the field is `null`.
| `string`
| The value of each occurrence of the field is a string.
| `varies`
| The field occurs multiple times in the payload with a variety of different types.
|===
You can also explicitly set the type by using the `type(Object)` method on
`FieldDescriptor`. The result of the `toString` method of the supplied `Object` is used
in the documentation. Typically, one of the values enumerated by `JsonFieldType` is used.
The following examples show how to do so:
====
[source,java,indent=0,role="primary"]
.MockMvc
----
include::{examples-dir}/com/example/mockmvc/Payload.java[tags=explicit-type]
----
<1> Set the field's type to `String`.
[source,java,indent=0,role="secondary"]
.WebTestClient
----
include::{examples-dir}/com/example/webtestclient/Payload.java[tags=explicit-type]
----
<1> Set the field's type to `String`.
[source,java,indent=0,role="secondary"]
.REST Assured
----
include::{examples-dir}/com/example/restassured/Payload.java[tags=explicit-type]
----
<1> Set the field's type to `String`.
====
[[documenting-your-api-request-response-payloads-fields-xml]]
===== XML payloads
This section describes how to work with XML payloads.
[[documenting-your-api-request-response-payloads-fields-xml-field-paths]]
====== XML Field Paths
XML field paths are described using XPath. `/` is used to descend into a child node.
[[documenting-your-api-request-response-payloads-fields-xml-field-types]]
====== XML Field Types
When documenting an XML payload, you must provide a type for the field by using the
`type(Object)` method on `FieldDescriptor`. The result of the supplied type's `toString`
method is used in the documentation.
[[documenting-your-api-request-response-payloads-fields-reusing-field-descriptors]]
===== Reusing Field Descriptors
In addition to the general support for <<documenting-your-api-reusing-snippets,reusing
snippets>>, the request and response snippets let additional descriptors be configured
with a path prefix. This lets the descriptors for a repeated portion of a request or
response payload be created once and then reused.
Consider an endpoint that returns a book:
====
[source,json,indent=0]
----
{
"title": "Pride and Prejudice",
"author": "Jane Austen"
}
----
====
The paths for `title` and `author` are `title` and `author`, respectively.
Now consider an endpoint that returns an array of books:
====
[source,json,indent=0]
----
[{
"title": "Pride and Prejudice",
"author": "Jane Austen"
},
{
"title": "To Kill a Mockingbird",
"author": "Harper Lee"
}]
----
====
The paths for `title` and `author` are `[].title` and `[].author`, respectively. The only
difference between the single book and the array of books is that the fields' paths now
have a `[].` prefix.
You can create the descriptors that document a book as follows:
====
[source,java,indent=0]
----
include::{examples-dir}/com/example/Payload.java[tags=book-descriptors]
----
====
You can then use them to document a single book, as follows:
====
[source,java,indent=0,role="primary"]
.MockMvc
----
include::{examples-dir}/com/example/mockmvc/Payload.java[tags=single-book]
----
<1> Document `title` and `author` by using existing descriptors
[source,java,indent=0,role="secondary"]
.WebTestClient
----
include::{examples-dir}/com/example/webtestclient/Payload.java[tags=single-book]
----
<1> Document `title` and `author` by using existing descriptors
[source,java,indent=0,role="secondary"]
.REST Assured
----
include::{examples-dir}/com/example/restassured/Payload.java[tags=single-book]
----
<1> Document `title` and `author` by using existing descriptors
====
You can also use the descriptors to document an array of books, as follows:
====
[source,java,indent=0,role="primary"]
.MockMvc
----
include::{examples-dir}/com/example/mockmvc/Payload.java[tags=book-array]
----
<1> Document the array.
<2> Document `[].title` and `[].author` by using the existing descriptors prefixed with
`[].`
[source,java,indent=0,role="secondary"]
.WebTestClient
----
include::{examples-dir}/com/example/webtestclient/Payload.java[tags=book-array]
----
<1> Document the array.
<2> Document `[].title` and `[].author` by using the existing descriptors prefixed with
`[].`
[source,java,indent=0,role="secondary"]
.REST Assured
----
include::{examples-dir}/com/example/restassured/Payload.java[tags=book-array]
----
<1> Document the array.
<2> Document `[].title` and `[].author` by using the existing descriptors prefixed with
`[].`
====
[[documenting-your-api-request-response-payloads-subsections]]
==== Documenting a Subsection of a Request or Response Payload
If a payload is large or structurally complex, it can be useful to document individual
sections of the payload. REST Docs let you do so by extracting a subsection of the
payload and then documenting it.
[[documenting-your-api-request-response-payloads-subsections-body]]
===== Documenting a Subsection of a Request or Response Body
Consider the following JSON response body:
====
[source,json,indent=0]
----
{
"weather": {
"wind": {
"speed": 15.3,
"direction": 287.0
},
"temperature": {
"high": 21.2,
"low": 14.8
}
}
}
----
====
You can produce a snippet that documents the `temperature` object as follows:
====
[source,java,indent=0,role="primary"]
.MockMvc
----
include::{examples-dir}/com/example/mockmvc/Payload.java[tags=body-subsection]
----
<1> Produce a snippet containing a subsection of the response body. Uses the static
`responseBody` and `beneathPath` methods on
`org.springframework.restdocs.payload.PayloadDocumentation`. To produce a snippet for
the request body, you can use `requestBody` in place of `responseBody`.
[source,java,indent=0,role="secondary"]
.WebTestClient
----
include::{examples-dir}/com/example/webtestclient/Payload.java[tags=body-subsection]
----
<1> Produce a snippet containing a subsection of the response body. Uses the static
`responseBody` and `beneathPath` methods on
`org.springframework.restdocs.payload.PayloadDocumentation`. To produce a snippet for
the request body, you can use `requestBody` in place of `responseBody`.
[source,java,indent=0,role="secondary"]
.REST Assured
----
include::{examples-dir}/com/example/restassured/Payload.java[tags=body-subsection]
----
<1> Produce a snippet containing a subsection of the response body. Uses the static
`responseBody` and `beneathPath` methods on
`org.springframework.restdocs.payload.PayloadDocumentation`. To produce a snippet for
the request body, you can use `requestBody` in place of `responseBody`.
====
The result is a snippet with the following contents:
====
[source,json,indent=0]
----
{
"temperature": {
"high": 21.2,
"low": 14.8
}
}
----
====
To make the snippet's name distinct, an identifier for the subsection is included. By
default, this identifier is `beneath-${path}`. For example, the preceding code results in
a snippet named `response-body-beneath-weather.temperature.adoc`. You can customized the
identifier by using the `withSubsectionId(String)` method, as follows:
====
[source,java,indent=0]
----
include::{examples-dir}/com/example/Payload.java[tags=custom-subsection-id]
----
====
The result is a snippet named `request-body-temp.adoc`.
[[documenting-your-api-request-response-payloads-subsections-fields]]
===== Documenting the Fields of a Subsection of a Request or Response
As well as documenting a subsection of a request or response body, you can also document
the fields in a particular subsection. You can produce a snippet that documents the
fields of the `temperature` object (`high` and `low`) as follows:
====
[source,java,indent=0,role="primary"]
.MockMvc
----
include::{examples-dir}/com/example/mockmvc/Payload.java[tags=fields-subsection]
----
<1> Produce a snippet describing the fields in the subsection of the response payload
beneath the path `weather.temperature`. Uses the static `beneathPath` method on
`org.springframework.restdocs.payload.PayloadDocumentation`.
<2> Document the `high` and `low` fields.
[source,java,indent=0,role="secondary"]
.WebTestClient
----
include::{examples-dir}/com/example/webtestclient/Payload.java[tags=fields-subsection]
----
<1> Produce a snippet describing the fields in the subsection of the response payload
beneath the path `weather.temperature`. Uses the static `beneathPath` method on
`org.springframework.restdocs.payload.PayloadDocumentation`.
<2> Document the `high` and `low` fields.
[source,java,indent=0,role="secondary"]
.REST Assured
----
include::{examples-dir}/com/example/restassured/Payload.java[tags=fields-subsection]
----
<1> Produce a snippet describing the fields in the subsection of the response payload
beneath the path `weather.temperature`. Uses the static `beneathPath` method on
`org.springframework.restdocs.payload.PayloadDocumentation`.
<2> Document the `high` and `low` fields.
====
The result is a snippet that contains a table describing the `high` and `low` fields of
`weather.temperature`. To make the snippet's name distinct, an identifier for the
subsection is included. By default, this identifier is `beneath-${path}`. For example,
the preceding code results in a snippet named
`response-fields-beneath-weather.temperature.adoc`.
[[documenting-your-api-request-parameters]]
=== Request Parameters
You can document a request's parameters by using `requestParameters`. You can include
request parameters in a `GET` request's query string. The following examples show how to
do so:
====
[source,java,indent=0,role="primary"]
.MockMvc
----
include::{examples-dir}/com/example/mockmvc/RequestParameters.java[tags=request-parameters-query-string]
----
<1> Perform a `GET` request with two parameters, `page` and `per_page`, in the query
string.
<2> Configure Spring REST Docs to produce a snippet describing the request's parameters.
Uses the static `requestParameters` method on
`org.springframework.restdocs.request.RequestDocumentation`.
<3> Document the `page` parameter. Uses the static `parameterWithName` method on
`org.springframework.restdocs.request.RequestDocumentation`.
<4> Document the `per_page` parameter.
[source,java,indent=0,role="secondary"]
.WebTestClient
----
include::{examples-dir}/com/example/webtestclient/RequestParameters.java[tags=request-parameters-query-string]
----
<1> Perform a `GET` request with two parameters, `page` and `per_page`, in the query
string.
<2> Configure Spring REST Docs to produce a snippet describing the request's parameters.
Uses the static `requestParameters` method on
`org.springframework.restdocs.request.RequestDocumentation`.
<3> Document the `page` parameter. Uses the static `parameterWithName` method on
`org.springframework.restdocs.request.RequestDocumentation`.
<4> Document the `per_page` parameter.
[source,java,indent=0,role="secondary"]
.REST Assured
----
include::{examples-dir}/com/example/restassured/RequestParameters.java[tags=request-parameters-query-string]
----
<1> Configure Spring REST Docs to produce a snippet describing the request's parameters.
Uses the static `requestParameters` method on
`org.springframework.restdocs.request.RequestDocumentation`.
<2> Document the `page` parameter. Uses the static `parameterWithName` method on
`org.springframework.restdocs.request.RequestDocumentation`.
<3> Document the `per_page` parameter.
<4> Perform a `GET` request with two parameters, `page` and `per_page`, in the query
string.
====
You can also include request parameters as form data in the body of a POST request. The
following examples show how to do so:
====
[source,java,indent=0,role="primary"]
.MockMvc
----
include::{examples-dir}/com/example/mockmvc/RequestParameters.java[tags=request-parameters-form-data]
----
<1> Perform a `POST` request with a single parameter, `username`.
[source,java,indent=0,role="secondary"]
.WebTestClient
----
include::{examples-dir}/com/example/webtestclient/RequestParameters.java[tags=request-parameters-form-data]
----
<1> Perform a `POST` request with a single parameter, `username`.
[source,java,indent=0,role="secondary"]
.REST Assured
----
include::{examples-dir}/com/example/restassured/RequestParameters.java[tags=request-parameters-form-data]
----
<1> Configure the `username` parameter.
<2> Perform the `POST` request.
====
In all cases, the result is a snippet named `request-parameters.adoc` that contains a
table describing the parameters that are supported by the resource.
When documenting request parameters, the test fails if an undocumented request parameter
is used in the request. Similarly, the test also fails if a documented request parameter
is not found in the request and the request parameter has not been marked as optional.
If you do not want to document a request parameter, you can mark it as ignored. This
prevents it from appearing in the generated snippet while avoiding the failure described
above.
You can also document request parameters in a relaxed mode where any undocumented
parameters do not cause a test failure. To do so, use the `relaxedRequestParameters`
method on `org.springframework.restdocs.request.RequestDocumentation`. This can be useful
when documenting a particular scenario where you only want to focus on a subset of the
request parameters.
[[documenting-your-api-path-parameters]]
=== Path Parameters
You can document a request's path parameters by using `pathParameters`. The following
examples show how to do so:
====
[source,java,indent=0,role="primary"]
.MockMvc
----
include::{examples-dir}/com/example/mockmvc/PathParameters.java[tags=path-parameters]
----
<1> Perform a `GET` request with two path parameters, `latitude` and `longitude`.
<2> Configure Spring REST Docs to produce a snippet describing the request's path
parameters. Uses the static `pathParameters` method on
`org.springframework.restdocs.request.RequestDocumentation`.
<3> Document the parameter named `latitude`. Uses the static `parameterWithName` method on
`org.springframework.restdocs.request.RequestDocumentation`.
<4> Document the parameter named `longitude`.
[source,java,indent=0,role="secondary"]
.WebTestClient
----
include::{examples-dir}/com/example/webtestclient/PathParameters.java[tags=path-parameters]
----
<1> Perform a `GET` request with two path parameters, `latitude` and `longitude`.
<2> Configure Spring REST Docs to produce a snippet describing the request's path
parameters. Uses the static `pathParameters` method on
`org.springframework.restdocs.request.RequestDocumentation`.
<3> Document the parameter named `latitude`. Uses the static `parameterWithName` method on
`org.springframework.restdocs.request.RequestDocumentation`.
<4> Document the parameter named `longitude`.
[source,java,indent=0,role="secondary"]
.REST Assured
----
include::{examples-dir}/com/example/restassured/PathParameters.java[tags=path-parameters]
----
<1> Configure Spring REST Docs to produce a snippet describing the request's path
parameters. Uses the static `pathParameters` method on
`org.springframework.restdocs.request.RequestDocumentation`.
<2> Document the parameter named `latitude`. Uses the static `parameterWithName` method on
`org.springframework.restdocs.request.RequestDocumentation`.
<3> Document the parameter named `longitude`.
<4> Perform a `GET` request with two path parameters, `latitude` and `longitude`.
====
The result is a snippet named `path-parameters.adoc` that contains a table describing
the path parameters that are supported by the resource.
TIP: If you use MockMvc, to make the path parameters available for documentation,
you must build the request by using one of the methods on
`RestDocumentationRequestBuilders` rather than `MockMvcRequestBuilders`.
When documenting path parameters, the test fails if an undocumented path parameter is
used in the request. Similarly, the test also fails if a documented path parameter is not
found in the request and the path parameter has not been marked as optional.
You can also document path parameters in a relaxed mode, where any undocumented
parameters do not cause a test failure. To do so, use the `relaxedPathParameters` method
on `org.springframework.restdocs.request.RequestDocumentation`. This can be useful when
documenting a particular scenario where you only want to focus on a subset of the path
parameters.
If you do not want to document a path parameter, you can mark it as ignored. Doing so
prevents it from appearing in the generated snippet while avoiding the failure described
earlier.
[[documenting-your-api-request-parts]]
=== Request Parts
You can use `requestParts` to document the parts of a multipart request. The following
example shows how to do so:
====
[source,java,indent=0,role="primary"]
.MockMvc
----
include::{examples-dir}/com/example/mockmvc/RequestParts.java[tags=request-parts]
----
<1> Perform a `POST` request with a single part named `file`.
<2> Configure Spring REST Docs to produce a snippet describing the request's parts. Uses
the static `requestParts` method on
`org.springframework.restdocs.request.RequestDocumentation`.
<3> Document the part named `file`. Uses the static `partWithName` method on
`org.springframework.restdocs.request.RequestDocumentation`.
[source,java,indent=0,role="secondary"]
.WebTestClient
----
include::{examples-dir}/com/example/webtestclient/RequestParts.java[tags=request-parts]
----
<1> Perform a `POST` request with a single part named `file`.
<2> Configure Spring REST Docs to produce a snippet describing the request's parts. Uses
the static `requestParts` method on
`org.springframework.restdocs.request.RequestDocumentation`.
<3> Document the part named `file`. Uses the static `partWithName` method on
`org.springframework.restdocs.request.RequestDocumentation`.
[source,java,indent=0,role="secondary"]
.REST Assured
----
include::{examples-dir}/com/example/restassured/RequestParts.java[tags=request-parts]
----
<1> Configure Spring REST Docs to produce a snippet describing the request's parts. Uses
the static `requestParts` method on
`org.springframework.restdocs.request.RequestDocumentation`.
<2> Document the part named `file`. Uses the static `partWithName` method on
`org.springframework.restdocs.request.RequestDocumentation`.
<3> Configure the request with the part named `file`.
<4> Perform the `POST` request to `/upload`.
====
The result is a snippet named `request-parts.adoc` that contains a table describing the
request parts that are supported by the resource.
When documenting request parts, the test fails if an undocumented part is used in the
request. Similarly, the test also fails if a documented part is not found in the request
and the part has not been marked as optional.
You can also document request parts in a relaxed mode where any undocumented parts do not
cause a test failure. To do so, use the `relaxedRequestParts` method on
`org.springframework.restdocs.request.RequestDocumentation`. This can be useful
when documenting a particular scenario where you only want to focus on a subset of the
request parts.
If you do not want to document a request part, you can mark it as ignored. This prevents
it from appearing in the generated snippet while avoiding the failure described earlier.
[[documenting-your-api-request-parts-payloads]]
=== Request Part Payloads
You can document the payload of a request part in much the same way as the
<<documenting-your-api-request-response-payloads,payload of a request>>, with support
for documenting a request part's body and its fields.
[[documenting-your-api-request-parts-payloads-body]]
==== Documenting a Request Part's Body
You can generate a snippet containing the body of a request part as follows:
====
[source,java,indent=0,role="primary"]
.MockMvc
----
include::{examples-dir}/com/example/mockmvc/RequestPartPayload.java[tags=body]
----
<1> Configure Spring REST docs to produce a snippet containing the body of the request
part named `metadata`. Uses the static `requestPartBody` method on
`PayloadDocumentation`.
[source,java,indent=0,role="secondary"]
.WebTestClient
----
include::{examples-dir}/com/example/webtestclient/RequestPartPayload.java[tags=body]
----
<1> Configure Spring REST docs to produce a snippet containing the body of the request
part named `metadata`. Uses the static `requestPartBody` method on
`PayloadDocumentation`.
[source,java,indent=0,role="secondary"]
.REST Assured
----
include::{examples-dir}/com/example/restassured/RequestPartPayload.java[tags=body]
----
<1> Configure Spring REST docs to produce a snippet containing the body of the request
part named `metadata`. Uses the static `requestPartBody` method on
`PayloadDocumentation`.
====
The result is a snippet named `request-part-${part-name}-body.adoc` that contains the
part's body. For example, documenting a part named `metadata` produces a snippet named
`request-part-metadata-body.adoc`.
[[documenting-your-api-request-parts-payloads-fields]]
==== Documenting a Request Part's Fields
You can document a request part's fields in much the same way as the fields of a request
or response, as follows:
====
[source,java,indent=0,role="primary"]
.MockMvc
----
include::{examples-dir}/com/example/mockmvc/RequestPartPayload.java[tags=fields]
----
<1> Configure Spring REST docs to produce a snippet describing the fields in the payload
of the request part named `metadata`. Uses the static `requestPartFields` method on
`PayloadDocumentation`.
<2> Expect a field with the path `version`. Uses the static `fieldWithPath` method on
`org.springframework.restdocs.payload.PayloadDocumentation`.
[source,java,indent=0,role="secondary"]
.WebTestClient
----
include::{examples-dir}/com/example/webtestclient/RequestPartPayload.java[tags=fields]
----
<1> Configure Spring REST docs to produce a snippet describing the fields in the payload
of the request part named `metadata`. Uses the static `requestPartFields` method on
`PayloadDocumentation`.
<2> Expect a field with the path `version`. Uses the static `fieldWithPath` method on
`org.springframework.restdocs.payload.PayloadDocumentation`.
[source,java,indent=0,role="secondary"]
.REST Assured
----
include::{examples-dir}/com/example/restassured/RequestPartPayload.java[tags=fields]
----
<1> Configure Spring REST docs to produce a snippet describing the fields in the payload
of the request part named `metadata`. Uses the static `requestPartFields` method on
`PayloadDocumentation`.
<2> Expect a field with the path `version`. Uses the static `fieldWithPath` method on
`org.springframework.restdocs.payload.PayloadDocumentation`.
====
The result is a snippet that contains a table describing the part's fields. This snippet
is named `request-part-${part-name}-fields.adoc`. For example, documenting a part named
`metadata` produces a snippet named `request-part-metadata-fields.adoc`.
When documenting fields, the test fails if an undocumented field is found in the payload
of the part. Similarly, the test also fails if a documented field is not found in the
payload of the part and the field has not been marked as optional. For payloads with a
hierarchical structure, documenting a field is sufficient for all of its descendants to
also be treated as having been documented.
If you do not want to document a field, you can mark it as ignored. Doing so prevents it
from appearing in the generated snippet while avoiding the failure described above.
You can also document fields in a relaxed mode, where any undocumented fields do not
cause a test failure. To do so, use the `relaxedRequestPartFields` method on
`org.springframework.restdocs.payload.PayloadDocumentation`. This can be useful when
documenting a particular scenario where you only want to focus on a subset of the payload
of the part.
For further information on describing fields, documenting payloads that use XML, and
more, see the <<documenting-your-api-request-response-payloads,section on documenting
request and response payloads>>.
[[documenting-your-api-http-headers]]
=== HTTP Headers
You can document the headers in a request or response by using `requestHeaders` and
`responseHeaders`, respectively. The following examples show how to do so:
====
[source,java,indent=0,role="primary"]
.MockMvc
----
include::{examples-dir}/com/example/mockmvc/HttpHeaders.java[tags=headers]
----
<1> Perform a `GET` request with an `Authorization` header that uses basic authentication.
<2> Configure Spring REST Docs to produce a snippet describing the request's headers.
Uses the static `requestHeaders` method on
`org.springframework.restdocs.headers.HeaderDocumentation`.
<3> Document the `Authorization` header. Uses the static `headerWithName` method on
`org.springframework.restdocs.headers.HeaderDocumentation`.
<4> Produce a snippet describing the response's headers. Uses the static `responseHeaders`
method on `org.springframework.restdocs.headers.HeaderDocumentation`.
[source,java,indent=0,role="secondary"]
.WebTestClient
----
include::{examples-dir}/com/example/webtestclient/HttpHeaders.java[tags=headers]
----
<1> Perform a `GET` request with an `Authorization` header that uses basic authentication.
<2> Configure Spring REST Docs to produce a snippet describing the request's headers.
Uses the static `requestHeaders` method on
`org.springframework.restdocs.headers.HeaderDocumentation`.
<3> Document the `Authorization` header. Uses the static `headerWithName` method on
`org.springframework.restdocs.headers.HeaderDocumentation`.
<4> Produce a snippet describing the response's headers. Uses the static `responseHeaders`
method on `org.springframework.restdocs.headers.HeaderDocumentation`.
[source,java,indent=0,role="secondary"]
.REST Assured
----
include::{examples-dir}/com/example/restassured/HttpHeaders.java[tags=headers]
----
<1> Configure Spring REST Docs to produce a snippet describing the request's headers.
Uses the static `requestHeaders` method on
`org.springframework.restdocs.headers.HeaderDocumentation`.
<2> Document the `Authorization` header. Uses the static `headerWithName` method on
`org.springframework.restdocs.headers.HeaderDocumentation.
<3> Produce a snippet describing the response's headers. Uses the static `responseHeaders`
method on `org.springframework.restdocs.headers.HeaderDocumentation`.
<4> Configure the request with an `Authorization` header that uses basic authentication.
====
The result is a snippet named `request-headers.adoc` and a snippet named
`response-headers.adoc`. Each contains a table describing the headers.
When documenting HTTP Headers, the test fails if a documented header is not found in
the request or response.
[[documenting-your-api-reusing-snippets]]
=== Reusing Snippets
It is common for an API that is being documented to have some features that are common
across several of its resources. To avoid repetition when documenting such resources, you
can reuse a `Snippet` configured with the common elements.
First, create the `Snippet` that describes the common elements. The following example
shows how to do so:
====
[source,java,indent=0]
----
include::{examples-dir}/com/example/SnippetReuse.java[tags=field]
----
====
Second, use this snippet and add further descriptors that are resource-specific. The
following examples show how to do so:
====
[source,java,indent=0,role="primary"]
.MockMvc
----
include::{examples-dir}/com/example/mockmvc/MockMvcSnippetReuse.java[tags=use]
----
<1> Reuse the `pagingLinks` `Snippet`, calling `and` to add descriptors that are specific
to the resource that is being documented.
[source,java,indent=0,role="secondary"]
.WebTestClient
----
include::{examples-dir}/com/example/webtestclient/WebTestClientSnippetReuse.java[tags=use]
----
<1> Reuse the `pagingLinks` `Snippet`, calling `and` to add descriptors that are specific
to the resource that is being documented.
[source,java,indent=0,role="secondary"]
.REST Assured
----
include::{examples-dir}/com/example/restassured/RestAssuredSnippetReuse.java[tags=use]
----
<1> Reuse the `pagingLinks` `Snippet`, calling `and` to add descriptors that are specific
to the resource that is being documented.
====
The result of the example is that links with `rel` values of `first`, `last`, `next`,
`previous`, `alpha`, and `bravo` are all documented.
[[documenting-your-api-constraints]]
=== Documenting Constraints
Spring REST Docs provides a number of classes that can help you to document constraints.
You can use an instance of `ConstraintDescriptions` to access descriptions of a class's
constraints. The following example shows how to do so:
====
[source,java,indent=0]
----
include::{examples-dir}/com/example/Constraints.java[tags=constraints]
----
<1> Create an instance of `ConstraintDescriptions` for the `UserInput` class.
<2> Get the descriptions of the `name` property's constraints. This list contains two
descriptions: one for the `NotNull` constraint and one for the `Size` constraint.
====
The {samples}/rest-notes-spring-hateoas/src/test/java/com/example/notes/ApiDocumentation.java[`ApiDocumentation`]
class in the Spring HATEOAS sample shows this functionality in action.
[[documenting-your-api-constraints-finding]]
==== Finding Constraints
By default, constraints are found by using a Bean Validation `Validator`. Currently, only
property constraints are supported. You can customize the `Validator` that is used by
creating `ConstraintDescriptions` with a custom `ValidatorConstraintResolver` instance.
To take complete control of constraint resolution, you can use your own implementation of
`ConstraintResolver`.
[[documenting-your-api-constraints-describing]]
==== Describing Constraints
Default descriptions are provided for all of Bean Validation 2.0's constraints:
* `AssertFalse`
* `AssertTrue`
* `DecimalMax`
* `DecimalMin`
* `Digits`
* `Email`
* `Future`
* `FutureOrPresent`
* `Max`
* `Min`
* `Negative`
* `NegativeOrZero`
* `NotBlank`
* `NotEmpty`
* `NotNull`
* `Null`
* `Past`
* `PastOrPresent`
* `Pattern`
* `Positive`
* `PositiveOrZero`
* `Size`
Default descriptions are also provided for the following constraints from Hibernate
Validator:
* `CodePointLength`
* `CreditCardNumber`
* `Currency`
* `EAN`
* `Email`
* `Length`
* `LuhnCheck`
* `Mod10Check`
* `Mod11Check`
* `NotBlank`
* `NotEmpty`
* `Currency`
* `Range`
* `SafeHtml`
* `URL`
To override the default descriptions or to provide a new description, you can create a
resource bundle with a base name of
`org.springframework.restdocs.constraints.ConstraintDescriptions`. The Spring
HATEOAS-based sample contains
{samples}/rest-notes-spring-hateoas/src/test/resources/org/springframework/restdocs/constraints/ConstraintDescriptions.properties[an
example of such a resource bundle].
Each key in the resource bundle is the fully-qualified name of a constraint plus a
`.description`. For example, the key for the standard `@NotNull` constraint is
`javax.validation.constraints.NotNull.description`.
You can use a property placeholder referring to a constraint's attributes in its
description. For example, the default description of the `@Min` constraint,
`Must be at least ${value}`, refers to the constraint's `value` attribute.
To take more control of constraint description resolution, you can create
`ConstraintDescriptions` with a custom `ResourceBundleConstraintDescriptionResolver`. To
take complete control, you can create `ConstraintDescriptions` with a custom
`ConstraintDescriptionResolver` implementation.
==== Using Constraint Descriptions in Generated Snippets
Once you have a constraint's descriptions, you are free to use them however you like in
the generated snippets. For example, you may want to include the constraint descriptions
as part of a field's description. Alternatively, you could include the constraints as
<<documenting-your-api-customizing-including-extra-information, extra information>> in
the request fields snippet. The
{samples}/rest-notes-spring-hateoas/src/test/java/com/example/notes/ApiDocumentation.java[`ApiDocumentation`]
class in the Spring HATEOAS-based sample illustrates the latter approach.
[[documenting-your-api-default-snippets]]
=== Default Snippets
A number of snippets are produced automatically when you document a request and response.
[cols="1,3"]
|===
|Snippet | Description
| `curl-request.adoc`
| Contains the https://curl.haxx.se[`curl`] command that is equivalent to the `MockMvc`
call that is being documented.
| `httpie-request.adoc`
| Contains the https://httpie.org[`HTTPie`] command that is equivalent to the `MockMvc`
call that is being documented.
| `http-request.adoc`
| Contains the HTTP request that is equivalent to the `MockMvc` call that is being
documented.
| `http-response.adoc`
| Contains the HTTP response that was returned.
| `request-body.adoc`
| Contains the body of the request that was sent.
| `response-body.adoc`
| Contains the body of the response that was returned.
|===
You can configure which snippets are produced by default. See the
<<configuration, configuration section>> for more information.
[[documentating-your-api-parameterized-output-directories]]
=== Using Parameterized Output Directories
When using MockMvc or REST Assured, you can parameterize the output directory used by
`document`. You cannot parameterize the output directory when using `WebTestClient`.
The following parameters are supported:
[cols="1,3"]
|===
| Parameter | Description
| {methodName}
| The unmodified name of the test method.
| {method-name}
| The name of the test method, formatted using kebab-case.
| {method_name}
| The name of the test method, formatted using snake_case.
| {ClassName}
| The unmodified simple name of the test class.
| {class-name}
| The simple name of the test class, formatted using kebab-case.
| {class_name}
| The simple name of the test class, formatted using snake_case.
| {step}
| The count of calls made to the service in the current test.
|===
For example, `document("{class-name}/{method-name}")` in a test method named
`creatingANote` on the test class `GettingStartedDocumentation` writes
snippets into a directory named `getting-started-documentation/creating-a-note`.
A parameterized output directory is particularly useful in combination with a `@Before`
method. It lets documentation be configured once in a setup method and then reused
in every test in the class. The following examples show how to do so:
====
[source,java,indent=0,role="primary"]
.MockMvc
----
include::{examples-dir}/com/example/mockmvc/ParameterizedOutput.java[tags=parameterized-output]
----
[source,java,indent=0,role="secondary"]
.REST Assured
----
include::{examples-dir}/com/example/restassured/ParameterizedOutput.java[tags=parameterized-output]
----
====
With this configuration in place, every call to the service you are testing produces
the <<documenting-your-api-default-snippets,default snippets>> without any further
configuration. Take a look at the `GettingStartedDocumentation` classes in each of the
sample applications to see this functionality in action.
[[documenting-your-api-customizing]]
=== Customizing the Output
This section describes how to customize the output of Spring REST Docs.
[[documenting-your-api-customizing-snippets]]
==== Customizing the Generated Snippets
Spring REST Docs uses https://mustache.github.io[Mustache] templates to produce the
generated snippets.
{source}/spring-restdocs-core/src/main/resources/org/springframework/restdocs/templates[Default
templates] are provided for each of the snippets that Spring REST Docs can produce. To
customize a snippet's content, you can provide your own template.
Templates are loaded from the classpath from an `org.springframework.restdocs.templates`
subpackage. The name of the subpackage is determined by the ID of the template format
that is in use. The default template format, Asciidoctor, has an ID of `asciidoctor`, so
snippets are loaded from `org.springframework.restdocs.templates.asciidoctor`. Each
template is named after the snippet that it produces. For example, to override the
template for the `curl-request.adoc` snippet, create a template named
`curl-request.snippet` in
`src/test/resources/org/springframework/restdocs/templates/asciidoctor`.
[[documenting-your-api-customizing-including-extra-information]]
==== Including Extra Information
There are two ways to provide extra information for inclusion in a generated snippet:
* Use the `attributes` method on a descriptor to add one or more attributes to it.
* Pass in some attributes when calling `curlRequest`, `httpRequest`, `httpResponse`, and
so on. Such attributes are associated with the snippet as a whole.
Any additional attributes are made available during the template rendering process.
Coupled with a custom snippet template, this makes it possible to include extra
information in a generated snippet.
A concrete example is the addition of a constraints column and a title when documenting
request fields. The first step is to provide a `constraints` attribute for each field
that you document and to provide a `title` attribute. The following examples show how to
do so:
====
[source,java,indent=0,role="primary"]
.MockMvc
----
include::{examples-dir}/com/example/mockmvc/Payload.java[tags=constraints]
----
<1> Configure the `title` attribute for the request fields snippet.
<2> Set the `constraints` attribute for the `name` field.
<3> Set the `constraints` attribute for the `email` field.
[source,java,indent=0,role="secondary"]
.WebTestClient
----
include::{examples-dir}/com/example/webtestclient/Payload.java[tags=constraints]
----
<1> Configure the `title` attribute for the request fields snippet.
<2> Set the `constraints` attribute for the `name` field.
<3> Set the `constraints` attribute for the `email` field.
[source,java,indent=0,role="secondary"]
.REST Assured
----
include::{examples-dir}/com/example/restassured/Payload.java[tags=constraints]
----
<1> Configure the `title` attribute for the request fields snippet.
<2> Set the `constraints` attribute for the `name` field.
<3> Set the `constraints` attribute for the `email` field.
====
The second step is to provide a custom template named `request-fields.snippet` that
includes the information about the fields' constraints in the generated snippet's table
and adds a title. The following example shows how to do so:
====
[source,indent=0]
----
.{{title}} <1>
|===
|Path|Type|Description|Constraints <2>
{{#fields}}
|{{path}}
|{{type}}
|{{description}}
|{{constraints}} <3>
{{/fields}}
|===
----
<1> Add a title to the table.
<2> Add a new column named "Constraints".
<3> Include the descriptors' `constraints` attribute in each row of the table.
====