Handle form and query parameters separately
Previously, form and query parameters were handled together as request parameters. Howeer, request parameters are a server-side construct that's specific to the servlet specification. As such they're not appropriate for the client-side documentation that Spring REST Docs aims to produce. This commit replaces support for documenting request parameters with support for documenting query paramters found in the query string of the request's URI and for documenting form parameters found in the form URL encoded body of the request. Closes gh-832
This commit is contained in:
@@ -649,21 +649,20 @@ For example, the preceding code results in a snippet named `response-fields-bene
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
[[documenting-your-api-request-parameters]]
|
[[documenting-your-api-query-parameters]]
|
||||||
=== Request Parameters
|
=== Query Parameters
|
||||||
|
|
||||||
You can document a request's parameters by using `requestParameters`.
|
You can document a request's query parameters by using `queryParameters`.
|
||||||
You can include request parameters in a `GET` request's query string.
|
|
||||||
The following examples show how to do so:
|
The following examples show how to do so:
|
||||||
|
|
||||||
[source,java,indent=0,role="primary"]
|
[source,java,indent=0,role="primary"]
|
||||||
.MockMvc
|
.MockMvc
|
||||||
----
|
----
|
||||||
include::{examples-dir}/com/example/mockmvc/RequestParameters.java[tags=request-parameters-query-string]
|
include::{examples-dir}/com/example/mockmvc/QueryParameters.java[tags=query-parameters]
|
||||||
----
|
----
|
||||||
<1> Perform a `GET` request with two parameters, `page` and `per_page`, in the 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.
|
<2> Configure Spring REST Docs to produce a snippet describing the request's query parameters.
|
||||||
Uses the static `requestParameters` method on `org.springframework.restdocs.request.RequestDocumentation`.
|
Uses the static `queryParameters` method on `org.springframework.restdocs.request.RequestDocumentation`.
|
||||||
<3> Document the `page` parameter.
|
<3> Document the `page` parameter.
|
||||||
Uses the static `parameterWithName` method on `org.springframework.restdocs.request.RequestDocumentation`.
|
Uses the static `parameterWithName` method on `org.springframework.restdocs.request.RequestDocumentation`.
|
||||||
<4> Document the `per_page` parameter.
|
<4> Document the `per_page` parameter.
|
||||||
@@ -671,11 +670,11 @@ Uses the static `parameterWithName` method on `org.springframework.restdocs.requ
|
|||||||
[source,java,indent=0,role="secondary"]
|
[source,java,indent=0,role="secondary"]
|
||||||
.WebTestClient
|
.WebTestClient
|
||||||
----
|
----
|
||||||
include::{examples-dir}/com/example/webtestclient/RequestParameters.java[tags=request-parameters-query-string]
|
include::{examples-dir}/com/example/webtestclient/QueryParameters.java[tags=query-parameters]
|
||||||
----
|
----
|
||||||
<1> Perform a `GET` request with two parameters, `page` and `per_page`, in the 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.
|
<2> Configure Spring REST Docs to produce a snippet describing the request's query parameters.
|
||||||
Uses the static `requestParameters` method on `org.springframework.restdocs.request.RequestDocumentation`.
|
Uses the static `queryParameters` method on `org.springframework.restdocs.request.RequestDocumentation`.
|
||||||
<3> Document the `page` parameter.
|
<3> Document the `page` parameter.
|
||||||
Uses the static `parameterWithName` method on `org.springframework.restdocs.request.RequestDocumentation`.
|
Uses the static `parameterWithName` method on `org.springframework.restdocs.request.RequestDocumentation`.
|
||||||
<4> Document the `per_page` parameter.
|
<4> Document the `per_page` parameter.
|
||||||
@@ -683,51 +682,77 @@ Uses the static `parameterWithName` method on `org.springframework.restdocs.requ
|
|||||||
[source,java,indent=0,role="secondary"]
|
[source,java,indent=0,role="secondary"]
|
||||||
.REST Assured
|
.REST Assured
|
||||||
----
|
----
|
||||||
include::{examples-dir}/com/example/restassured/RequestParameters.java[tags=request-parameters-query-string]
|
include::{examples-dir}/com/example/restassured/QueryParameters.java[tags=query-parameters]
|
||||||
----
|
----
|
||||||
<1> Configure Spring REST Docs to produce a snippet describing the request's parameters.
|
<1> Configure Spring REST Docs to produce a snippet describing the request's query parameters.
|
||||||
Uses the static `requestParameters` method on `org.springframework.restdocs.request.RequestDocumentation`.
|
Uses the static `queryParameters` method on `org.springframework.restdocs.request.RequestDocumentation`.
|
||||||
<2> Document the `page` parameter.
|
<2> Document the `page` parameter.
|
||||||
Uses the static `parameterWithName` method on `org.springframework.restdocs.request.RequestDocumentation`.
|
Uses the static `parameterWithName` method on `org.springframework.restdocs.request.RequestDocumentation`.
|
||||||
<3> Document the `per_page` parameter.
|
<3> Document the `per_page` parameter.
|
||||||
<4> Perform a `GET` request with two parameters, `page` and `per_page`, in the query string.
|
<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.
|
When documenting query parameters, the test fails if an undocumented query parameter is used in the request's query string.
|
||||||
|
Similarly, the test also fails if a documented query parameter is not found in the request's query string and the parameter has not been marked as optional.
|
||||||
|
|
||||||
|
If you do not want to document a query 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 query parameters in a relaxed mode where any undocumented parameters do not cause a test failure.
|
||||||
|
To do so, use the `relaxedQueryParameters` 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 query parameters.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
[[documenting-your-api-form-parameters]]
|
||||||
|
=== Form Parameters
|
||||||
|
|
||||||
|
You can document a request's form parameters by using `formParameters`.
|
||||||
The following examples show how to do so:
|
The following examples show how to do so:
|
||||||
|
|
||||||
[source,java,indent=0,role="primary"]
|
[source,java,indent=0,role="primary"]
|
||||||
.MockMvc
|
.MockMvc
|
||||||
----
|
----
|
||||||
include::{examples-dir}/com/example/mockmvc/RequestParameters.java[tags=request-parameters-form-data]
|
include::{examples-dir}/com/example/mockmvc/FormParameters.java[tags=form-parameters]
|
||||||
----
|
----
|
||||||
<1> Perform a `POST` request with a single parameter, `username`.
|
<1> Perform a `POST` request with a single form parameter, `username`.
|
||||||
|
<2> Configure Spring REST Docs to produce a snippet describing the request's form parameters.
|
||||||
|
Uses the static `formParameters` method on `org.springframework.restdocs.request.RequestDocumentation`.
|
||||||
|
<3> Document the `username` parameter.
|
||||||
|
Uses the static `parameterWithName` method on `org.springframework.restdocs.request.RequestDocumentation`.
|
||||||
|
|
||||||
[source,java,indent=0,role="secondary"]
|
[source,java,indent=0,role="secondary"]
|
||||||
.WebTestClient
|
.WebTestClient
|
||||||
----
|
----
|
||||||
include::{examples-dir}/com/example/webtestclient/RequestParameters.java[tags=request-parameters-form-data]
|
include::{examples-dir}/com/example/webtestclient/FormParameters.java[tags=form-parameters]
|
||||||
----
|
----
|
||||||
<1> Perform a `POST` request with a single parameter, `username`.
|
<1> Perform a `POST` request with a single form parameter, `username`.
|
||||||
|
<2> Configure Spring REST Docs to produce a snippet describing the request's form parameters.
|
||||||
|
Uses the static `formParameters` method on `org.springframework.restdocs.request.RequestDocumentation`.
|
||||||
|
<3> Document the `username` parameter.
|
||||||
|
Uses the static `parameterWithName` method on `org.springframework.restdocs.request.RequestDocumentation`.
|
||||||
|
|
||||||
[source,java,indent=0,role="secondary"]
|
[source,java,indent=0,role="secondary"]
|
||||||
.REST Assured
|
.REST Assured
|
||||||
----
|
----
|
||||||
include::{examples-dir}/com/example/restassured/RequestParameters.java[tags=request-parameters-form-data]
|
include::{examples-dir}/com/example/restassured/FormParameters.java[tags=form-parameters]
|
||||||
----
|
----
|
||||||
<1> Configure the `username` parameter.
|
<1> Configure Spring REST Docs to produce a snippet describing the request's form parameters.
|
||||||
<2> Perform the `POST` request.
|
Uses the static `formParameters` method on `org.springframework.restdocs.request.RequestDocumentation`.
|
||||||
|
<2> Document the `username` parameter.
|
||||||
|
Uses the static `parameterWithName` method on `org.springframework.restdocs.request.RequestDocumentation`.
|
||||||
|
<3> Perform a `POST` request with a single form parameter, `username`.
|
||||||
|
|
||||||
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.
|
In all cases, the result is a snippet named `form-parameters.adoc` that contains a table describing the form parameters that are supported by the resource.
|
||||||
|
|
||||||
When documenting request parameters, the test fails if an undocumented request parameter is used in the request.
|
When documenting form parameters, the test fails if an undocumented form parameter is used in the request body.
|
||||||
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.
|
Similarly, the test also fails if a documented form parameter is not found in the request body and the form parameter has not been marked as optional.
|
||||||
|
|
||||||
If you do not want to document a request parameter, you can mark it as ignored.
|
If you do not want to document a form parameter, you can mark it as ignored.
|
||||||
This prevents it from appearing in the generated snippet while avoiding the failure described above.
|
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.
|
You can also document form 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`.
|
To do so, use the `relaxedFormParameters` 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.
|
This can be useful when documenting a particular scenario where you only want to focus on a subset of the form parameters.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
40
docs/src/test/java/com/example/mockmvc/FormParameters.java
Normal file
40
docs/src/test/java/com/example/mockmvc/FormParameters.java
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2014-2021 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
|
||||||
|
*
|
||||||
|
* https://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.mockmvc;
|
||||||
|
|
||||||
|
import org.springframework.test.web.servlet.MockMvc;
|
||||||
|
|
||||||
|
import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document;
|
||||||
|
import static org.springframework.restdocs.request.RequestDocumentation.formParameters;
|
||||||
|
import static org.springframework.restdocs.request.RequestDocumentation.parameterWithName;
|
||||||
|
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
|
||||||
|
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||||
|
|
||||||
|
public class FormParameters {
|
||||||
|
|
||||||
|
private MockMvc mockMvc;
|
||||||
|
|
||||||
|
public void postFormDataSnippet() throws Exception {
|
||||||
|
// tag::form-parameters[]
|
||||||
|
this.mockMvc.perform(post("/users").param("username", "Tester")) // <1>
|
||||||
|
.andExpect(status().isCreated()).andDo(document("create-user", formParameters(// <2>
|
||||||
|
parameterWithName("username").description("The user's username") // <3>
|
||||||
|
)));
|
||||||
|
// end::form-parameters[]
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -20,31 +20,22 @@ import org.springframework.test.web.servlet.MockMvc;
|
|||||||
|
|
||||||
import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document;
|
import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document;
|
||||||
import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.get;
|
import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.get;
|
||||||
import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.post;
|
|
||||||
import static org.springframework.restdocs.request.RequestDocumentation.parameterWithName;
|
import static org.springframework.restdocs.request.RequestDocumentation.parameterWithName;
|
||||||
import static org.springframework.restdocs.request.RequestDocumentation.requestParameters;
|
import static org.springframework.restdocs.request.RequestDocumentation.queryParameters;
|
||||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||||
|
|
||||||
public class RequestParameters {
|
public class QueryParameters {
|
||||||
|
|
||||||
private MockMvc mockMvc;
|
private MockMvc mockMvc;
|
||||||
|
|
||||||
public void getQueryStringSnippet() throws Exception {
|
public void getQueryStringSnippet() throws Exception {
|
||||||
// tag::request-parameters-query-string[]
|
// tag::query-parameters[]
|
||||||
this.mockMvc.perform(get("/users?page=2&per_page=100")) // <1>
|
this.mockMvc.perform(get("/users?page=2&per_page=100")) // <1>
|
||||||
.andExpect(status().isOk()).andDo(document("users", requestParameters(// <2>
|
.andExpect(status().isOk()).andDo(document("users", queryParameters(// <2>
|
||||||
parameterWithName("page").description("The page to retrieve"), // <3>
|
parameterWithName("page").description("The page to retrieve"), // <3>
|
||||||
parameterWithName("per_page").description("Entries per page") // <4>
|
parameterWithName("per_page").description("Entries per page") // <4>
|
||||||
)));
|
)));
|
||||||
// end::request-parameters-query-string[]
|
// end::query-parameters[]
|
||||||
}
|
|
||||||
|
|
||||||
public void postFormDataSnippet() throws Exception {
|
|
||||||
// tag::request-parameters-form-data[]
|
|
||||||
this.mockMvc.perform(post("/users").param("username", "Tester")) // <1>
|
|
||||||
.andExpect(status().isCreated()).andDo(document("create-user",
|
|
||||||
requestParameters(parameterWithName("username").description("The user's username"))));
|
|
||||||
// end::request-parameters-form-data[]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2014-2022 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
|
||||||
|
*
|
||||||
|
* https://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.restassured;
|
||||||
|
|
||||||
|
import io.restassured.RestAssured;
|
||||||
|
import io.restassured.specification.RequestSpecification;
|
||||||
|
|
||||||
|
import static org.hamcrest.CoreMatchers.is;
|
||||||
|
import static org.springframework.restdocs.request.RequestDocumentation.formParameters;
|
||||||
|
import static org.springframework.restdocs.request.RequestDocumentation.parameterWithName;
|
||||||
|
import static org.springframework.restdocs.restassured.RestAssuredRestDocumentation.document;
|
||||||
|
|
||||||
|
public class FormParameters {
|
||||||
|
|
||||||
|
private RequestSpecification spec;
|
||||||
|
|
||||||
|
public void postFormDataSnippet() {
|
||||||
|
// tag::form-parameters[]
|
||||||
|
RestAssured.given(this.spec).filter(document("create-user", formParameters(// <1>
|
||||||
|
parameterWithName("username").description("The user's username")))) // <2>
|
||||||
|
.formParam("username", "Tester").when().post("/users") // <3>
|
||||||
|
.then().assertThat().statusCode(is(200));
|
||||||
|
// end::form-parameters[]
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -21,32 +21,21 @@ import io.restassured.specification.RequestSpecification;
|
|||||||
|
|
||||||
import static org.hamcrest.CoreMatchers.is;
|
import static org.hamcrest.CoreMatchers.is;
|
||||||
import static org.springframework.restdocs.request.RequestDocumentation.parameterWithName;
|
import static org.springframework.restdocs.request.RequestDocumentation.parameterWithName;
|
||||||
import static org.springframework.restdocs.request.RequestDocumentation.requestParameters;
|
import static org.springframework.restdocs.request.RequestDocumentation.queryParameters;
|
||||||
import static org.springframework.restdocs.restassured.RestAssuredRestDocumentation.document;
|
import static org.springframework.restdocs.restassured.RestAssuredRestDocumentation.document;
|
||||||
|
|
||||||
public class RequestParameters {
|
public class QueryParameters {
|
||||||
|
|
||||||
private RequestSpecification spec;
|
private RequestSpecification spec;
|
||||||
|
|
||||||
public void getQueryStringSnippet() {
|
public void getQueryStringSnippet() {
|
||||||
// tag::request-parameters-query-string[]
|
// tag::query-parameters[]
|
||||||
RestAssured.given(this.spec).filter(document("users", requestParameters(// <1>
|
RestAssured.given(this.spec).filter(document("users", queryParameters(// <1>
|
||||||
parameterWithName("page").description("The page to retrieve"), // <2>
|
parameterWithName("page").description("The page to retrieve"), // <2>
|
||||||
parameterWithName("per_page").description("Entries per page")))) // <3>
|
parameterWithName("per_page").description("Entries per page")))) // <3>
|
||||||
.when().get("/users?page=2&per_page=100") // <4>
|
.when().get("/users?page=2&per_page=100") // <4>
|
||||||
.then().assertThat().statusCode(is(200));
|
.then().assertThat().statusCode(is(200));
|
||||||
// end::request-parameters-query-string[]
|
// end::query-parameters[]
|
||||||
}
|
|
||||||
|
|
||||||
public void postFormDataSnippet() {
|
|
||||||
// tag::request-parameters-form-data[]
|
|
||||||
RestAssured.given(this.spec)
|
|
||||||
.filter(document("create-user",
|
|
||||||
requestParameters(parameterWithName("username").description("The user's username"))))
|
|
||||||
.formParam("username", "Tester") // <1>
|
|
||||||
.when().post("/users") // <2>
|
|
||||||
.then().assertThat().statusCode(is(200));
|
|
||||||
// end::request-parameters-form-data[]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -21,37 +21,26 @@ import org.springframework.util.LinkedMultiValueMap;
|
|||||||
import org.springframework.util.MultiValueMap;
|
import org.springframework.util.MultiValueMap;
|
||||||
import org.springframework.web.reactive.function.BodyInserters;
|
import org.springframework.web.reactive.function.BodyInserters;
|
||||||
|
|
||||||
|
import static org.springframework.restdocs.request.RequestDocumentation.formParameters;
|
||||||
import static org.springframework.restdocs.request.RequestDocumentation.parameterWithName;
|
import static org.springframework.restdocs.request.RequestDocumentation.parameterWithName;
|
||||||
import static org.springframework.restdocs.request.RequestDocumentation.requestParameters;
|
|
||||||
import static org.springframework.restdocs.webtestclient.WebTestClientRestDocumentation.document;
|
import static org.springframework.restdocs.webtestclient.WebTestClientRestDocumentation.document;
|
||||||
|
|
||||||
public class RequestParameters {
|
public class FormParameters {
|
||||||
|
|
||||||
// @formatter:off
|
// @formatter:off
|
||||||
|
|
||||||
private WebTestClient webTestClient;
|
private WebTestClient webTestClient;
|
||||||
|
|
||||||
public void getQueryStringSnippet() {
|
|
||||||
// tag::request-parameters-query-string[]
|
|
||||||
this.webTestClient.get().uri("/users?page=2&per_page=100") // <1>
|
|
||||||
.exchange().expectStatus().isOk().expectBody()
|
|
||||||
.consumeWith(document("users", requestParameters(// <2>
|
|
||||||
parameterWithName("page").description("The page to retrieve"), // <3>
|
|
||||||
parameterWithName("per_page").description("Entries per page") // <4>
|
|
||||||
)));
|
|
||||||
// end::request-parameters-query-string[]
|
|
||||||
}
|
|
||||||
|
|
||||||
public void postFormDataSnippet() {
|
public void postFormDataSnippet() {
|
||||||
// tag::request-parameters-form-data[]
|
// tag::form-parameters[]
|
||||||
MultiValueMap<String, String> formData = new LinkedMultiValueMap<>();
|
MultiValueMap<String, String> formData = new LinkedMultiValueMap<>();
|
||||||
formData.add("username", "Tester");
|
formData.add("username", "Tester");
|
||||||
this.webTestClient.post().uri("/users").body(BodyInserters.fromFormData(formData)) // <1>
|
this.webTestClient.post().uri("/users").body(BodyInserters.fromFormData(formData)) // <1>
|
||||||
.exchange().expectStatus().isCreated().expectBody()
|
.exchange().expectStatus().isCreated().expectBody()
|
||||||
.consumeWith(document("create-user", requestParameters(
|
.consumeWith(document("create-user", formParameters(// <2>
|
||||||
parameterWithName("username").description("The user's username")
|
parameterWithName("username").description("The user's username") // <3>
|
||||||
)));
|
)));
|
||||||
// end::request-parameters-form-data[]
|
// end::form-parameters[]
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2014-2022 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
|
||||||
|
*
|
||||||
|
* https://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.webtestclient;
|
||||||
|
|
||||||
|
import org.springframework.test.web.reactive.server.WebTestClient;
|
||||||
|
|
||||||
|
import static org.springframework.restdocs.request.RequestDocumentation.parameterWithName;
|
||||||
|
import static org.springframework.restdocs.request.RequestDocumentation.queryParameters;
|
||||||
|
import static org.springframework.restdocs.webtestclient.WebTestClientRestDocumentation.document;
|
||||||
|
|
||||||
|
public class QueryParameters {
|
||||||
|
|
||||||
|
// @formatter:off
|
||||||
|
|
||||||
|
private WebTestClient webTestClient;
|
||||||
|
|
||||||
|
public void getQueryStringSnippet() {
|
||||||
|
// tag::query-parameters[]
|
||||||
|
this.webTestClient.get().uri("/users?page=2&per_page=100") // <1>
|
||||||
|
.exchange().expectStatus().isOk().expectBody()
|
||||||
|
.consumeWith(document("users", queryParameters(// <2>
|
||||||
|
parameterWithName("page").description("The page to retrieve"), // <3>
|
||||||
|
parameterWithName("per_page").description("Entries per page") // <4>
|
||||||
|
)));
|
||||||
|
// end::query-parameters[]
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -24,13 +24,11 @@ import java.util.List;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
import org.springframework.http.HttpHeaders;
|
import org.springframework.http.HttpHeaders;
|
||||||
import org.springframework.http.HttpMethod;
|
import org.springframework.http.HttpMethod;
|
||||||
import org.springframework.restdocs.operation.OperationRequest;
|
import org.springframework.restdocs.operation.OperationRequest;
|
||||||
import org.springframework.restdocs.operation.OperationRequestPart;
|
import org.springframework.restdocs.operation.OperationRequestPart;
|
||||||
import org.springframework.restdocs.operation.Parameters;
|
|
||||||
import org.springframework.restdocs.operation.RequestCookie;
|
import org.springframework.restdocs.operation.RequestCookie;
|
||||||
import org.springframework.util.Base64Utils;
|
import org.springframework.util.Base64Utils;
|
||||||
|
|
||||||
@@ -65,15 +63,6 @@ final class CliOperationRequest implements OperationRequest {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
Parameters getNonPartParameters() {
|
|
||||||
Parameters parameters = getParameters();
|
|
||||||
Parameters nonPartParameters = new Parameters();
|
|
||||||
nonPartParameters.putAll(parameters);
|
|
||||||
Set<String> partNames = getParts().stream().map(OperationRequestPart::getName).collect(Collectors.toSet());
|
|
||||||
nonPartParameters.keySet().removeAll(partNames);
|
|
||||||
return nonPartParameters;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public byte[] getContent() {
|
public byte[] getContent() {
|
||||||
return this.delegate.getContent();
|
return this.delegate.getContent();
|
||||||
@@ -115,11 +104,6 @@ final class CliOperationRequest implements OperationRequest {
|
|||||||
return this.delegate.getMethod();
|
return this.delegate.getMethod();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public Parameters getParameters() {
|
|
||||||
return this.delegate.getParameters();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Collection<OperationRequestPart> getParts() {
|
public Collection<OperationRequestPart> getParts() {
|
||||||
return this.delegate.getParts();
|
return this.delegate.getParts();
|
||||||
|
|||||||
@@ -22,12 +22,11 @@ import java.util.List;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
|
|
||||||
import org.springframework.http.HttpMethod;
|
import org.springframework.http.HttpHeaders;
|
||||||
import org.springframework.http.MediaType;
|
import org.springframework.http.MediaType;
|
||||||
import org.springframework.restdocs.operation.Operation;
|
import org.springframework.restdocs.operation.Operation;
|
||||||
import org.springframework.restdocs.operation.OperationRequest;
|
import org.springframework.restdocs.operation.OperationRequest;
|
||||||
import org.springframework.restdocs.operation.OperationRequestPart;
|
import org.springframework.restdocs.operation.OperationRequestPart;
|
||||||
import org.springframework.restdocs.operation.Parameters;
|
|
||||||
import org.springframework.restdocs.operation.RequestCookie;
|
import org.springframework.restdocs.operation.RequestCookie;
|
||||||
import org.springframework.restdocs.snippet.Snippet;
|
import org.springframework.restdocs.snippet.Snippet;
|
||||||
import org.springframework.restdocs.snippet.TemplatedSnippet;
|
import org.springframework.restdocs.snippet.TemplatedSnippet;
|
||||||
@@ -82,21 +81,9 @@ public class CurlRequestSnippet extends TemplatedSnippet {
|
|||||||
|
|
||||||
private String getUrl(Operation operation) {
|
private String getUrl(Operation operation) {
|
||||||
OperationRequest request = operation.getRequest();
|
OperationRequest request = operation.getRequest();
|
||||||
Parameters uniqueParameters = request.getParameters().getUniqueParameters(operation.getRequest().getUri());
|
|
||||||
if (!uniqueParameters.isEmpty() && includeParametersInUri(request)) {
|
|
||||||
return String.format("'%s%s%s'", request.getUri(),
|
|
||||||
StringUtils.hasText(request.getUri().getRawQuery()) ? "&" : "?", uniqueParameters.toQueryString());
|
|
||||||
}
|
|
||||||
return String.format("'%s'", request.getUri());
|
return String.format("'%s'", request.getUri());
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean includeParametersInUri(OperationRequest request) {
|
|
||||||
HttpMethod method = request.getMethod();
|
|
||||||
return (method != HttpMethod.PUT && method != HttpMethod.POST && method != HttpMethod.PATCH)
|
|
||||||
|| (request.getContent().length > 0 && !MediaType.APPLICATION_FORM_URLENCODED
|
|
||||||
.isCompatibleWith(request.getHeaders().getContentType()));
|
|
||||||
}
|
|
||||||
|
|
||||||
private String getOptions(Operation operation) {
|
private String getOptions(Operation operation) {
|
||||||
StringBuilder builder = new StringBuilder();
|
StringBuilder builder = new StringBuilder();
|
||||||
writeIncludeHeadersInOutputOption(builder);
|
writeIncludeHeadersInOutputOption(builder);
|
||||||
@@ -147,6 +134,10 @@ public class CurlRequestSnippet extends TemplatedSnippet {
|
|||||||
private void writeHeaders(CliOperationRequest request, List<String> lines) {
|
private void writeHeaders(CliOperationRequest request, List<String> lines) {
|
||||||
for (Entry<String, List<String>> entry : request.getHeaders().entrySet()) {
|
for (Entry<String, List<String>> entry : request.getHeaders().entrySet()) {
|
||||||
for (String header : entry.getValue()) {
|
for (String header : entry.getValue()) {
|
||||||
|
if (StringUtils.hasText(request.getContentAsString()) && HttpHeaders.CONTENT_TYPE.equals(entry.getKey())
|
||||||
|
&& MediaType.APPLICATION_FORM_URLENCODED.equals(request.getHeaders().getContentType())) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
lines.add(String.format("-H '%s: %s'", entry.getKey(), header));
|
lines.add(String.format("-H '%s: %s'", entry.getKey(), header));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -176,24 +167,6 @@ public class CurlRequestSnippet extends TemplatedSnippet {
|
|||||||
if (StringUtils.hasText(content)) {
|
if (StringUtils.hasText(content)) {
|
||||||
lines.add(String.format("-d '%s'", content));
|
lines.add(String.format("-d '%s'", content));
|
||||||
}
|
}
|
||||||
else if (!request.getParts().isEmpty()) {
|
|
||||||
for (Entry<String, List<String>> entry : request.getNonPartParameters().entrySet()) {
|
|
||||||
for (String value : entry.getValue()) {
|
|
||||||
lines.add(String.format("-F '%s=%s'", entry.getKey(), value));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (request.isPutOrPost()) {
|
|
||||||
writeContentUsingParameters(request, lines);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void writeContentUsingParameters(OperationRequest request, List<String> lines) {
|
|
||||||
Parameters uniqueParameters = request.getParameters().getUniqueParameters(request.getUri());
|
|
||||||
String queryString = uniqueParameters.toQueryString();
|
|
||||||
if (StringUtils.hasText(queryString)) {
|
|
||||||
lines.add(String.format("-d '%s'", queryString));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,12 +25,11 @@ import java.util.Map;
|
|||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
|
|
||||||
import org.springframework.http.HttpHeaders;
|
import org.springframework.http.HttpHeaders;
|
||||||
import org.springframework.http.HttpMethod;
|
|
||||||
import org.springframework.http.MediaType;
|
import org.springframework.http.MediaType;
|
||||||
|
import org.springframework.restdocs.operation.FormParameters;
|
||||||
import org.springframework.restdocs.operation.Operation;
|
import org.springframework.restdocs.operation.Operation;
|
||||||
import org.springframework.restdocs.operation.OperationRequest;
|
import org.springframework.restdocs.operation.OperationRequest;
|
||||||
import org.springframework.restdocs.operation.OperationRequestPart;
|
import org.springframework.restdocs.operation.OperationRequestPart;
|
||||||
import org.springframework.restdocs.operation.Parameters;
|
|
||||||
import org.springframework.restdocs.operation.RequestCookie;
|
import org.springframework.restdocs.operation.RequestCookie;
|
||||||
import org.springframework.restdocs.snippet.Snippet;
|
import org.springframework.restdocs.snippet.Snippet;
|
||||||
import org.springframework.restdocs.snippet.TemplatedSnippet;
|
import org.springframework.restdocs.snippet.TemplatedSnippet;
|
||||||
@@ -85,6 +84,9 @@ public class HttpieRequestSnippet extends TemplatedSnippet {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private Object getContentStandardIn(CliOperationRequest request) {
|
private Object getContentStandardIn(CliOperationRequest request) {
|
||||||
|
if (MediaType.APPLICATION_FORM_URLENCODED.isCompatibleWith(request.getHeaders().getContentType())) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
String content = request.getContentAsString();
|
String content = request.getContentAsString();
|
||||||
if (StringUtils.hasText(content)) {
|
if (StringUtils.hasText(content)) {
|
||||||
return String.format("echo '%s' | ", content);
|
return String.format("echo '%s' | ", content);
|
||||||
@@ -102,21 +104,15 @@ public class HttpieRequestSnippet extends TemplatedSnippet {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private String getUrl(OperationRequest request) {
|
private String getUrl(OperationRequest request) {
|
||||||
Parameters uniqueParameters = request.getParameters().getUniqueParameters(request.getUri());
|
|
||||||
if (!uniqueParameters.isEmpty() && includeParametersInUri(request)) {
|
|
||||||
return String.format("'%s%s%s'", request.getUri(),
|
|
||||||
StringUtils.hasText(request.getUri().getRawQuery()) ? "&" : "?", uniqueParameters.toQueryString());
|
|
||||||
}
|
|
||||||
return String.format("'%s'", request.getUri());
|
return String.format("'%s'", request.getUri());
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getRequestItems(CliOperationRequest request) {
|
private String getRequestItems(CliOperationRequest request) {
|
||||||
List<String> lines = new ArrayList<>();
|
List<String> lines = new ArrayList<>();
|
||||||
|
|
||||||
writeFormDataIfNecessary(request, lines);
|
|
||||||
writeHeaders(request, lines);
|
writeHeaders(request, lines);
|
||||||
writeCookies(request, lines);
|
writeCookies(request, lines);
|
||||||
writeParametersIfNecessary(request, lines);
|
writeFormDataIfNecessary(request, lines);
|
||||||
|
|
||||||
return this.commandFormatter.format(lines);
|
return this.commandFormatter.format(lines);
|
||||||
}
|
}
|
||||||
@@ -125,24 +121,11 @@ public class HttpieRequestSnippet extends TemplatedSnippet {
|
|||||||
if (!request.getParts().isEmpty()) {
|
if (!request.getParts().isEmpty()) {
|
||||||
writer.print("--multipart ");
|
writer.print("--multipart ");
|
||||||
}
|
}
|
||||||
else if (!request.getParameters().getUniqueParameters(request.getUri()).isEmpty()
|
else if (MediaType.APPLICATION_FORM_URLENCODED.isCompatibleWith(request.getHeaders().getContentType())) {
|
||||||
&& !includeParametersInUri(request) && includeParametersAsFormOptions(request)) {
|
|
||||||
writer.print("--form ");
|
writer.print("--form ");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean includeParametersInUri(OperationRequest request) {
|
|
||||||
HttpMethod method = request.getMethod();
|
|
||||||
return (method != HttpMethod.PUT && method != HttpMethod.POST && method != HttpMethod.PATCH)
|
|
||||||
|| (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, PrintWriter writer) {
|
private void writeUserOptionIfNecessary(CliOperationRequest request, PrintWriter writer) {
|
||||||
String credentials = request.getBasicAuthCredentials();
|
String credentials = request.getBasicAuthCredentials();
|
||||||
if (credentials != null) {
|
if (credentials != null) {
|
||||||
@@ -155,23 +138,33 @@ public class HttpieRequestSnippet extends TemplatedSnippet {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void writeFormDataIfNecessary(OperationRequest request, List<String> lines) {
|
private void writeFormDataIfNecessary(OperationRequest request, List<String> lines) {
|
||||||
for (OperationRequestPart part : request.getParts()) {
|
if (MediaType.APPLICATION_FORM_URLENCODED.isCompatibleWith(request.getHeaders().getContentType())) {
|
||||||
StringBuilder oneLine = new StringBuilder();
|
FormParameters.from(request).forEach(
|
||||||
oneLine.append(String.format("'%s'", part.getName()));
|
(key, values) -> values.forEach((value) -> lines.add(String.format("'%s=%s'", key, value))));
|
||||||
if (!StringUtils.hasText(part.getSubmittedFileName())) {
|
}
|
||||||
oneLine.append(String.format("='%s'", part.getContentAsString()));
|
else {
|
||||||
}
|
for (OperationRequestPart part : request.getParts()) {
|
||||||
else {
|
StringBuilder oneLine = new StringBuilder();
|
||||||
oneLine.append(String.format("@'%s'", part.getSubmittedFileName()));
|
oneLine.append(String.format("'%s'", part.getName()));
|
||||||
}
|
if (!StringUtils.hasText(part.getSubmittedFileName())) {
|
||||||
|
oneLine.append(String.format("='%s'", part.getContentAsString()));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
oneLine.append(String.format("@'%s'", part.getSubmittedFileName()));
|
||||||
|
}
|
||||||
|
|
||||||
lines.add(oneLine.toString());
|
lines.add(oneLine.toString());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void writeHeaders(OperationRequest request, List<String> lines) {
|
private void writeHeaders(OperationRequest request, List<String> lines) {
|
||||||
HttpHeaders headers = request.getHeaders();
|
HttpHeaders headers = request.getHeaders();
|
||||||
for (Entry<String, List<String>> entry : headers.entrySet()) {
|
for (Entry<String, List<String>> entry : headers.entrySet()) {
|
||||||
|
if (entry.getKey().equals(HttpHeaders.CONTENT_TYPE)
|
||||||
|
&& headers.getContentType().isCompatibleWith(MediaType.APPLICATION_FORM_URLENCODED)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
for (String header : entry.getValue()) {
|
for (String header : entry.getValue()) {
|
||||||
// HTTPie adds Content-Type automatically with --form
|
// HTTPie adds Content-Type automatically with --form
|
||||||
if (!request.getParts().isEmpty() && entry.getKey().equals(HttpHeaders.CONTENT_TYPE)
|
if (!request.getParts().isEmpty() && entry.getKey().equals(HttpHeaders.CONTENT_TYPE)
|
||||||
@@ -189,29 +182,4 @@ public class HttpieRequestSnippet extends TemplatedSnippet {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void writeParametersIfNecessary(CliOperationRequest request, List<String> lines) {
|
|
||||||
if (StringUtils.hasText(request.getContentAsString())) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!request.getParts().isEmpty()) {
|
|
||||||
writeContentUsingParameters(request.getNonPartParameters(), lines);
|
|
||||||
}
|
|
||||||
else if (request.isPutOrPost()) {
|
|
||||||
writeContentUsingParameters(request.getParameters().getUniqueParameters(request.getUri()), lines);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void writeContentUsingParameters(Parameters parameters, List<String> lines) {
|
|
||||||
for (Map.Entry<String, List<String>> entry : parameters.entrySet()) {
|
|
||||||
if (entry.getValue().isEmpty()) {
|
|
||||||
lines.add(String.format("'%s='", entry.getKey()));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
for (String value : entry.getValue()) {
|
|
||||||
lines.add(String.format("'%s=%s'", entry.getKey(), value));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,8 +23,6 @@ import java.util.HashMap;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
import java.util.Set;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
import org.springframework.http.HttpHeaders;
|
import org.springframework.http.HttpHeaders;
|
||||||
import org.springframework.http.HttpMethod;
|
import org.springframework.http.HttpMethod;
|
||||||
@@ -32,7 +30,6 @@ import org.springframework.http.MediaType;
|
|||||||
import org.springframework.restdocs.operation.Operation;
|
import org.springframework.restdocs.operation.Operation;
|
||||||
import org.springframework.restdocs.operation.OperationRequest;
|
import org.springframework.restdocs.operation.OperationRequest;
|
||||||
import org.springframework.restdocs.operation.OperationRequestPart;
|
import org.springframework.restdocs.operation.OperationRequestPart;
|
||||||
import org.springframework.restdocs.operation.Parameters;
|
|
||||||
import org.springframework.restdocs.operation.RequestCookie;
|
import org.springframework.restdocs.operation.RequestCookie;
|
||||||
import org.springframework.restdocs.snippet.Snippet;
|
import org.springframework.restdocs.snippet.Snippet;
|
||||||
import org.springframework.restdocs.snippet.TemplatedSnippet;
|
import org.springframework.restdocs.snippet.TemplatedSnippet;
|
||||||
@@ -78,15 +75,6 @@ public class HttpRequestSnippet extends TemplatedSnippet {
|
|||||||
private String getPath(OperationRequest request) {
|
private String getPath(OperationRequest request) {
|
||||||
String path = request.getUri().getRawPath();
|
String path = request.getUri().getRawPath();
|
||||||
String queryString = request.getUri().getRawQuery();
|
String queryString = request.getUri().getRawQuery();
|
||||||
Parameters uniqueParameters = request.getParameters().getUniqueParameters(request.getUri());
|
|
||||||
if (!uniqueParameters.isEmpty() && includeParametersInUri(request)) {
|
|
||||||
if (StringUtils.hasText(queryString)) {
|
|
||||||
queryString = queryString + "&" + uniqueParameters.toQueryString();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
queryString = uniqueParameters.toQueryString();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (StringUtils.hasText(queryString)) {
|
if (StringUtils.hasText(queryString)) {
|
||||||
path = path + "?" + queryString;
|
path = path + "?" + queryString;
|
||||||
}
|
}
|
||||||
@@ -133,14 +121,7 @@ public class HttpRequestSnippet extends TemplatedSnippet {
|
|||||||
writer.printf("%n%s", content);
|
writer.printf("%n%s", content);
|
||||||
}
|
}
|
||||||
else if (isPutOrPost(request)) {
|
else if (isPutOrPost(request)) {
|
||||||
if (request.getParts().isEmpty()) {
|
if (!request.getParts().isEmpty()) {
|
||||||
String queryString = request.getParameters().getUniqueParameters(request.getUri()).toQueryString();
|
|
||||||
if (StringUtils.hasText(queryString)) {
|
|
||||||
writer.println();
|
|
||||||
writer.print(queryString);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
writeParts(request, writer);
|
writeParts(request, writer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -153,23 +134,6 @@ public class HttpRequestSnippet extends TemplatedSnippet {
|
|||||||
|
|
||||||
private void writeParts(OperationRequest request, PrintWriter writer) {
|
private void writeParts(OperationRequest request, PrintWriter writer) {
|
||||||
writer.println();
|
writer.println();
|
||||||
Set<String> partNames = request.getParts().stream().map(OperationRequestPart::getName)
|
|
||||||
.collect(Collectors.toSet());
|
|
||||||
for (Entry<String, List<String>> parameter : request.getParameters().entrySet()) {
|
|
||||||
if (!partNames.contains(parameter.getKey())) {
|
|
||||||
if (parameter.getValue().isEmpty()) {
|
|
||||||
writePartBoundary(writer);
|
|
||||||
writePart(parameter.getKey(), "", null, null, writer);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
for (String value : parameter.getValue()) {
|
|
||||||
writePartBoundary(writer);
|
|
||||||
writePart(parameter.getKey(), value, null, null, writer);
|
|
||||||
writer.println();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (OperationRequestPart part : request.getParts()) {
|
for (OperationRequestPart part : request.getParts()) {
|
||||||
writePartBoundary(writer);
|
writePartBoundary(writer);
|
||||||
writePart(part, writer);
|
writePart(part, writer);
|
||||||
@@ -206,7 +170,6 @@ public class HttpRequestSnippet extends TemplatedSnippet {
|
|||||||
|
|
||||||
private boolean requiresFormEncodingContentTypeHeader(OperationRequest request) {
|
private boolean requiresFormEncodingContentTypeHeader(OperationRequest request) {
|
||||||
return request.getHeaders().get(HttpHeaders.CONTENT_TYPE) == null && isPutOrPost(request)
|
return request.getHeaders().get(HttpHeaders.CONTENT_TYPE) == null && isPutOrPost(request)
|
||||||
&& !request.getParameters().getUniqueParameters(request.getUri()).isEmpty()
|
|
||||||
&& !includeParametersInUri(request);
|
&& !includeParametersInUri(request);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2014-2019 the original author or authors.
|
* Copyright 2014-2022 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -17,36 +17,46 @@
|
|||||||
package org.springframework.restdocs.operation;
|
package org.springframework.restdocs.operation;
|
||||||
|
|
||||||
import java.io.UnsupportedEncodingException;
|
import java.io.UnsupportedEncodingException;
|
||||||
import java.net.URI;
|
|
||||||
import java.net.URLDecoder;
|
import java.net.URLDecoder;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Scanner;
|
import java.util.Scanner;
|
||||||
|
|
||||||
|
import org.springframework.util.LinkedMultiValueMap;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A parser for the query string of a URI.
|
* A request's form parameters, derived from its form URL encoded body content.
|
||||||
*
|
*
|
||||||
* @author Andy Wilkinson
|
* @author Andy Wilkinson
|
||||||
|
* @since 3.0.0
|
||||||
*/
|
*/
|
||||||
public class QueryStringParser {
|
public final class FormParameters extends LinkedMultiValueMap<String, String> {
|
||||||
|
|
||||||
|
private FormParameters() {
|
||||||
|
|
||||||
/**
|
|
||||||
* Parses the query string of the given {@code uri} and returns the resulting
|
|
||||||
* {@link Parameters}.
|
|
||||||
* @param uri the uri to parse
|
|
||||||
* @return the parameters parsed from the query string
|
|
||||||
*/
|
|
||||||
public Parameters parse(URI uri) {
|
|
||||||
String query = uri.getRawQuery();
|
|
||||||
if (query != null) {
|
|
||||||
return parse(query);
|
|
||||||
}
|
|
||||||
return new Parameters();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private Parameters parse(String query) {
|
/**
|
||||||
Parameters parameters = new Parameters();
|
* Extracts the form parameters from the body of the given {@code request}. If the
|
||||||
try (Scanner scanner = new Scanner(query)) {
|
* request has no body content, an empty {@code FormParameters} is returned, rather
|
||||||
|
* than {@code null}.
|
||||||
|
* @param request the request
|
||||||
|
* @return the form parameters extracted from the body content
|
||||||
|
*/
|
||||||
|
public static FormParameters from(OperationRequest request) {
|
||||||
|
return of(request.getContentAsString());
|
||||||
|
}
|
||||||
|
|
||||||
|
private static FormParameters of(String bodyContent) {
|
||||||
|
if (bodyContent == null || bodyContent.length() == 0) {
|
||||||
|
return new FormParameters();
|
||||||
|
}
|
||||||
|
return parse(bodyContent);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static FormParameters parse(String bodyContent) {
|
||||||
|
FormParameters parameters = new FormParameters();
|
||||||
|
try (Scanner scanner = new Scanner(bodyContent)) {
|
||||||
scanner.useDelimiter("&");
|
scanner.useDelimiter("&");
|
||||||
while (scanner.hasNext()) {
|
while (scanner.hasNext()) {
|
||||||
processParameter(scanner.next(), parameters);
|
processParameter(scanner.next(), parameters);
|
||||||
@@ -55,7 +65,7 @@ public class QueryStringParser {
|
|||||||
return parameters;
|
return parameters;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void processParameter(String parameter, Parameters parameters) {
|
private static void processParameter(String parameter, FormParameters parameters) {
|
||||||
String[] components = parameter.split("=");
|
String[] components = parameter.split("=");
|
||||||
if (components.length > 0 && components.length < 3) {
|
if (components.length > 0 && components.length < 3) {
|
||||||
if (components.length == 2) {
|
if (components.length == 2) {
|
||||||
@@ -64,7 +74,7 @@ public class QueryStringParser {
|
|||||||
parameters.add(decode(name), decode(value));
|
parameters.add(decode(name), decode(value));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
List<String> values = parameters.computeIfAbsent(components[0], (p) -> new LinkedList<String>());
|
List<String> values = parameters.computeIfAbsent(components[0], (p) -> new LinkedList<>());
|
||||||
values.add("");
|
values.add("");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -73,12 +83,12 @@ public class QueryStringParser {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private String decode(String encoded) {
|
private static String decode(String encoded) {
|
||||||
try {
|
try {
|
||||||
return URLDecoder.decode(encoded, "UTF-8");
|
return URLDecoder.decode(encoded, "UTF-8");
|
||||||
}
|
}
|
||||||
catch (UnsupportedEncodingException ex) {
|
catch (UnsupportedEncodingException ex) {
|
||||||
throw new IllegalStateException("Unable to URL encode " + encoded + " using UTF-8", ex);
|
throw new IllegalStateException("Unable to URL decode " + encoded + " using UTF-8", ex);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2014-2018 the original author or authors.
|
* Copyright 2014-2022 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -58,14 +58,6 @@ public interface OperationRequest {
|
|||||||
*/
|
*/
|
||||||
HttpMethod getMethod();
|
HttpMethod getMethod();
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the request's parameters. For a {@code GET} request, the parameters are
|
|
||||||
* derived from the query string. For a {@code POST} request, the parameters are
|
|
||||||
* derived form the request's body.
|
|
||||||
* @return the parameters
|
|
||||||
*/
|
|
||||||
Parameters getParameters();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the request's parts, provided that it is a multipart request. If not, then
|
* Returns the request's parts, provided that it is a multipart request. If not, then
|
||||||
* an empty {@link Collection} is returned.
|
* an empty {@link Collection} is returned.
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2014-2020 the original author or authors.
|
* Copyright 2014-2022 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -17,7 +17,6 @@
|
|||||||
package org.springframework.restdocs.operation;
|
package org.springframework.restdocs.operation;
|
||||||
|
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.net.URISyntaxException;
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
|
||||||
@@ -39,15 +38,15 @@ public class OperationRequestFactory {
|
|||||||
* @param method the request method
|
* @param method the request method
|
||||||
* @param content the content of the request
|
* @param content the content of the request
|
||||||
* @param headers the request's headers
|
* @param headers the request's headers
|
||||||
* @param parameters the request's parameters
|
|
||||||
* @param parts the request's parts
|
* @param parts the request's parts
|
||||||
* @param cookies the request's cookies
|
* @param cookies the request's cookies
|
||||||
* @return the {@code OperationRequest}
|
* @return the {@code OperationRequest}
|
||||||
|
* @since 3.0.0
|
||||||
*/
|
*/
|
||||||
public OperationRequest create(URI uri, HttpMethod method, byte[] content, HttpHeaders headers,
|
public OperationRequest create(URI uri, HttpMethod method, byte[] content, HttpHeaders headers,
|
||||||
Parameters parameters, Collection<OperationRequestPart> parts, Collection<RequestCookie> cookies) {
|
Collection<OperationRequestPart> parts, Collection<RequestCookie> cookies) {
|
||||||
return new StandardOperationRequest(uri, method, content, augmentHeaders(headers, uri, content), parameters,
|
return new StandardOperationRequest(uri, method, content, augmentHeaders(headers, uri, content),
|
||||||
parts, cookies);
|
(parts != null) ? parts : Collections.emptyList(), cookies);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -58,13 +57,13 @@ public class OperationRequestFactory {
|
|||||||
* @param method the request method
|
* @param method the request method
|
||||||
* @param content the content of the request
|
* @param content the content of the request
|
||||||
* @param headers the request's headers
|
* @param headers the request's headers
|
||||||
* @param parameters the request's parameters
|
|
||||||
* @param parts the request's parts
|
* @param parts the request's parts
|
||||||
* @return the {@code OperationRequest}
|
* @return the {@code OperationRequest}
|
||||||
|
* @since 3.0.0
|
||||||
*/
|
*/
|
||||||
public OperationRequest create(URI uri, HttpMethod method, byte[] content, HttpHeaders headers,
|
public OperationRequest create(URI uri, HttpMethod method, byte[] content, HttpHeaders headers,
|
||||||
Parameters parameters, Collection<OperationRequestPart> parts) {
|
Collection<OperationRequestPart> parts) {
|
||||||
return create(uri, method, content, headers, parameters, parts, Collections.<RequestCookie>emptyList());
|
return create(uri, method, content, headers, parts, Collections.emptyList());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -77,8 +76,7 @@ public class OperationRequestFactory {
|
|||||||
*/
|
*/
|
||||||
public OperationRequest createFrom(OperationRequest original, byte[] newContent) {
|
public OperationRequest createFrom(OperationRequest original, byte[] newContent) {
|
||||||
return new StandardOperationRequest(original.getUri(), original.getMethod(), newContent,
|
return new StandardOperationRequest(original.getUri(), original.getMethod(), newContent,
|
||||||
getUpdatedHeaders(original.getHeaders(), newContent), original.getParameters(), original.getParts(),
|
getUpdatedHeaders(original.getHeaders(), newContent), original.getParts(), original.getCookies());
|
||||||
original.getCookies());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -90,33 +88,7 @@ public class OperationRequestFactory {
|
|||||||
*/
|
*/
|
||||||
public OperationRequest createFrom(OperationRequest original, HttpHeaders newHeaders) {
|
public OperationRequest createFrom(OperationRequest original, HttpHeaders newHeaders) {
|
||||||
return new StandardOperationRequest(original.getUri(), original.getMethod(), original.getContent(), newHeaders,
|
return new StandardOperationRequest(original.getUri(), original.getMethod(), original.getContent(), newHeaders,
|
||||||
original.getParameters(), original.getParts(), original.getCookies());
|
original.getParts(), original.getCookies());
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a new {@code OperationRequest} based on the given {@code original} but with
|
|
||||||
* the given {@code newParameters} applied. The query string of a {@code GET} request
|
|
||||||
* will be updated to reflect the new parameters.
|
|
||||||
* @param original the original request
|
|
||||||
* @param newParameters the new parameters
|
|
||||||
* @return the new request with the parameters applied
|
|
||||||
*/
|
|
||||||
public OperationRequest createFrom(OperationRequest original, Parameters newParameters) {
|
|
||||||
URI uri = (original.getMethod() == HttpMethod.GET) ? updateQueryString(original.getUri(), newParameters)
|
|
||||||
: original.getUri();
|
|
||||||
return new StandardOperationRequest(uri, original.getMethod(), original.getContent(), original.getHeaders(),
|
|
||||||
newParameters, original.getParts(), original.getCookies());
|
|
||||||
}
|
|
||||||
|
|
||||||
private URI updateQueryString(URI originalUri, Parameters parameters) {
|
|
||||||
try {
|
|
||||||
return new URI(originalUri.getScheme(), originalUri.getUserInfo(), originalUri.getHost(),
|
|
||||||
originalUri.getPort(), originalUri.getPath(),
|
|
||||||
parameters.isEmpty() ? null : parameters.toQueryString(), originalUri.getFragment());
|
|
||||||
}
|
|
||||||
catch (URISyntaxException ex) {
|
|
||||||
throw new RuntimeException(ex);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private HttpHeaders augmentHeaders(HttpHeaders originalHeaders, URI uri, byte[] content) {
|
private HttpHeaders augmentHeaders(HttpHeaders originalHeaders, URI uri, byte[] content) {
|
||||||
|
|||||||
@@ -1,115 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2014-2019 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
|
|
||||||
*
|
|
||||||
* https://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.operation;
|
|
||||||
|
|
||||||
import java.io.UnsupportedEncodingException;
|
|
||||||
import java.net.URI;
|
|
||||||
import java.net.URLEncoder;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import org.springframework.util.LinkedMultiValueMap;
|
|
||||||
import org.springframework.util.StringUtils;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The parameters received in a request.
|
|
||||||
*
|
|
||||||
* @author Andy Wilkinson
|
|
||||||
*/
|
|
||||||
@SuppressWarnings("serial")
|
|
||||||
public class Parameters extends LinkedMultiValueMap<String, String> {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Converts the parameters to a query string suitable for use in a URI or the body of
|
|
||||||
* a form-encoded request.
|
|
||||||
* @return the query string
|
|
||||||
*/
|
|
||||||
public String toQueryString() {
|
|
||||||
StringBuilder sb = new StringBuilder();
|
|
||||||
for (Map.Entry<String, List<String>> entry : entrySet()) {
|
|
||||||
if (entry.getValue().isEmpty()) {
|
|
||||||
append(sb, entry.getKey());
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
for (String value : entry.getValue()) {
|
|
||||||
append(sb, entry.getKey(), value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return sb.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a new {@code Parameters} containing only the parameters that do no appear
|
|
||||||
* in the query string of the given {@code uri}.
|
|
||||||
* @param uri the uri
|
|
||||||
* @return the unique parameters
|
|
||||||
*/
|
|
||||||
public Parameters getUniqueParameters(URI uri) {
|
|
||||||
Parameters queryStringParameters = new QueryStringParser().parse(uri);
|
|
||||||
Parameters uniqueParameters = new Parameters();
|
|
||||||
|
|
||||||
for (Map.Entry<String, List<String>> parameter : entrySet()) {
|
|
||||||
addIfUnique(parameter, queryStringParameters, uniqueParameters);
|
|
||||||
}
|
|
||||||
return uniqueParameters;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void addIfUnique(Map.Entry<String, List<String>> parameter, Parameters queryStringParameters,
|
|
||||||
Parameters uniqueParameters) {
|
|
||||||
if (!queryStringParameters.containsKey(parameter.getKey())) {
|
|
||||||
uniqueParameters.put(parameter.getKey(), parameter.getValue());
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
List<String> candidates = parameter.getValue();
|
|
||||||
List<String> existing = queryStringParameters.get(parameter.getKey());
|
|
||||||
for (String candidate : candidates) {
|
|
||||||
if (!existing.contains(candidate)) {
|
|
||||||
uniqueParameters.add(parameter.getKey(), candidate);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void append(StringBuilder sb, String key) {
|
|
||||||
append(sb, key, "");
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void append(StringBuilder sb, String key, String value) {
|
|
||||||
doAppend(sb, urlEncodeUTF8(key) + "=" + urlEncodeUTF8(value));
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void doAppend(StringBuilder sb, String toAppend) {
|
|
||||||
if (sb.length() > 0) {
|
|
||||||
sb.append("&");
|
|
||||||
}
|
|
||||||
sb.append(toAppend);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static String urlEncodeUTF8(String s) {
|
|
||||||
if (!StringUtils.hasLength(s)) {
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
return URLEncoder.encode(s, "UTF-8");
|
|
||||||
}
|
|
||||||
catch (UnsupportedEncodingException ex) {
|
|
||||||
throw new IllegalStateException("Unable to URL encode " + s + " using UTF-8", ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,90 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2014-2022 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
|
||||||
|
*
|
||||||
|
* https://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.operation;
|
||||||
|
|
||||||
|
import java.net.URLDecoder;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Scanner;
|
||||||
|
|
||||||
|
import org.springframework.util.LinkedMultiValueMap;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A request's query parameters, derived from its URI's query string.
|
||||||
|
*
|
||||||
|
* @author Andy Wilkinson
|
||||||
|
* @since 3.0.0
|
||||||
|
*/
|
||||||
|
public final class QueryParameters extends LinkedMultiValueMap<String, String> {
|
||||||
|
|
||||||
|
private QueryParameters() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extracts the query parameters from the query string of the given {@code request}.
|
||||||
|
* If the request has no query string, an empty {@code QueryParameters} is returned,
|
||||||
|
* rather than {@code null}.
|
||||||
|
* @param request the request
|
||||||
|
* @return the query parameters extracted from the request's query string
|
||||||
|
*/
|
||||||
|
public static QueryParameters from(OperationRequest request) {
|
||||||
|
return from(request.getUri().getRawQuery());
|
||||||
|
}
|
||||||
|
|
||||||
|
private static QueryParameters from(String queryString) {
|
||||||
|
if (queryString == null || queryString.length() == 0) {
|
||||||
|
return new QueryParameters();
|
||||||
|
}
|
||||||
|
return parse(queryString);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static QueryParameters parse(String query) {
|
||||||
|
QueryParameters parameters = new QueryParameters();
|
||||||
|
try (Scanner scanner = new Scanner(query)) {
|
||||||
|
scanner.useDelimiter("&");
|
||||||
|
while (scanner.hasNext()) {
|
||||||
|
processParameter(scanner.next(), parameters);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return parameters;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void processParameter(String parameter, QueryParameters parameters) {
|
||||||
|
String[] components = parameter.split("=");
|
||||||
|
if (components.length > 0 && components.length < 3) {
|
||||||
|
if (components.length == 2) {
|
||||||
|
String name = components[0];
|
||||||
|
String value = components[1];
|
||||||
|
parameters.add(decode(name), decode(value));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
List<String> values = parameters.computeIfAbsent(components[0], (p) -> new LinkedList<>());
|
||||||
|
values.add("");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw new IllegalArgumentException("The parameter '" + parameter + "' is malformed");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String decode(String encoded) {
|
||||||
|
return URLDecoder.decode(encoded, StandardCharsets.UTF_8);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2014-2019 the original author or authors.
|
* Copyright 2014-2022 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -32,8 +32,6 @@ class StandardOperationRequest extends AbstractOperationMessage implements Opera
|
|||||||
|
|
||||||
private HttpMethod method;
|
private HttpMethod method;
|
||||||
|
|
||||||
private Parameters parameters;
|
|
||||||
|
|
||||||
private Collection<OperationRequestPart> parts;
|
private Collection<OperationRequestPart> parts;
|
||||||
|
|
||||||
private URI uri;
|
private URI uri;
|
||||||
@@ -48,16 +46,14 @@ class StandardOperationRequest extends AbstractOperationMessage implements Opera
|
|||||||
* @param method the method
|
* @param method the method
|
||||||
* @param content the content
|
* @param content the content
|
||||||
* @param headers the headers
|
* @param headers the headers
|
||||||
* @param parameters the parameters
|
|
||||||
* @param parts the parts
|
* @param parts the parts
|
||||||
* @param cookies the cookies
|
* @param cookies the cookies
|
||||||
*/
|
*/
|
||||||
StandardOperationRequest(URI uri, HttpMethod method, byte[] content, HttpHeaders headers, Parameters parameters,
|
StandardOperationRequest(URI uri, HttpMethod method, byte[] content, HttpHeaders headers,
|
||||||
Collection<OperationRequestPart> parts, Collection<RequestCookie> cookies) {
|
Collection<OperationRequestPart> parts, Collection<RequestCookie> cookies) {
|
||||||
super(content, headers);
|
super(content, headers);
|
||||||
this.uri = uri;
|
this.uri = uri;
|
||||||
this.method = method;
|
this.method = method;
|
||||||
this.parameters = parameters;
|
|
||||||
this.parts = parts;
|
this.parts = parts;
|
||||||
this.cookies = cookies;
|
this.cookies = cookies;
|
||||||
}
|
}
|
||||||
@@ -67,11 +63,6 @@ class StandardOperationRequest extends AbstractOperationMessage implements Opera
|
|||||||
return this.method;
|
return this.method;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public Parameters getParameters() {
|
|
||||||
return this.parameters;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Collection<OperationRequestPart> getParts() {
|
public Collection<OperationRequestPart> getParts() {
|
||||||
return Collections.unmodifiableCollection(this.parts);
|
return Collections.unmodifiableCollection(this.parts);
|
||||||
|
|||||||
@@ -134,9 +134,9 @@ public class UriModifyingOperationPreprocessor implements OperationPreprocessor
|
|||||||
HttpHeaders modifiedHeaders = modify(request.getHeaders());
|
HttpHeaders modifiedHeaders = modify(request.getHeaders());
|
||||||
modifiedHeaders.set(HttpHeaders.HOST,
|
modifiedHeaders.set(HttpHeaders.HOST,
|
||||||
modifiedUri.getHost() + ((modifiedUri.getPort() != -1) ? ":" + modifiedUri.getPort() : ""));
|
modifiedUri.getHost() + ((modifiedUri.getPort() != -1) ? ":" + modifiedUri.getPort() : ""));
|
||||||
return this.contentModifyingDelegate.preprocess(new OperationRequestFactory().create(
|
return this.contentModifyingDelegate
|
||||||
uriBuilder.build(true).toUri(), request.getMethod(), request.getContent(), modifiedHeaders,
|
.preprocess(new OperationRequestFactory().create(uriBuilder.build(true).toUri(), request.getMethod(),
|
||||||
request.getParameters(), modify(request.getParts()), request.getCookies()));
|
request.getContent(), modifiedHeaders, modify(request.getParts()), request.getCookies()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2014-2020 the original author or authors.
|
* Copyright 2014-2022 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -22,36 +22,33 @@ import java.util.List;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.springframework.restdocs.operation.FormParameters;
|
||||||
import org.springframework.restdocs.operation.Operation;
|
import org.springframework.restdocs.operation.Operation;
|
||||||
import org.springframework.restdocs.operation.OperationRequest;
|
|
||||||
import org.springframework.restdocs.snippet.Snippet;
|
import org.springframework.restdocs.snippet.Snippet;
|
||||||
import org.springframework.restdocs.snippet.SnippetException;
|
import org.springframework.restdocs.snippet.SnippetException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A {@link Snippet} that documents the request parameters supported by a RESTful
|
* A {@link Snippet} that documents the form parameters supported by a RESTful resource.
|
||||||
* resource.
|
|
||||||
* <p>
|
|
||||||
* Request parameters are sent as part of the query string or as POSTed form data.
|
|
||||||
*
|
*
|
||||||
* @author Andy Wilkinson
|
* @author Andy Wilkinson
|
||||||
* @see OperationRequest#getParameters()
|
* @since 3.0.0
|
||||||
* @see RequestDocumentation#requestParameters(ParameterDescriptor...)
|
* @see RequestDocumentation#formParameters(ParameterDescriptor...)
|
||||||
* @see RequestDocumentation#requestParameters(Map, ParameterDescriptor...)
|
* @see RequestDocumentation#formParameters(Map, ParameterDescriptor...)
|
||||||
*/
|
*/
|
||||||
public class RequestParametersSnippet extends AbstractParametersSnippet {
|
public class FormParametersSnippet extends AbstractParametersSnippet {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new {@code RequestParametersSnippet} that will document the request's
|
* Creates a new {@code FormParametersSnippet} that will document the request's form
|
||||||
* parameters using the given {@code descriptors}. Undocumented parameters will
|
* parameters using the given {@code descriptors}. Undocumented parameters will
|
||||||
* trigger a failure.
|
* trigger a failure.
|
||||||
* @param descriptors the parameter descriptors
|
* @param descriptors the parameter descriptors
|
||||||
*/
|
*/
|
||||||
protected RequestParametersSnippet(List<ParameterDescriptor> descriptors) {
|
protected FormParametersSnippet(List<ParameterDescriptor> descriptors) {
|
||||||
this(descriptors, null, false);
|
this(descriptors, null, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new {@code RequestParametersSnippet} that will document the request's
|
* Creates a new {@code FormParametersSnippet} that will document the request's form
|
||||||
* parameters using the given {@code descriptors}. If
|
* parameters using the given {@code descriptors}. If
|
||||||
* {@code ignoreUndocumentedParameters} is {@code true}, undocumented parameters will
|
* {@code ignoreUndocumentedParameters} is {@code true}, undocumented parameters will
|
||||||
* be ignored and will not trigger a failure.
|
* be ignored and will not trigger a failure.
|
||||||
@@ -59,24 +56,24 @@ public class RequestParametersSnippet extends AbstractParametersSnippet {
|
|||||||
* @param ignoreUndocumentedParameters whether undocumented parameters should be
|
* @param ignoreUndocumentedParameters whether undocumented parameters should be
|
||||||
* ignored
|
* ignored
|
||||||
*/
|
*/
|
||||||
protected RequestParametersSnippet(List<ParameterDescriptor> descriptors, boolean ignoreUndocumentedParameters) {
|
protected FormParametersSnippet(List<ParameterDescriptor> descriptors, boolean ignoreUndocumentedParameters) {
|
||||||
this(descriptors, null, ignoreUndocumentedParameters);
|
this(descriptors, null, ignoreUndocumentedParameters);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new {@code RequestParametersSnippet} that will document the request's
|
* Creates a new {@code FormParametersSnippet} that will document the request's form
|
||||||
* parameters using the given {@code descriptors}. The given {@code attributes} will
|
* parameters using the given {@code descriptors}. The given {@code attributes} will
|
||||||
* be included in the model during template rendering. Undocumented parameters will
|
* be included in the model during template rendering. Undocumented parameters will
|
||||||
* trigger a failure.
|
* trigger a failure.
|
||||||
* @param descriptors the parameter descriptors
|
* @param descriptors the parameter descriptors
|
||||||
* @param attributes the additional attributes
|
* @param attributes the additional attributes
|
||||||
*/
|
*/
|
||||||
protected RequestParametersSnippet(List<ParameterDescriptor> descriptors, Map<String, Object> attributes) {
|
protected FormParametersSnippet(List<ParameterDescriptor> descriptors, Map<String, Object> attributes) {
|
||||||
this(descriptors, attributes, false);
|
this(descriptors, attributes, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new {@code RequestParametersSnippet} that will document the request's
|
* Creates a new {@code FormParametersSnippet} that will document the request's form
|
||||||
* parameters using the given {@code descriptors}. The given {@code attributes} will
|
* parameters using the given {@code descriptors}. The given {@code attributes} will
|
||||||
* be included in the model during template rendering. If
|
* be included in the model during template rendering. If
|
||||||
* {@code ignoreUndocumentedParameters} is {@code true}, undocumented parameters will
|
* {@code ignoreUndocumentedParameters} is {@code true}, undocumented parameters will
|
||||||
@@ -86,54 +83,53 @@ public class RequestParametersSnippet extends AbstractParametersSnippet {
|
|||||||
* @param ignoreUndocumentedParameters whether undocumented parameters should be
|
* @param ignoreUndocumentedParameters whether undocumented parameters should be
|
||||||
* ignored
|
* ignored
|
||||||
*/
|
*/
|
||||||
protected RequestParametersSnippet(List<ParameterDescriptor> descriptors, Map<String, Object> attributes,
|
protected FormParametersSnippet(List<ParameterDescriptor> descriptors, Map<String, Object> attributes,
|
||||||
boolean ignoreUndocumentedParameters) {
|
boolean ignoreUndocumentedParameters) {
|
||||||
super("request-parameters", descriptors, attributes, ignoreUndocumentedParameters);
|
super("form-parameters", descriptors, attributes, ignoreUndocumentedParameters);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void verificationFailed(Set<String> undocumentedParameters, Set<String> missingParameters) {
|
protected void verificationFailed(Set<String> undocumentedParameters, Set<String> missingParameters) {
|
||||||
String message = "";
|
String message = "";
|
||||||
if (!undocumentedParameters.isEmpty()) {
|
if (!undocumentedParameters.isEmpty()) {
|
||||||
message += "Request parameters with the following names were not documented: " + undocumentedParameters;
|
message += "Form parameters with the following names were not documented: " + undocumentedParameters;
|
||||||
}
|
}
|
||||||
if (!missingParameters.isEmpty()) {
|
if (!missingParameters.isEmpty()) {
|
||||||
if (message.length() > 0) {
|
if (message.length() > 0) {
|
||||||
message += ". ";
|
message += ". ";
|
||||||
}
|
}
|
||||||
message += "Request parameters with the following names were not found in the request: "
|
message += "Form parameters with the following names were not found in the request: " + missingParameters;
|
||||||
+ missingParameters;
|
|
||||||
}
|
}
|
||||||
throw new SnippetException(message);
|
throw new SnippetException(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Set<String> extractActualParameters(Operation operation) {
|
protected Set<String> extractActualParameters(Operation operation) {
|
||||||
return operation.getRequest().getParameters().keySet();
|
return FormParameters.from(operation.getRequest()).keySet();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a new {@code RequestParametersSnippet} configured with this snippet's
|
* Returns a new {@code FormParametersSnippet} configured with this snippet's
|
||||||
* attributes and its descriptors combined with the given
|
* attributes and its descriptors combined with the given
|
||||||
* {@code additionalDescriptors}.
|
* {@code additionalDescriptors}.
|
||||||
* @param additionalDescriptors the additional descriptors
|
* @param additionalDescriptors the additional descriptors
|
||||||
* @return the new snippet
|
* @return the new snippet
|
||||||
*/
|
*/
|
||||||
public RequestParametersSnippet and(ParameterDescriptor... additionalDescriptors) {
|
public FormParametersSnippet and(ParameterDescriptor... additionalDescriptors) {
|
||||||
return and(Arrays.asList(additionalDescriptors));
|
return and(Arrays.asList(additionalDescriptors));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a new {@code RequestParametersSnippet} configured with this snippet's
|
* Returns a new {@code FormParametersSnippet} configured with this snippet's
|
||||||
* attributes and its descriptors combined with the given
|
* attributes and its descriptors combined with the given
|
||||||
* {@code additionalDescriptors}.
|
* {@code additionalDescriptors}.
|
||||||
* @param additionalDescriptors the additional descriptors
|
* @param additionalDescriptors the additional descriptors
|
||||||
* @return the new snippet
|
* @return the new snippet
|
||||||
*/
|
*/
|
||||||
public RequestParametersSnippet and(List<ParameterDescriptor> additionalDescriptors) {
|
public FormParametersSnippet and(List<ParameterDescriptor> additionalDescriptors) {
|
||||||
List<ParameterDescriptor> combinedDescriptors = new ArrayList<>(getParameterDescriptors().values());
|
List<ParameterDescriptor> combinedDescriptors = new ArrayList<>(getParameterDescriptors().values());
|
||||||
combinedDescriptors.addAll(additionalDescriptors);
|
combinedDescriptors.addAll(additionalDescriptors);
|
||||||
return new RequestParametersSnippet(combinedDescriptors, this.getAttributes(),
|
return new FormParametersSnippet(combinedDescriptors, this.getAttributes(),
|
||||||
this.isIgnoreUndocumentedParameters());
|
this.isIgnoreUndocumentedParameters());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,136 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2014-2022 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
|
||||||
|
*
|
||||||
|
* https://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.request;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.springframework.restdocs.operation.Operation;
|
||||||
|
import org.springframework.restdocs.operation.QueryParameters;
|
||||||
|
import org.springframework.restdocs.snippet.Snippet;
|
||||||
|
import org.springframework.restdocs.snippet.SnippetException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A {@link Snippet} that documents the query parameters supported by a RESTful resource.
|
||||||
|
*
|
||||||
|
* @author Andy Wilkinson
|
||||||
|
* @since 3.0.0
|
||||||
|
* @see RequestDocumentation#queryParameters(ParameterDescriptor...)
|
||||||
|
* @see RequestDocumentation#queryParameters(Map, ParameterDescriptor...)
|
||||||
|
*/
|
||||||
|
public class QueryParametersSnippet extends AbstractParametersSnippet {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new {@code QueryParametersSnippet} that will document the request's query
|
||||||
|
* parameters using the given {@code descriptors}. Undocumented parameters will
|
||||||
|
* trigger a failure.
|
||||||
|
* @param descriptors the parameter descriptors
|
||||||
|
*/
|
||||||
|
protected QueryParametersSnippet(List<ParameterDescriptor> descriptors) {
|
||||||
|
this(descriptors, null, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new {@code QueryParametersSnippet} that will document the request's query
|
||||||
|
* parameters using the given {@code descriptors}. If
|
||||||
|
* {@code ignoreUndocumentedParameters} is {@code true}, undocumented parameters will
|
||||||
|
* be ignored and will not trigger a failure.
|
||||||
|
* @param descriptors the parameter descriptors
|
||||||
|
* @param ignoreUndocumentedParameters whether undocumented parameters should be
|
||||||
|
* ignored
|
||||||
|
*/
|
||||||
|
protected QueryParametersSnippet(List<ParameterDescriptor> descriptors, boolean ignoreUndocumentedParameters) {
|
||||||
|
this(descriptors, null, ignoreUndocumentedParameters);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new {@code QueryParametersSnippet} that will document the request's query
|
||||||
|
* parameters using the given {@code descriptors}. The given {@code attributes} will
|
||||||
|
* be included in the model during template rendering. Undocumented parameters will
|
||||||
|
* trigger a failure.
|
||||||
|
* @param descriptors the parameter descriptors
|
||||||
|
* @param attributes the additional attributes
|
||||||
|
*/
|
||||||
|
protected QueryParametersSnippet(List<ParameterDescriptor> descriptors, Map<String, Object> attributes) {
|
||||||
|
this(descriptors, attributes, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new {@code QueryParametersSnippet} that will document the request's query
|
||||||
|
* parameters using the given {@code descriptors}. The given {@code attributes} will
|
||||||
|
* be included in the model during template rendering. If
|
||||||
|
* {@code ignoreUndocumentedParameters} is {@code true}, undocumented parameters will
|
||||||
|
* be ignored and will not trigger a failure.
|
||||||
|
* @param descriptors the parameter descriptors
|
||||||
|
* @param attributes the additional attributes
|
||||||
|
* @param ignoreUndocumentedParameters whether undocumented parameters should be
|
||||||
|
* ignored
|
||||||
|
*/
|
||||||
|
protected QueryParametersSnippet(List<ParameterDescriptor> descriptors, Map<String, Object> attributes,
|
||||||
|
boolean ignoreUndocumentedParameters) {
|
||||||
|
super("query-parameters", descriptors, attributes, ignoreUndocumentedParameters);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void verificationFailed(Set<String> undocumentedParameters, Set<String> missingParameters) {
|
||||||
|
String message = "";
|
||||||
|
if (!undocumentedParameters.isEmpty()) {
|
||||||
|
message += "Query parameters with the following names were not documented: " + undocumentedParameters;
|
||||||
|
}
|
||||||
|
if (!missingParameters.isEmpty()) {
|
||||||
|
if (message.length() > 0) {
|
||||||
|
message += ". ";
|
||||||
|
}
|
||||||
|
message += "Query parameters with the following names were not found in the request: " + missingParameters;
|
||||||
|
}
|
||||||
|
throw new SnippetException(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Set<String> extractActualParameters(Operation operation) {
|
||||||
|
return QueryParameters.from(operation.getRequest()).keySet();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a new {@code QueryParametersSnippet} configured with this snippet's
|
||||||
|
* attributes and its descriptors combined with the given
|
||||||
|
* {@code additionalDescriptors}.
|
||||||
|
* @param additionalDescriptors the additional descriptors
|
||||||
|
* @return the new snippet
|
||||||
|
*/
|
||||||
|
public QueryParametersSnippet and(ParameterDescriptor... additionalDescriptors) {
|
||||||
|
return and(Arrays.asList(additionalDescriptors));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a new {@code QueryParametersSnippet} configured with this snippet's
|
||||||
|
* attributes and its descriptors combined with the given
|
||||||
|
* {@code additionalDescriptors}.
|
||||||
|
* @param additionalDescriptors the additional descriptors
|
||||||
|
* @return the new snippet
|
||||||
|
*/
|
||||||
|
public QueryParametersSnippet and(List<ParameterDescriptor> additionalDescriptors) {
|
||||||
|
List<ParameterDescriptor> combinedDescriptors = new ArrayList<>(getParameterDescriptors().values());
|
||||||
|
combinedDescriptors.addAll(additionalDescriptors);
|
||||||
|
return new QueryParametersSnippet(combinedDescriptors, this.getAttributes(),
|
||||||
|
this.isIgnoreUndocumentedParameters());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2014-2019 the original author or authors.
|
* Copyright 2014-2022 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -203,159 +203,321 @@ public abstract class RequestDocumentation {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a {@code Snippet} that will document the parameters from the API
|
* Returns a {@code Snippet} that will document the query parameters from the API
|
||||||
* operation's request. The parameters will be documented using the given
|
* operation's request. The query parameters will be documented using the given
|
||||||
* {@code descriptors}.
|
* {@code descriptors}.
|
||||||
* <p>
|
* <p>
|
||||||
* If a parameter is present in the request, but is not documented by one of the
|
* If a query parameter is present in the request, but is not documented by one of the
|
||||||
* descriptors, a failure will occur when the snippet is invoked. Similarly, if a
|
* descriptors, a failure will occur when the snippet is invoked. Similarly, if a
|
||||||
* parameter is documented, is not marked as optional, and is not present in the
|
* query parameter is documented, is not marked as optional, and is not present in the
|
||||||
* request, a failure will also occur.
|
* request, a failure will also occur.
|
||||||
* <p>
|
* <p>
|
||||||
* If you do not want to document a request parameter, a parameter descriptor can be
|
* If you do not want to document a query parameter, a parameter descriptor can be
|
||||||
* marked as {@link ParameterDescriptor#ignored()}. This will prevent it from
|
* marked as {@link ParameterDescriptor#ignored()}. This will prevent it from
|
||||||
* appearing in the generated snippet while avoiding the failure described above.
|
* appearing in the generated snippet while avoiding the failure described above.
|
||||||
* @param descriptors the descriptions of the request's parameters
|
* @param descriptors the descriptions of the request's query parameters
|
||||||
* @return the snippet
|
* @return the snippet
|
||||||
* @see OperationRequest#getParameters()
|
* @since 3.0.0
|
||||||
*/
|
*/
|
||||||
public static RequestParametersSnippet requestParameters(ParameterDescriptor... descriptors) {
|
public static QueryParametersSnippet queryParameters(ParameterDescriptor... descriptors) {
|
||||||
return requestParameters(Arrays.asList(descriptors));
|
return queryParameters(Arrays.asList(descriptors));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a {@code Snippet} that will document the parameters from the API
|
* Returns a {@code Snippet} that will document the query parameters from the API
|
||||||
* operation's request. The parameters will be documented using the given
|
* operation's request. The query parameters will be documented using the given
|
||||||
* {@code descriptors}.
|
* {@code descriptors}.
|
||||||
* <p>
|
* <p>
|
||||||
* If a parameter is present in the request, but is not documented by one of the
|
* If a query parameter is present in the request, but is not documented by one of the
|
||||||
* descriptors, a failure will occur when the snippet is invoked. Similarly, if a
|
* descriptors, a failure will occur when the snippet is invoked. Similarly, if a
|
||||||
* parameter is documented, is not marked as optional, and is not present in the
|
* query parameter is documented, is not marked as optional, and is not present in the
|
||||||
* request, a failure will also occur.
|
* request, a failure will also occur.
|
||||||
* <p>
|
* <p>
|
||||||
* If you do not want to document a request parameter, a parameter descriptor can be
|
* If you do not want to document a query parameter, a parameter descriptor can be
|
||||||
* marked as {@link ParameterDescriptor#ignored()}. This will prevent it from
|
* marked as {@link ParameterDescriptor#ignored()}. This will prevent it from
|
||||||
* appearing in the generated snippet while avoiding the failure described above.
|
* appearing in the generated snippet while avoiding the failure described above.
|
||||||
* @param descriptors the descriptions of the request's parameters
|
* @param descriptors the descriptions of the request's query parameters
|
||||||
* @return the snippet
|
* @return the snippet
|
||||||
* @see OperationRequest#getParameters()
|
* @since 3.0.0
|
||||||
*/
|
*/
|
||||||
public static RequestParametersSnippet requestParameters(List<ParameterDescriptor> descriptors) {
|
public static QueryParametersSnippet queryParameters(List<ParameterDescriptor> descriptors) {
|
||||||
return new RequestParametersSnippet(descriptors);
|
return new QueryParametersSnippet(descriptors);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a {@code Snippet} that will document the parameters from the API
|
* Returns a {@code Snippet} that will document the query parameters from the API
|
||||||
* operation's request. The parameters will be documented using the given
|
* operation's request. The query parameters will be documented using the given
|
||||||
|
* {@code descriptors}.
|
||||||
|
* <p>
|
||||||
|
* If a query parameter is documented, is not marked as optional, and is not present
|
||||||
|
* in the response, a failure will occur. Any undocumented query parameters will be
|
||||||
|
* ignored.
|
||||||
|
* @param descriptors the descriptions of the request's query parameters
|
||||||
|
* @return the snippet
|
||||||
|
* @since 3.0.0
|
||||||
|
*/
|
||||||
|
public static QueryParametersSnippet relaxedQueryParameters(ParameterDescriptor... descriptors) {
|
||||||
|
return relaxedQueryParameters(Arrays.asList(descriptors));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a {@code Snippet} that will document the query parameters from the API
|
||||||
|
* operation's request. The query parameters will be documented using the given
|
||||||
* {@code descriptors}.
|
* {@code descriptors}.
|
||||||
* <p>
|
* <p>
|
||||||
* If a parameter is documented, is not marked as optional, and is not present in the
|
* If a parameter is documented, is not marked as optional, and is not present in the
|
||||||
* response, a failure will occur. Any undocumented parameters will be ignored.
|
* response, a failure will occur. Any undocumented query parameters will be ignored.
|
||||||
* @param descriptors the descriptions of the request's parameters
|
* @param descriptors the descriptions of the request's query parameters
|
||||||
* @return the snippet
|
* @return the snippet
|
||||||
* @see OperationRequest#getParameters()
|
* @since 3.0.0
|
||||||
*/
|
*/
|
||||||
public static RequestParametersSnippet relaxedRequestParameters(ParameterDescriptor... descriptors) {
|
public static QueryParametersSnippet relaxedQueryParameters(List<ParameterDescriptor> descriptors) {
|
||||||
return relaxedRequestParameters(Arrays.asList(descriptors));
|
return new QueryParametersSnippet(descriptors, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a {@code Snippet} that will document the parameters from the API
|
* Returns a {@code Snippet} that will document the query parameters from the API
|
||||||
* operation's request. The parameters will be documented using the given
|
|
||||||
* {@code descriptors}.
|
|
||||||
* <p>
|
|
||||||
* If a parameter is documented, is not marked as optional, and is not present in the
|
|
||||||
* response, a failure will occur. Any undocumented parameters will be ignored.
|
|
||||||
* @param descriptors the descriptions of the request's parameters
|
|
||||||
* @return the snippet
|
|
||||||
* @see OperationRequest#getParameters()
|
|
||||||
*/
|
|
||||||
public static RequestParametersSnippet relaxedRequestParameters(List<ParameterDescriptor> descriptors) {
|
|
||||||
return new RequestParametersSnippet(descriptors, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a {@code Snippet} that will document the parameters from the API
|
|
||||||
* operation's request. The given {@code attributes} will be available during snippet
|
* operation's request. The given {@code attributes} will be available during snippet
|
||||||
* rendering and the parameters will be documented using the given {@code descriptors}
|
* rendering and the query parameters will be documented using the given
|
||||||
* .
|
* {@code descriptors} .
|
||||||
* <p>
|
* <p>
|
||||||
* If a parameter is present in the request, but is not documented by one of the
|
* If a query parameter is present in the request, but is not documented by one of the
|
||||||
* descriptors, a failure will occur when the snippet is invoked. Similarly, if a
|
* descriptors, a failure will occur when the snippet is invoked. Similarly, if a
|
||||||
* parameter is documented, is not marked as optional, and is not present in the
|
* query parameter is documented, is not marked as optional, and is not present in the
|
||||||
* request, a failure will also occur.
|
* request, a failure will also occur.
|
||||||
* <p>
|
* <p>
|
||||||
* If you do not want to document a request parameter, a parameter descriptor can be
|
* If you do not want to document a query parameter, a parameter descriptor can be
|
||||||
* marked as {@link ParameterDescriptor#ignored()}. This will prevent it from
|
* marked as {@link ParameterDescriptor#ignored()}. This will prevent it from
|
||||||
* appearing in the generated snippet while avoiding the failure described above.
|
* appearing in the generated snippet while avoiding the failure described above.
|
||||||
* @param attributes the attributes
|
* @param attributes the attributes
|
||||||
* @param descriptors the descriptions of the request's parameters
|
* @param descriptors the descriptions of the request's query parameters
|
||||||
* @return the snippet that will document the parameters
|
* @return the snippet that will document the query parameters
|
||||||
* @see OperationRequest#getParameters()
|
* @since 3.0.0
|
||||||
*/
|
*/
|
||||||
public static RequestParametersSnippet requestParameters(Map<String, Object> attributes,
|
public static QueryParametersSnippet queryParameters(Map<String, Object> attributes,
|
||||||
ParameterDescriptor... descriptors) {
|
ParameterDescriptor... descriptors) {
|
||||||
return requestParameters(attributes, Arrays.asList(descriptors));
|
return queryParameters(attributes, Arrays.asList(descriptors));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a {@code Snippet} that will document the parameters from the API
|
* Returns a {@code Snippet} that will document the query parameters from the API
|
||||||
* operation's request. The given {@code attributes} will be available during snippet
|
* operation's request. The given {@code attributes} will be available during snippet
|
||||||
* rendering and the parameters will be documented using the given {@code descriptors}
|
* rendering and the query parameters will be documented using the given
|
||||||
* .
|
* {@code descriptors} .
|
||||||
* <p>
|
* <p>
|
||||||
* If a parameter is present in the request, but is not documented by one of the
|
* If a query parameter is present in the request, but is not documented by one of the
|
||||||
* descriptors, a failure will occur when the snippet is invoked. Similarly, if a
|
* descriptors, a failure will occur when the snippet is invoked. Similarly, if a
|
||||||
* parameter is documented, is not marked as optional, and is not present in the
|
* query parameter is documented, is not marked as optional, and is not present in the
|
||||||
* request, a failure will also occur.
|
* request, a failure will also occur.
|
||||||
* <p>
|
* <p>
|
||||||
* If you do not want to document a request parameter, a parameter descriptor can be
|
* If you do not want to document a query parameter, a parameter descriptor can be
|
||||||
* marked as {@link ParameterDescriptor#ignored()}. This will prevent it from
|
* marked as {@link ParameterDescriptor#ignored()}. This will prevent it from
|
||||||
* appearing in the generated snippet while avoiding the failure described above.
|
* appearing in the generated snippet while avoiding the failure described above.
|
||||||
* @param attributes the attributes
|
* @param attributes the attributes
|
||||||
* @param descriptors the descriptions of the request's parameters
|
* @param descriptors the descriptions of the request's query parameters
|
||||||
* @return the snippet that will document the parameters
|
* @return the snippet that will document the query parameters
|
||||||
* @see OperationRequest#getParameters()
|
* @since 3.0.0
|
||||||
*/
|
*/
|
||||||
public static RequestParametersSnippet requestParameters(Map<String, Object> attributes,
|
public static QueryParametersSnippet queryParameters(Map<String, Object> attributes,
|
||||||
List<ParameterDescriptor> descriptors) {
|
List<ParameterDescriptor> descriptors) {
|
||||||
return new RequestParametersSnippet(descriptors, attributes);
|
return new QueryParametersSnippet(descriptors, attributes);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a {@code Snippet} that will document the parameters from the API
|
* Returns a {@code Snippet} that will document the query parameters from the API
|
||||||
* operation's request. The given {@code attributes} will be available during snippet
|
* operation's request. The given {@code attributes} will be available during snippet
|
||||||
* rendering and the parameters will be documented using the given {@code descriptors}
|
* rendering and the query parameters will be documented using the given
|
||||||
* .
|
* {@code descriptors} .
|
||||||
* <p>
|
* <p>
|
||||||
* If a parameter is documented, is not marked as optional, and is not present in the
|
* If a query parameter is documented, is not marked as optional, and is not present
|
||||||
* response, a failure will occur. Any undocumented parameters will be ignored.
|
* in the response, a failure will occur. Any undocumented query parameters will be
|
||||||
|
* ignored.
|
||||||
* @param attributes the attributes
|
* @param attributes the attributes
|
||||||
* @param descriptors the descriptions of the request's parameters
|
* @param descriptors the descriptions of the request's query parameters
|
||||||
* @return the snippet that will document the parameters
|
* @return the snippet that will document the query parameters
|
||||||
* @see OperationRequest#getParameters()
|
* @since 3.0.0
|
||||||
*/
|
*/
|
||||||
public static RequestParametersSnippet relaxedRequestParameters(Map<String, Object> attributes,
|
public static QueryParametersSnippet relaxedQueryParameters(Map<String, Object> attributes,
|
||||||
ParameterDescriptor... descriptors) {
|
ParameterDescriptor... descriptors) {
|
||||||
return relaxedRequestParameters(attributes, Arrays.asList(descriptors));
|
return relaxedQueryParameters(attributes, Arrays.asList(descriptors));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a {@code Snippet} that will document the parameters from the API
|
* Returns a {@code Snippet} that will document the query parameters from the API
|
||||||
* operation's request. The given {@code attributes} will be available during snippet
|
* operation's request. The given {@code attributes} will be available during snippet
|
||||||
* rendering and the parameters will be documented using the given {@code descriptors}
|
* rendering and the query parameters will be documented using the given
|
||||||
* .
|
* {@code descriptors} .
|
||||||
|
* <p>
|
||||||
|
* If a query parameter is documented, is not marked as optional, and is not present
|
||||||
|
* in the response, a failure will occur. Any undocumented query parameters will be
|
||||||
|
* ignored.
|
||||||
|
* @param attributes the attributes
|
||||||
|
* @param descriptors the descriptions of the request's query parameters
|
||||||
|
* @return the snippet that will document the query parameters
|
||||||
|
* @since 3.0.0
|
||||||
|
*/
|
||||||
|
public static QueryParametersSnippet relaxedQueryParameters(Map<String, Object> attributes,
|
||||||
|
List<ParameterDescriptor> descriptors) {
|
||||||
|
return new QueryParametersSnippet(descriptors, attributes, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a {@code Snippet} that will document the form parameters from the API
|
||||||
|
* operation's request. The form parameters will be documented using the given
|
||||||
|
* {@code descriptors}.
|
||||||
|
* <p>
|
||||||
|
* If a form parameter is present in the request, but is not documented by one of the
|
||||||
|
* descriptors, a failure will occur when the snippet is invoked. Similarly, if a form
|
||||||
|
* parameter is documented, is not marked as optional, and is not present in the
|
||||||
|
* request, a failure will also occur.
|
||||||
|
* <p>
|
||||||
|
* If you do not want to document a form parameter, a parameter descriptor can be
|
||||||
|
* marked as {@link ParameterDescriptor#ignored()}. This will prevent it from
|
||||||
|
* appearing in the generated snippet while avoiding the failure described above.
|
||||||
|
* @param descriptors the descriptions of the request's form parameters
|
||||||
|
* @return the snippet
|
||||||
|
* @since 3.0.0
|
||||||
|
*/
|
||||||
|
public static FormParametersSnippet formParameters(ParameterDescriptor... descriptors) {
|
||||||
|
return formParameters(Arrays.asList(descriptors));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a {@code Snippet} that will document the form parameters from the API
|
||||||
|
* operation's request. The form parameters will be documented using the given
|
||||||
|
* {@code descriptors}.
|
||||||
|
* <p>
|
||||||
|
* If a form parameter is present in the request, but is not documented by one of the
|
||||||
|
* descriptors, a failure will occur when the snippet is invoked. Similarly, if a form
|
||||||
|
* parameter is documented, is not marked as optional, and is not present in the
|
||||||
|
* request, a failure will also occur.
|
||||||
|
* <p>
|
||||||
|
* If you do not want to document a form parameter, a parameter descriptor can be
|
||||||
|
* marked as {@link ParameterDescriptor#ignored()}. This will prevent it from
|
||||||
|
* appearing in the generated snippet while avoiding the failure described above.
|
||||||
|
* @param descriptors the descriptions of the request's form parameters
|
||||||
|
* @return the snippet
|
||||||
|
* @since 3.0.0
|
||||||
|
*/
|
||||||
|
public static FormParametersSnippet formParameters(List<ParameterDescriptor> descriptors) {
|
||||||
|
return new FormParametersSnippet(descriptors);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a {@code Snippet} that will document the form parameters from the API
|
||||||
|
* operation's request. The form parameters will be documented using the given
|
||||||
|
* {@code descriptors}.
|
||||||
|
* <p>
|
||||||
|
* If a form parameter is documented, is not marked as optional, and is not present in
|
||||||
|
* the response, a failure will occur. Any undocumented form parameters will be
|
||||||
|
* ignored.
|
||||||
|
* @param descriptors the descriptions of the request's form parameters
|
||||||
|
* @return the snippet
|
||||||
|
* @since 3.0.0
|
||||||
|
*/
|
||||||
|
public static FormParametersSnippet relaxedFormParameters(ParameterDescriptor... descriptors) {
|
||||||
|
return relaxedFormParameters(Arrays.asList(descriptors));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a {@code Snippet} that will document the form parameters from the API
|
||||||
|
* operation's request. The form parameters will be documented using the given
|
||||||
|
* {@code descriptors}.
|
||||||
* <p>
|
* <p>
|
||||||
* If a parameter is documented, is not marked as optional, and is not present in the
|
* If a parameter is documented, is not marked as optional, and is not present in the
|
||||||
* response, a failure will occur. Any undocumented parameters will be ignored.
|
* response, a failure will occur. Any undocumented form parameters will be ignored.
|
||||||
* @param attributes the attributes
|
* @param descriptors the descriptions of the request's form parameters
|
||||||
* @param descriptors the descriptions of the request's parameters
|
* @return the snippet
|
||||||
* @return the snippet that will document the parameters
|
* @since 3.0.0
|
||||||
* @see OperationRequest#getParameters()
|
|
||||||
*/
|
*/
|
||||||
public static RequestParametersSnippet relaxedRequestParameters(Map<String, Object> attributes,
|
public static FormParametersSnippet relaxedFormParameters(List<ParameterDescriptor> descriptors) {
|
||||||
|
return new FormParametersSnippet(descriptors, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a {@code Snippet} that will document the form parameters from the API
|
||||||
|
* operation's request. The given {@code attributes} will be available during snippet
|
||||||
|
* rendering and the form parameters will be documented using the given
|
||||||
|
* {@code descriptors} .
|
||||||
|
* <p>
|
||||||
|
* If a form parameter is present in the request, but is not documented by one of the
|
||||||
|
* descriptors, a failure will occur when the snippet is invoked. Similarly, if a form
|
||||||
|
* parameter is documented, is not marked as optional, and is not present in the
|
||||||
|
* request, a failure will also occur.
|
||||||
|
* <p>
|
||||||
|
* If you do not want to document a form parameter, a parameter descriptor can be
|
||||||
|
* marked as {@link ParameterDescriptor#ignored()}. This will prevent it from
|
||||||
|
* appearing in the generated snippet while avoiding the failure described above.
|
||||||
|
* @param attributes the attributes
|
||||||
|
* @param descriptors the descriptions of the request's form parameters
|
||||||
|
* @return the snippet that will document the form parameters
|
||||||
|
* @since 3.0.0
|
||||||
|
*/
|
||||||
|
public static FormParametersSnippet formParameters(Map<String, Object> attributes,
|
||||||
|
ParameterDescriptor... descriptors) {
|
||||||
|
return formParameters(attributes, Arrays.asList(descriptors));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a {@code Snippet} that will document the form parameters from the API
|
||||||
|
* operation's request. The given {@code attributes} will be available during snippet
|
||||||
|
* rendering and the form parameters will be documented using the given
|
||||||
|
* {@code descriptors} .
|
||||||
|
* <p>
|
||||||
|
* If a form parameter is present in the request, but is not documented by one of the
|
||||||
|
* descriptors, a failure will occur when the snippet is invoked. Similarly, if a form
|
||||||
|
* parameter is documented, is not marked as optional, and is not present in the
|
||||||
|
* request, a failure will also occur.
|
||||||
|
* <p>
|
||||||
|
* If you do not want to document a form parameter, a parameter descriptor can be
|
||||||
|
* marked as {@link ParameterDescriptor#ignored()}. This will prevent it from
|
||||||
|
* appearing in the generated snippet while avoiding the failure described above.
|
||||||
|
* @param attributes the attributes
|
||||||
|
* @param descriptors the descriptions of the request's form parameters
|
||||||
|
* @return the snippet that will document the form parameters
|
||||||
|
* @since 3.0.0
|
||||||
|
*/
|
||||||
|
public static FormParametersSnippet formParameters(Map<String, Object> attributes,
|
||||||
List<ParameterDescriptor> descriptors) {
|
List<ParameterDescriptor> descriptors) {
|
||||||
return new RequestParametersSnippet(descriptors, attributes, true);
|
return new FormParametersSnippet(descriptors, attributes);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a {@code Snippet} that will document the form parameters from the API
|
||||||
|
* operation's request. The given {@code attributes} will be available during snippet
|
||||||
|
* rendering and the form parameters will be documented using the given
|
||||||
|
* {@code descriptors} .
|
||||||
|
* <p>
|
||||||
|
* If a form parameter is documented, is not marked as optional, and is not present in
|
||||||
|
* the response, a failure will occur. Any undocumented form parameters will be
|
||||||
|
* ignored.
|
||||||
|
* @param attributes the attributes
|
||||||
|
* @param descriptors the descriptions of the request's form parameters
|
||||||
|
* @return the snippet that will document the form parameters
|
||||||
|
* @since 3.0.0
|
||||||
|
*/
|
||||||
|
public static FormParametersSnippet relaxedFormParameters(Map<String, Object> attributes,
|
||||||
|
ParameterDescriptor... descriptors) {
|
||||||
|
return relaxedFormParameters(attributes, Arrays.asList(descriptors));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a {@code Snippet} that will document the form parameters from the API
|
||||||
|
* operation's request. The given {@code attributes} will be available during snippet
|
||||||
|
* rendering and the form parameters will be documented using the given
|
||||||
|
* {@code descriptors} .
|
||||||
|
* <p>
|
||||||
|
* If a form parameter is documented, is not marked as optional, and is not present in
|
||||||
|
* the response, a failure will occur. Any undocumented form parameters will be
|
||||||
|
* ignored.
|
||||||
|
* @param attributes the attributes
|
||||||
|
* @param descriptors the descriptions of the request's form parameters
|
||||||
|
* @return the snippet that will document the form parameters
|
||||||
|
* @since 3.0.0
|
||||||
|
*/
|
||||||
|
public static FormParametersSnippet relaxedFormParameters(Map<String, Object> attributes,
|
||||||
|
List<ParameterDescriptor> descriptors) {
|
||||||
|
return new FormParametersSnippet(descriptors, attributes, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -482,7 +644,6 @@ public abstract class RequestDocumentation {
|
|||||||
* @param attributes the attributes
|
* @param attributes the attributes
|
||||||
* @param descriptors the descriptions of the request's parts
|
* @param descriptors the descriptions of the request's parts
|
||||||
* @return the snippet
|
* @return the snippet
|
||||||
* @see OperationRequest#getParameters()
|
|
||||||
*/
|
*/
|
||||||
public static RequestPartsSnippet relaxedRequestParts(Map<String, Object> attributes,
|
public static RequestPartsSnippet relaxedRequestParts(Map<String, Object> attributes,
|
||||||
RequestPartDescriptor... descriptors) {
|
RequestPartDescriptor... descriptors) {
|
||||||
@@ -499,7 +660,6 @@ public abstract class RequestDocumentation {
|
|||||||
* @param attributes the attributes
|
* @param attributes the attributes
|
||||||
* @param descriptors the descriptions of the request's parts
|
* @param descriptors the descriptions of the request's parts
|
||||||
* @return the snippet
|
* @return the snippet
|
||||||
* @see OperationRequest#getParameters()
|
|
||||||
*/
|
*/
|
||||||
public static RequestPartsSnippet relaxedRequestParts(Map<String, Object> attributes,
|
public static RequestPartsSnippet relaxedRequestParts(Map<String, Object> attributes,
|
||||||
List<RequestPartDescriptor> descriptors) {
|
List<RequestPartDescriptor> descriptors) {
|
||||||
|
|||||||
@@ -0,0 +1,9 @@
|
|||||||
|
|===
|
||||||
|
|Parameter|Description
|
||||||
|
|
||||||
|
{{#parameters}}
|
||||||
|
|{{#tableCellContent}}`+{{name}}+`{{/tableCellContent}}
|
||||||
|
|{{#tableCellContent}}{{description}}{{/tableCellContent}}
|
||||||
|
|
||||||
|
{{/parameters}}
|
||||||
|
|===
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
|===
|
||||||
|
|Parameter|Description
|
||||||
|
|
||||||
|
{{#parameters}}
|
||||||
|
|{{#tableCellContent}}`+{{name}}+`{{/tableCellContent}}
|
||||||
|
|{{#tableCellContent}}{{description}}{{/tableCellContent}}
|
||||||
|
|
||||||
|
{{/parameters}}
|
||||||
|
|===
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
Parameter | Description
|
||||||
|
--------- | -----------
|
||||||
|
{{#parameters}}
|
||||||
|
`{{name}}` | {{description}}
|
||||||
|
{{/parameters}}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
Parameter | Description
|
||||||
|
--------- | -----------
|
||||||
|
{{#parameters}}
|
||||||
|
`{{name}}` | {{description}}
|
||||||
|
{{/parameters}}
|
||||||
@@ -57,14 +57,6 @@ public class CurlRequestSnippetTests extends AbstractSnippetTests {
|
|||||||
.is(codeBlock("bash").withContent("$ curl 'http://localhost/foo' -i -X GET"));
|
.is(codeBlock("bash").withContent("$ curl 'http://localhost/foo' -i -X GET"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
public void getRequestWithParameter() throws IOException {
|
|
||||||
new CurlRequestSnippet(this.commandFormatter)
|
|
||||||
.document(this.operationBuilder.request("http://localhost/foo").param("a", "alpha").build());
|
|
||||||
assertThat(this.generatedSnippets.curlRequest())
|
|
||||||
.is(codeBlock("bash").withContent("$ curl 'http://localhost/foo?a=alpha' -i -X GET"));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void nonGetRequest() throws IOException {
|
public void nonGetRequest() throws IOException {
|
||||||
new CurlRequestSnippet(this.commandFormatter)
|
new CurlRequestSnippet(this.commandFormatter)
|
||||||
@@ -89,30 +81,6 @@ public class CurlRequestSnippetTests extends AbstractSnippetTests {
|
|||||||
.is(codeBlock("bash").withContent("$ curl 'http://localhost/foo?param=value' -i -X GET"));
|
.is(codeBlock("bash").withContent("$ curl 'http://localhost/foo?param=value' -i -X GET"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
public void getRequestWithTotallyOverlappingQueryStringAndParameters() throws IOException {
|
|
||||||
new CurlRequestSnippet(this.commandFormatter).document(
|
|
||||||
this.operationBuilder.request("http://localhost/foo?param=value").param("param", "value").build());
|
|
||||||
assertThat(this.generatedSnippets.curlRequest())
|
|
||||||
.is(codeBlock("bash").withContent("$ curl 'http://localhost/foo?param=value' -i -X GET"));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void getRequestWithPartiallyOverlappingQueryStringAndParameters() throws IOException {
|
|
||||||
new CurlRequestSnippet(this.commandFormatter).document(this.operationBuilder
|
|
||||||
.request("http://localhost/foo?a=alpha").param("a", "alpha").param("b", "bravo").build());
|
|
||||||
assertThat(this.generatedSnippets.curlRequest())
|
|
||||||
.is(codeBlock("bash").withContent("$ curl 'http://localhost/foo?a=alpha&b=bravo' -i -X GET"));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void getRequestWithDisjointQueryStringAndParameters() throws IOException {
|
|
||||||
new CurlRequestSnippet(this.commandFormatter)
|
|
||||||
.document(this.operationBuilder.request("http://localhost/foo?a=alpha").param("b", "bravo").build());
|
|
||||||
assertThat(this.generatedSnippets.curlRequest())
|
|
||||||
.is(codeBlock("bash").withContent("$ curl 'http://localhost/foo?a=alpha&b=bravo' -i -X GET"));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void getRequestWithQueryStringWithNoValue() throws IOException {
|
public void getRequestWithQueryStringWithNoValue() throws IOException {
|
||||||
new CurlRequestSnippet(this.commandFormatter)
|
new CurlRequestSnippet(this.commandFormatter)
|
||||||
@@ -140,7 +108,16 @@ public class CurlRequestSnippetTests extends AbstractSnippetTests {
|
|||||||
@Test
|
@Test
|
||||||
public void postRequestWithOneParameter() throws IOException {
|
public void postRequestWithOneParameter() throws IOException {
|
||||||
new CurlRequestSnippet(this.commandFormatter).document(
|
new CurlRequestSnippet(this.commandFormatter).document(
|
||||||
this.operationBuilder.request("http://localhost/foo").method("POST").param("k1", "v1").build());
|
this.operationBuilder.request("http://localhost/foo").method("POST").content("k1=v1").build());
|
||||||
|
assertThat(this.generatedSnippets.curlRequest())
|
||||||
|
.is(codeBlock("bash").withContent("$ curl 'http://localhost/foo' -i -X POST -d 'k1=v1'"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void postRequestWithOneParameterAndExplicitContentType() throws IOException {
|
||||||
|
new CurlRequestSnippet(this.commandFormatter).document(this.operationBuilder.request("http://localhost/foo")
|
||||||
|
.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_FORM_URLENCODED_VALUE).method("POST")
|
||||||
|
.content("k1=v1").build());
|
||||||
assertThat(this.generatedSnippets.curlRequest())
|
assertThat(this.generatedSnippets.curlRequest())
|
||||||
.is(codeBlock("bash").withContent("$ curl 'http://localhost/foo' -i -X POST -d 'k1=v1'"));
|
.is(codeBlock("bash").withContent("$ curl 'http://localhost/foo' -i -X POST -d 'k1=v1'"));
|
||||||
}
|
}
|
||||||
@@ -148,7 +125,7 @@ public class CurlRequestSnippetTests extends AbstractSnippetTests {
|
|||||||
@Test
|
@Test
|
||||||
public void postRequestWithOneParameterWithNoValue() throws IOException {
|
public void postRequestWithOneParameterWithNoValue() throws IOException {
|
||||||
new CurlRequestSnippet(this.commandFormatter)
|
new CurlRequestSnippet(this.commandFormatter)
|
||||||
.document(this.operationBuilder.request("http://localhost/foo").method("POST").param("k1").build());
|
.document(this.operationBuilder.request("http://localhost/foo").method("POST").content("k1=").build());
|
||||||
assertThat(this.generatedSnippets.curlRequest())
|
assertThat(this.generatedSnippets.curlRequest())
|
||||||
.is(codeBlock("bash").withContent("$ curl 'http://localhost/foo' -i -X POST -d 'k1='"));
|
.is(codeBlock("bash").withContent("$ curl 'http://localhost/foo' -i -X POST -d 'k1='"));
|
||||||
}
|
}
|
||||||
@@ -156,7 +133,7 @@ public class CurlRequestSnippetTests extends AbstractSnippetTests {
|
|||||||
@Test
|
@Test
|
||||||
public void postRequestWithMultipleParameters() throws IOException {
|
public void postRequestWithMultipleParameters() throws IOException {
|
||||||
new CurlRequestSnippet(this.commandFormatter).document(this.operationBuilder.request("http://localhost/foo")
|
new CurlRequestSnippet(this.commandFormatter).document(this.operationBuilder.request("http://localhost/foo")
|
||||||
.method("POST").param("k1", "v1", "v1-bis").param("k2", "v2").build());
|
.method("POST").content("k1=v1&k1=v1-bis&k2=v2").build());
|
||||||
assertThat(this.generatedSnippets.curlRequest()).is(codeBlock("bash")
|
assertThat(this.generatedSnippets.curlRequest()).is(codeBlock("bash")
|
||||||
.withContent("$ curl 'http://localhost/foo' -i -X POST" + " -d 'k1=v1&k1=v1-bis&k2=v2'"));
|
.withContent("$ curl 'http://localhost/foo' -i -X POST" + " -d 'k1=v1&k1=v1-bis&k2=v2'"));
|
||||||
}
|
}
|
||||||
@@ -164,52 +141,24 @@ public class CurlRequestSnippetTests extends AbstractSnippetTests {
|
|||||||
@Test
|
@Test
|
||||||
public void postRequestWithUrlEncodedParameter() throws IOException {
|
public void postRequestWithUrlEncodedParameter() throws IOException {
|
||||||
new CurlRequestSnippet(this.commandFormatter).document(
|
new CurlRequestSnippet(this.commandFormatter).document(
|
||||||
this.operationBuilder.request("http://localhost/foo").method("POST").param("k1", "a&b").build());
|
this.operationBuilder.request("http://localhost/foo").method("POST").content("k1=a%26b").build());
|
||||||
assertThat(this.generatedSnippets.curlRequest())
|
assertThat(this.generatedSnippets.curlRequest())
|
||||||
.is(codeBlock("bash").withContent("$ curl 'http://localhost/foo' -i -X POST -d 'k1=a%26b'"));
|
.is(codeBlock("bash").withContent("$ curl 'http://localhost/foo' -i -X POST -d 'k1=a%26b'"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void postRequestWithDisjointQueryStringAndParameter() throws IOException {
|
public void postRequestWithJsonData() throws IOException {
|
||||||
new CurlRequestSnippet(this.commandFormatter).document(this.operationBuilder
|
new CurlRequestSnippet(this.commandFormatter).document(this.operationBuilder.request("http://localhost/foo")
|
||||||
.request("http://localhost/foo?a=alpha").method("POST").param("b", "bravo").build());
|
.method("POST").header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
|
||||||
assertThat(this.generatedSnippets.curlRequest())
|
.content("{\"a\":\"alpha\"}").build());
|
||||||
.is(codeBlock("bash").withContent("$ curl 'http://localhost/foo?a=alpha' -i -X POST -d 'b=bravo'"));
|
assertThat(this.generatedSnippets.curlRequest()).is(codeBlock("bash").withContent(
|
||||||
}
|
"$ curl 'http://localhost/foo' -i -X POST -H 'Content-Type: application/json' -d '{\"a\":\"alpha\"}'"));
|
||||||
|
|
||||||
@Test
|
|
||||||
public void postRequestWithTotallyOverlappingQueryStringAndParameters() throws IOException {
|
|
||||||
new CurlRequestSnippet(this.commandFormatter)
|
|
||||||
.document(this.operationBuilder.request("http://localhost/foo?a=alpha&b=bravo").method("POST")
|
|
||||||
.param("a", "alpha").param("b", "bravo").build());
|
|
||||||
assertThat(this.generatedSnippets.curlRequest())
|
|
||||||
.is(codeBlock("bash").withContent("$ curl 'http://localhost/foo?a=alpha&b=bravo' -i -X POST"));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void postRequestWithPartiallyOverlappingQueryStringAndParameters() throws IOException {
|
|
||||||
new CurlRequestSnippet(this.commandFormatter)
|
|
||||||
.document(this.operationBuilder.request("http://localhost/foo?a=alpha").method("POST")
|
|
||||||
.param("a", "alpha").param("b", "bravo").build());
|
|
||||||
assertThat(this.generatedSnippets.curlRequest())
|
|
||||||
.is(codeBlock("bash").withContent("$ curl 'http://localhost/foo?a=alpha' -i -X POST -d 'b=bravo'"));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void postRequestWithOverlappingParametersAndFormUrlEncodedBody() throws IOException {
|
|
||||||
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());
|
|
||||||
assertThat(this.generatedSnippets.curlRequest())
|
|
||||||
.is(codeBlock("bash").withContent("$ curl 'http://localhost/foo' -i -X POST "
|
|
||||||
+ "-H 'Content-Type: application/x-www-form-urlencoded' " + "-d 'a=alpha&b=bravo'"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void putRequestWithOneParameter() throws IOException {
|
public void putRequestWithOneParameter() throws IOException {
|
||||||
new CurlRequestSnippet(this.commandFormatter).document(
|
new CurlRequestSnippet(this.commandFormatter)
|
||||||
this.operationBuilder.request("http://localhost/foo").method("PUT").param("k1", "v1").build());
|
.document(this.operationBuilder.request("http://localhost/foo").method("PUT").content("k1=v1").build());
|
||||||
assertThat(this.generatedSnippets.curlRequest())
|
assertThat(this.generatedSnippets.curlRequest())
|
||||||
.is(codeBlock("bash").withContent("$ curl 'http://localhost/foo' -i -X PUT -d 'k1=v1'"));
|
.is(codeBlock("bash").withContent("$ curl 'http://localhost/foo' -i -X PUT -d 'k1=v1'"));
|
||||||
}
|
}
|
||||||
@@ -217,7 +166,7 @@ public class CurlRequestSnippetTests extends AbstractSnippetTests {
|
|||||||
@Test
|
@Test
|
||||||
public void putRequestWithMultipleParameters() throws IOException {
|
public void putRequestWithMultipleParameters() throws IOException {
|
||||||
new CurlRequestSnippet(this.commandFormatter).document(this.operationBuilder.request("http://localhost/foo")
|
new CurlRequestSnippet(this.commandFormatter).document(this.operationBuilder.request("http://localhost/foo")
|
||||||
.method("PUT").param("k1", "v1").param("k1", "v1-bis").param("k2", "v2").build());
|
.method("PUT").content("k1=v1&k1=v1-bis&k2=v2").build());
|
||||||
assertThat(this.generatedSnippets.curlRequest()).is(codeBlock("bash")
|
assertThat(this.generatedSnippets.curlRequest()).is(codeBlock("bash")
|
||||||
.withContent("$ curl 'http://localhost/foo' -i -X PUT" + " -d 'k1=v1&k1=v1-bis&k2=v2'"));
|
.withContent("$ curl 'http://localhost/foo' -i -X PUT" + " -d 'k1=v1&k1=v1-bis&k2=v2'"));
|
||||||
}
|
}
|
||||||
@@ -225,7 +174,7 @@ public class CurlRequestSnippetTests extends AbstractSnippetTests {
|
|||||||
@Test
|
@Test
|
||||||
public void putRequestWithUrlEncodedParameter() throws IOException {
|
public void putRequestWithUrlEncodedParameter() throws IOException {
|
||||||
new CurlRequestSnippet(this.commandFormatter).document(
|
new CurlRequestSnippet(this.commandFormatter).document(
|
||||||
this.operationBuilder.request("http://localhost/foo").method("PUT").param("k1", "a&b").build());
|
this.operationBuilder.request("http://localhost/foo").method("PUT").content("k1=a%26b").build());
|
||||||
assertThat(this.generatedSnippets.curlRequest())
|
assertThat(this.generatedSnippets.curlRequest())
|
||||||
.is(codeBlock("bash").withContent("$ curl 'http://localhost/foo' -i -X PUT -d 'k1=a%26b'"));
|
.is(codeBlock("bash").withContent("$ curl 'http://localhost/foo' -i -X PUT -d 'k1=a%26b'"));
|
||||||
}
|
}
|
||||||
@@ -287,29 +236,6 @@ public class CurlRequestSnippetTests extends AbstractSnippetTests {
|
|||||||
assertThat(this.generatedSnippets.curlRequest()).is(codeBlock("bash").withContent(expectedContent));
|
assertThat(this.generatedSnippets.curlRequest()).is(codeBlock("bash").withContent(expectedContent));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
public void multipartPostWithParameters() throws IOException {
|
|
||||||
new CurlRequestSnippet(this.commandFormatter).document(this.operationBuilder.request("http://localhost/upload")
|
|
||||||
.method("POST").header(HttpHeaders.CONTENT_TYPE, MediaType.MULTIPART_FORM_DATA_VALUE)
|
|
||||||
.part("image", new byte[0]).submittedFileName("documents/images/example.png").and()
|
|
||||||
.param("a", "apple", "avocado").param("b", "banana").build());
|
|
||||||
String expectedContent = "$ curl 'http://localhost/upload' -i -X POST -H "
|
|
||||||
+ "'Content-Type: multipart/form-data' -F "
|
|
||||||
+ "'image=@documents/images/example.png' -F 'a=apple' -F 'a=avocado' " + "-F 'b=banana'";
|
|
||||||
assertThat(this.generatedSnippets.curlRequest()).is(codeBlock("bash").withContent(expectedContent));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void multipartPostWithOverlappingPartsAndParameters() throws IOException {
|
|
||||||
new CurlRequestSnippet(this.commandFormatter).document(this.operationBuilder.request("http://localhost/upload")
|
|
||||||
.method("POST").header(HttpHeaders.CONTENT_TYPE, MediaType.MULTIPART_FORM_DATA_VALUE)
|
|
||||||
.part("image", new byte[0]).submittedFileName("documents/images/example.png").and()
|
|
||||||
.part("a", "apple".getBytes()).and().param("a", "apple").build());
|
|
||||||
String expectedContent = "$ curl 'http://localhost/upload' -i -X POST -H "
|
|
||||||
+ "'Content-Type: multipart/form-data' -F 'image=@documents/images/example.png' -F 'a=apple'";
|
|
||||||
assertThat(this.generatedSnippets.curlRequest()).is(codeBlock("bash").withContent(expectedContent));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void basicAuthCredentialsAreSuppliedUsingUserOption() throws IOException {
|
public void basicAuthCredentialsAreSuppliedUsingUserOption() throws IOException {
|
||||||
new CurlRequestSnippet(this.commandFormatter).document(this.operationBuilder.request("http://localhost/foo")
|
new CurlRequestSnippet(this.commandFormatter).document(this.operationBuilder.request("http://localhost/foo")
|
||||||
@@ -329,22 +255,6 @@ public class CurlRequestSnippetTests extends AbstractSnippetTests {
|
|||||||
+ " -H 'Content-Type: application/json' -H 'a: alpha'"));
|
+ " -H 'Content-Type: application/json' -H 'a: alpha'"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
public void postWithContentAndParameters() throws IOException {
|
|
||||||
new CurlRequestSnippet(this.commandFormatter).document(this.operationBuilder.request("http://localhost/foo")
|
|
||||||
.param("a", "alpha").method("POST").param("b", "bravo").content("Some content").build());
|
|
||||||
assertThat(this.generatedSnippets.curlRequest()).is(codeBlock("bash")
|
|
||||||
.withContent("$ curl 'http://localhost/foo?a=alpha&b=bravo' -i " + "-X POST -d 'Some content'"));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void deleteWithParameters() throws IOException {
|
|
||||||
new CurlRequestSnippet(this.commandFormatter).document(this.operationBuilder.request("http://localhost/foo")
|
|
||||||
.method("DELETE").param("a", "alpha").param("b", "bravo").build());
|
|
||||||
assertThat(this.generatedSnippets.curlRequest())
|
|
||||||
.is(codeBlock("bash").withContent("$ curl 'http://localhost/foo?a=alpha&b=bravo' -i " + "-X DELETE"));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void deleteWithQueryString() throws IOException {
|
public void deleteWithQueryString() throws IOException {
|
||||||
new CurlRequestSnippet(this.commandFormatter).document(
|
new CurlRequestSnippet(this.commandFormatter).document(
|
||||||
|
|||||||
@@ -58,14 +58,6 @@ public class HttpieRequestSnippetTests extends AbstractSnippetTests {
|
|||||||
.is(codeBlock("bash").withContent("$ http GET 'http://localhost/foo'"));
|
.is(codeBlock("bash").withContent("$ http GET 'http://localhost/foo'"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
public void getRequestWithParameter() throws IOException {
|
|
||||||
new HttpieRequestSnippet(this.commandFormatter)
|
|
||||||
.document(this.operationBuilder.request("http://localhost/foo").param("a", "alpha").build());
|
|
||||||
assertThat(this.generatedSnippets.httpieRequest())
|
|
||||||
.is(codeBlock("bash").withContent("$ http GET 'http://localhost/foo?a=alpha'"));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void nonGetRequest() throws IOException {
|
public void nonGetRequest() throws IOException {
|
||||||
new HttpieRequestSnippet(this.commandFormatter)
|
new HttpieRequestSnippet(this.commandFormatter)
|
||||||
@@ -90,30 +82,6 @@ public class HttpieRequestSnippetTests extends AbstractSnippetTests {
|
|||||||
.is(codeBlock("bash").withContent("$ http GET 'http://localhost/foo?param=value'"));
|
.is(codeBlock("bash").withContent("$ http GET 'http://localhost/foo?param=value'"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
public void getRequestWithTotallyOverlappingQueryStringAndParameters() throws IOException {
|
|
||||||
new HttpieRequestSnippet(this.commandFormatter).document(
|
|
||||||
this.operationBuilder.request("http://localhost/foo?param=value").param("param", "value").build());
|
|
||||||
assertThat(this.generatedSnippets.httpieRequest())
|
|
||||||
.is(codeBlock("bash").withContent("$ http GET 'http://localhost/foo?param=value'"));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void getRequestWithPartiallyOverlappingQueryStringAndParameters() throws IOException {
|
|
||||||
new HttpieRequestSnippet(this.commandFormatter).document(this.operationBuilder
|
|
||||||
.request("http://localhost/foo?a=alpha").param("a", "alpha").param("b", "bravo").build());
|
|
||||||
assertThat(this.generatedSnippets.httpieRequest())
|
|
||||||
.is(codeBlock("bash").withContent("$ http GET 'http://localhost/foo?a=alpha&b=bravo'"));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void getRequestWithDisjointQueryStringAndParameters() throws IOException {
|
|
||||||
new HttpieRequestSnippet(this.commandFormatter)
|
|
||||||
.document(this.operationBuilder.request("http://localhost/foo?a=alpha").param("b", "bravo").build());
|
|
||||||
assertThat(this.generatedSnippets.httpieRequest())
|
|
||||||
.is(codeBlock("bash").withContent("$ http GET 'http://localhost/foo?a=alpha&b=bravo'"));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void getRequestWithQueryStringWithNoValue() throws IOException {
|
public void getRequestWithQueryStringWithNoValue() throws IOException {
|
||||||
new HttpieRequestSnippet(this.commandFormatter)
|
new HttpieRequestSnippet(this.commandFormatter)
|
||||||
@@ -140,16 +108,18 @@ public class HttpieRequestSnippetTests extends AbstractSnippetTests {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void postRequestWithOneParameter() throws IOException {
|
public void postRequestWithOneParameter() throws IOException {
|
||||||
new HttpieRequestSnippet(this.commandFormatter).document(
|
new HttpieRequestSnippet(this.commandFormatter).document(this.operationBuilder.request("http://localhost/foo")
|
||||||
this.operationBuilder.request("http://localhost/foo").method("POST").param("k1", "v1").build());
|
.method("POST").header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_FORM_URLENCODED_VALUE)
|
||||||
|
.content("k1=v1").build());
|
||||||
assertThat(this.generatedSnippets.httpieRequest())
|
assertThat(this.generatedSnippets.httpieRequest())
|
||||||
.is(codeBlock("bash").withContent("$ http --form POST 'http://localhost/foo' 'k1=v1'"));
|
.is(codeBlock("bash").withContent("$ http --form POST 'http://localhost/foo' 'k1=v1'"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void postRequestWithOneParameterWithNoValue() throws IOException {
|
public void postRequestWithOneParameterWithNoValue() throws IOException {
|
||||||
new HttpieRequestSnippet(this.commandFormatter)
|
new HttpieRequestSnippet(this.commandFormatter).document(this.operationBuilder.request("http://localhost/foo")
|
||||||
.document(this.operationBuilder.request("http://localhost/foo").method("POST").param("k1").build());
|
.method("POST").header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_FORM_URLENCODED_VALUE)
|
||||||
|
.content("k1").build());
|
||||||
assertThat(this.generatedSnippets.httpieRequest())
|
assertThat(this.generatedSnippets.httpieRequest())
|
||||||
.is(codeBlock("bash").withContent("$ http --form POST 'http://localhost/foo' 'k1='"));
|
.is(codeBlock("bash").withContent("$ http --form POST 'http://localhost/foo' 'k1='"));
|
||||||
}
|
}
|
||||||
@@ -157,60 +127,26 @@ public class HttpieRequestSnippetTests extends AbstractSnippetTests {
|
|||||||
@Test
|
@Test
|
||||||
public void postRequestWithMultipleParameters() throws IOException {
|
public void postRequestWithMultipleParameters() throws IOException {
|
||||||
new HttpieRequestSnippet(this.commandFormatter).document(this.operationBuilder.request("http://localhost/foo")
|
new HttpieRequestSnippet(this.commandFormatter).document(this.operationBuilder.request("http://localhost/foo")
|
||||||
.method("POST").param("k1", "v1", "v1-bis").param("k2", "v2").build());
|
.method("POST").header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_FORM_URLENCODED_VALUE)
|
||||||
assertThat(this.generatedSnippets.httpieRequest()).is(codeBlock("bash")
|
.content("k1=v1&k1=v1-bis&k2=v2").build());
|
||||||
.withContent("$ http --form POST 'http://localhost/foo'" + " 'k1=v1' 'k1=v1-bis' 'k2=v2'"));
|
assertThat(this.generatedSnippets.httpieRequest()).is(
|
||||||
|
codeBlock("bash").withContent("$ http --form POST 'http://localhost/foo' 'k1=v1' 'k1=v1-bis' 'k2=v2'"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void postRequestWithUrlEncodedParameter() throws IOException {
|
public void postRequestWithUrlEncodedParameter() throws IOException {
|
||||||
new HttpieRequestSnippet(this.commandFormatter).document(
|
new HttpieRequestSnippet(this.commandFormatter).document(this.operationBuilder.request("http://localhost/foo")
|
||||||
this.operationBuilder.request("http://localhost/foo").method("POST").param("k1", "a&b").build());
|
.method("POST").header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_FORM_URLENCODED_VALUE)
|
||||||
|
.content("k1=a%26b").build());
|
||||||
assertThat(this.generatedSnippets.httpieRequest())
|
assertThat(this.generatedSnippets.httpieRequest())
|
||||||
.is(codeBlock("bash").withContent("$ http --form POST 'http://localhost/foo' 'k1=a&b'"));
|
.is(codeBlock("bash").withContent("$ http --form POST 'http://localhost/foo' 'k1=a&b'"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
public void postRequestWithDisjointQueryStringAndParameter() throws IOException {
|
|
||||||
new HttpieRequestSnippet(this.commandFormatter).document(this.operationBuilder
|
|
||||||
.request("http://localhost/foo?a=alpha").method("POST").param("b", "bravo").build());
|
|
||||||
assertThat(this.generatedSnippets.httpieRequest())
|
|
||||||
.is(codeBlock("bash").withContent("$ http --form POST 'http://localhost/foo?a=alpha' 'b=bravo'"));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void postRequestWithTotallyOverlappingQueryStringAndParameters() throws IOException {
|
|
||||||
new HttpieRequestSnippet(this.commandFormatter)
|
|
||||||
.document(this.operationBuilder.request("http://localhost/foo?a=alpha&b=bravo").method("POST")
|
|
||||||
.param("a", "alpha").param("b", "bravo").build());
|
|
||||||
assertThat(this.generatedSnippets.httpieRequest())
|
|
||||||
.is(codeBlock("bash").withContent("$ http POST 'http://localhost/foo?a=alpha&b=bravo'"));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void postRequestWithPartiallyOverlappingQueryStringAndParameters() throws IOException {
|
|
||||||
new HttpieRequestSnippet(this.commandFormatter)
|
|
||||||
.document(this.operationBuilder.request("http://localhost/foo?a=alpha").method("POST")
|
|
||||||
.param("a", "alpha").param("b", "bravo").build());
|
|
||||||
assertThat(this.generatedSnippets.httpieRequest())
|
|
||||||
.is(codeBlock("bash").withContent("$ http --form POST 'http://localhost/foo?a=alpha' 'b=bravo'"));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void postRequestWithOverlappingParametersAndFormUrlEncodedBody() throws IOException {
|
|
||||||
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());
|
|
||||||
assertThat(this.generatedSnippets.httpieRequest())
|
|
||||||
.is(codeBlock("bash").withContent("$ echo 'a=alpha&b=bravo' | http POST 'http://localhost/foo' "
|
|
||||||
+ "'Content-Type:application/x-www-form-urlencoded'"));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void putRequestWithOneParameter() throws IOException {
|
public void putRequestWithOneParameter() throws IOException {
|
||||||
new HttpieRequestSnippet(this.commandFormatter).document(
|
new HttpieRequestSnippet(this.commandFormatter).document(this.operationBuilder.request("http://localhost/foo")
|
||||||
this.operationBuilder.request("http://localhost/foo").method("PUT").param("k1", "v1").build());
|
.method("PUT").header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_FORM_URLENCODED_VALUE)
|
||||||
|
.content("k1=v1").build());
|
||||||
assertThat(this.generatedSnippets.httpieRequest())
|
assertThat(this.generatedSnippets.httpieRequest())
|
||||||
.is(codeBlock("bash").withContent("$ http --form PUT 'http://localhost/foo' 'k1=v1'"));
|
.is(codeBlock("bash").withContent("$ http --form PUT 'http://localhost/foo' 'k1=v1'"));
|
||||||
}
|
}
|
||||||
@@ -218,15 +154,17 @@ public class HttpieRequestSnippetTests extends AbstractSnippetTests {
|
|||||||
@Test
|
@Test
|
||||||
public void putRequestWithMultipleParameters() throws IOException {
|
public void putRequestWithMultipleParameters() throws IOException {
|
||||||
new HttpieRequestSnippet(this.commandFormatter).document(this.operationBuilder.request("http://localhost/foo")
|
new HttpieRequestSnippet(this.commandFormatter).document(this.operationBuilder.request("http://localhost/foo")
|
||||||
.method("PUT").param("k1", "v1").param("k1", "v1-bis").param("k2", "v2").build());
|
.method("PUT").header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_FORM_URLENCODED_VALUE)
|
||||||
|
.content("k1=v1&k1=v1-bis&k2=v2").build());
|
||||||
assertThat(this.generatedSnippets.httpieRequest()).is(codeBlock("bash")
|
assertThat(this.generatedSnippets.httpieRequest()).is(codeBlock("bash")
|
||||||
.withContent("$ http --form PUT 'http://localhost/foo'" + " 'k1=v1' 'k1=v1-bis' 'k2=v2'"));
|
.withContent("$ http --form PUT 'http://localhost/foo'" + " 'k1=v1' 'k1=v1-bis' 'k2=v2'"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void putRequestWithUrlEncodedParameter() throws IOException {
|
public void putRequestWithUrlEncodedParameter() throws IOException {
|
||||||
new HttpieRequestSnippet(this.commandFormatter).document(
|
new HttpieRequestSnippet(this.commandFormatter).document(this.operationBuilder.request("http://localhost/foo")
|
||||||
this.operationBuilder.request("http://localhost/foo").method("PUT").param("k1", "a&b").build());
|
.method("PUT").header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_FORM_URLENCODED_VALUE)
|
||||||
|
.content("k1=a%26b").build());
|
||||||
assertThat(this.generatedSnippets.httpieRequest())
|
assertThat(this.generatedSnippets.httpieRequest())
|
||||||
.is(codeBlock("bash").withContent("$ http --form PUT 'http://localhost/foo' 'k1=a&b'"));
|
.is(codeBlock("bash").withContent("$ http --form PUT 'http://localhost/foo' 'k1=a&b'"));
|
||||||
}
|
}
|
||||||
@@ -291,30 +229,6 @@ public class HttpieRequestSnippetTests extends AbstractSnippetTests {
|
|||||||
assertThat(this.generatedSnippets.httpieRequest()).is(codeBlock("bash").withContent(expectedContent));
|
assertThat(this.generatedSnippets.httpieRequest()).is(codeBlock("bash").withContent(expectedContent));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
public void multipartPostWithParameters() throws IOException {
|
|
||||||
new HttpieRequestSnippet(this.commandFormatter)
|
|
||||||
.document(this.operationBuilder.request("http://localhost/upload").method("POST")
|
|
||||||
.header(HttpHeaders.CONTENT_TYPE, MediaType.MULTIPART_FORM_DATA_VALUE)
|
|
||||||
.part("image", new byte[0]).submittedFileName("documents/images/example.png").and()
|
|
||||||
.param("a", "apple", "avocado").param("b", "banana").build());
|
|
||||||
String expectedContent = "$ http --multipart POST 'http://localhost/upload'"
|
|
||||||
+ " 'image'@'documents/images/example.png' 'a=apple' 'a=avocado'" + " 'b=banana'";
|
|
||||||
assertThat(this.generatedSnippets.httpieRequest()).is(codeBlock("bash").withContent(expectedContent));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void multipartPostWithOverlappingPartsAndParameters() throws IOException {
|
|
||||||
new HttpieRequestSnippet(this.commandFormatter)
|
|
||||||
.document(this.operationBuilder.request("http://localhost/upload").method("POST")
|
|
||||||
.header(HttpHeaders.CONTENT_TYPE, MediaType.MULTIPART_FORM_DATA_VALUE)
|
|
||||||
.part("image", new byte[0]).submittedFileName("documents/images/example.png").and()
|
|
||||||
.part("a", "apple".getBytes()).and().param("a", "apple").build());
|
|
||||||
String expectedContent = "$ http --multipart POST 'http://localhost/upload'"
|
|
||||||
+ " 'image'@'documents/images/example.png' 'a'='apple'";
|
|
||||||
assertThat(this.generatedSnippets.httpieRequest()).is(codeBlock("bash").withContent(expectedContent));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void basicAuthCredentialsAreSuppliedUsingAuthOption() throws IOException {
|
public void basicAuthCredentialsAreSuppliedUsingAuthOption() throws IOException {
|
||||||
new HttpieRequestSnippet(this.commandFormatter).document(this.operationBuilder.request("http://localhost/foo")
|
new HttpieRequestSnippet(this.commandFormatter).document(this.operationBuilder.request("http://localhost/foo")
|
||||||
@@ -334,22 +248,6 @@ public class HttpieRequestSnippetTests extends AbstractSnippetTests {
|
|||||||
+ " 'Content-Type:application/json' 'a:alpha'"));
|
+ " 'Content-Type:application/json' 'a:alpha'"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
public void postWithContentAndParameters() throws IOException {
|
|
||||||
new HttpieRequestSnippet(this.commandFormatter).document(this.operationBuilder.request("http://localhost/foo")
|
|
||||||
.method("POST").param("a", "alpha").param("b", "bravo").content("Some content").build());
|
|
||||||
assertThat(this.generatedSnippets.httpieRequest()).is(codeBlock("bash")
|
|
||||||
.withContent("$ echo 'Some content' | http POST " + "'http://localhost/foo?a=alpha&b=bravo'"));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void deleteWithParameters() throws IOException {
|
|
||||||
new HttpieRequestSnippet(this.commandFormatter).document(this.operationBuilder.request("http://localhost/foo")
|
|
||||||
.method("DELETE").param("a", "alpha").param("b", "bravo").build());
|
|
||||||
assertThat(this.generatedSnippets.httpieRequest())
|
|
||||||
.is(codeBlock("bash").withContent("$ http DELETE 'http://localhost/foo?a=alpha&b=bravo'"));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void deleteWithQueryString() throws IOException {
|
public void deleteWithQueryString() throws IOException {
|
||||||
new HttpieRequestSnippet(this.commandFormatter).document(
|
new HttpieRequestSnippet(this.commandFormatter).document(
|
||||||
|
|||||||
@@ -58,9 +58,9 @@ public class HttpRequestSnippetTests extends AbstractSnippetTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void getRequestWithParameters() throws IOException {
|
public void getRequestWithQueryParameters() throws IOException {
|
||||||
new HttpRequestSnippet().document(
|
new HttpRequestSnippet()
|
||||||
this.operationBuilder.request("http://localhost/foo").header("Alpha", "a").param("b", "bravo").build());
|
.document(this.operationBuilder.request("http://localhost/foo?b=bravo").header("Alpha", "a").build());
|
||||||
assertThat(this.generatedSnippets.httpRequest()).is(httpRequest(RequestMethod.GET, "/foo?b=bravo")
|
assertThat(this.generatedSnippets.httpRequest()).is(httpRequest(RequestMethod.GET, "/foo?b=bravo")
|
||||||
.header("Alpha", "a").header(HttpHeaders.HOST, "localhost"));
|
.header("Alpha", "a").header(HttpHeaders.HOST, "localhost"));
|
||||||
}
|
}
|
||||||
@@ -96,22 +96,6 @@ public class HttpRequestSnippetTests extends AbstractSnippetTests {
|
|||||||
.is(httpRequest(RequestMethod.GET, "/foo?bar").header(HttpHeaders.HOST, "localhost"));
|
.is(httpRequest(RequestMethod.GET, "/foo?bar").header(HttpHeaders.HOST, "localhost"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
public void getWithPartiallyOverlappingQueryStringAndParameters() throws IOException {
|
|
||||||
new HttpRequestSnippet().document(this.operationBuilder.request("http://localhost/foo?a=alpha")
|
|
||||||
.param("a", "alpha").param("b", "bravo").build());
|
|
||||||
assertThat(this.generatedSnippets.httpRequest())
|
|
||||||
.is(httpRequest(RequestMethod.GET, "/foo?a=alpha&b=bravo").header(HttpHeaders.HOST, "localhost"));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void getWithTotallyOverlappingQueryStringAndParameters() throws IOException {
|
|
||||||
new HttpRequestSnippet().document(this.operationBuilder.request("http://localhost/foo?a=alpha&b=bravo")
|
|
||||||
.param("a", "alpha").param("b", "bravo").build());
|
|
||||||
assertThat(this.generatedSnippets.httpRequest())
|
|
||||||
.is(httpRequest(RequestMethod.GET, "/foo?a=alpha&b=bravo").header(HttpHeaders.HOST, "localhost"));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void postRequestWithContent() throws IOException {
|
public void postRequestWithContent() throws IOException {
|
||||||
String content = "Hello, world";
|
String content = "Hello, world";
|
||||||
@@ -123,59 +107,16 @@ public class HttpRequestSnippetTests extends AbstractSnippetTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void postRequestWithContentAndParameters() throws IOException {
|
public void postRequestWithContentAndQueryParameters() throws IOException {
|
||||||
String content = "Hello, world";
|
String content = "Hello, world";
|
||||||
new HttpRequestSnippet().document(this.operationBuilder.request("http://localhost/foo").method("POST")
|
new HttpRequestSnippet().document(
|
||||||
.param("a", "alpha").content(content).build());
|
this.operationBuilder.request("http://localhost/foo?a=alpha").method("POST").content(content).build());
|
||||||
assertThat(this.generatedSnippets.httpRequest())
|
assertThat(this.generatedSnippets.httpRequest())
|
||||||
.is(httpRequest(RequestMethod.POST, "/foo?a=alpha").header(HttpHeaders.HOST, "localhost")
|
.is(httpRequest(RequestMethod.POST, "/foo?a=alpha").header(HttpHeaders.HOST, "localhost")
|
||||||
.content(content).header(HttpHeaders.CONTENT_LENGTH, content.getBytes().length));
|
.content(content).header(HttpHeaders.CONTENT_LENGTH, content.getBytes().length));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
public void postRequestWithContentAndDisjointQueryStringAndParameters() throws IOException {
|
|
||||||
String content = "Hello, world";
|
|
||||||
new HttpRequestSnippet().document(this.operationBuilder.request("http://localhost/foo?b=bravo").method("POST")
|
|
||||||
.param("a", "alpha").content(content).build());
|
|
||||||
assertThat(this.generatedSnippets.httpRequest())
|
|
||||||
.is(httpRequest(RequestMethod.POST, "/foo?b=bravo&a=alpha").header(HttpHeaders.HOST, "localhost")
|
|
||||||
.content(content).header(HttpHeaders.CONTENT_LENGTH, content.getBytes().length));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void postRequestWithContentAndPartiallyOverlappingQueryStringAndParameters() throws IOException {
|
|
||||||
String content = "Hello, world";
|
|
||||||
new HttpRequestSnippet().document(this.operationBuilder.request("http://localhost/foo?b=bravo").method("POST")
|
|
||||||
.param("a", "alpha").param("b", "bravo").content(content).build());
|
|
||||||
assertThat(this.generatedSnippets.httpRequest())
|
|
||||||
.is(httpRequest(RequestMethod.POST, "/foo?b=bravo&a=alpha").header(HttpHeaders.HOST, "localhost")
|
|
||||||
.content(content).header(HttpHeaders.CONTENT_LENGTH, content.getBytes().length));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void postRequestWithContentAndTotallyOverlappingQueryStringAndParameters() throws IOException {
|
|
||||||
String content = "Hello, world";
|
|
||||||
new HttpRequestSnippet().document(this.operationBuilder.request("http://localhost/foo?b=bravo&a=alpha")
|
|
||||||
.method("POST").param("a", "alpha").param("b", "bravo").content(content).build());
|
|
||||||
assertThat(this.generatedSnippets.httpRequest())
|
|
||||||
.is(httpRequest(RequestMethod.POST, "/foo?b=bravo&a=alpha").header(HttpHeaders.HOST, "localhost")
|
|
||||||
.content(content).header(HttpHeaders.CONTENT_LENGTH, content.getBytes().length));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void postRequestWithOverlappingParametersAndFormUrlEncodedBody() throws IOException {
|
|
||||||
String content = "a=alpha&b=bravo";
|
|
||||||
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());
|
|
||||||
assertThat(this.generatedSnippets.httpRequest()).is(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));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void postRequestWithCharset() throws IOException {
|
public void postRequestWithCharset() throws IOException {
|
||||||
String japaneseContent = "\u30b3\u30f3\u30c6\u30f3\u30c4";
|
String japaneseContent = "\u30b3\u30f3\u30c6\u30f3\u30c4";
|
||||||
@@ -187,24 +128,6 @@ public class HttpRequestSnippetTests extends AbstractSnippetTests {
|
|||||||
.header(HttpHeaders.CONTENT_LENGTH, contentBytes.length).content(japaneseContent));
|
.header(HttpHeaders.CONTENT_LENGTH, contentBytes.length).content(japaneseContent));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
public void postRequestWithParameter() throws IOException {
|
|
||||||
new HttpRequestSnippet().document(this.operationBuilder.request("http://localhost/foo").method("POST")
|
|
||||||
.param("b&r", "baz").param("a", "alpha").build());
|
|
||||||
assertThat(this.generatedSnippets.httpRequest())
|
|
||||||
.is(httpRequest(RequestMethod.POST, "/foo").header(HttpHeaders.HOST, "localhost")
|
|
||||||
.header("Content-Type", "application/x-www-form-urlencoded").content("b%26r=baz&a=alpha"));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void postRequestWithParameterWithNoValue() throws IOException {
|
|
||||||
new HttpRequestSnippet()
|
|
||||||
.document(this.operationBuilder.request("http://localhost/foo").method("POST").param("bar").build());
|
|
||||||
assertThat(this.generatedSnippets.httpRequest())
|
|
||||||
.is(httpRequest(RequestMethod.POST, "/foo").header(HttpHeaders.HOST, "localhost")
|
|
||||||
.header("Content-Type", "application/x-www-form-urlencoded").content("bar="));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void putRequestWithContent() throws IOException {
|
public void putRequestWithContent() throws IOException {
|
||||||
String content = "Hello, world";
|
String content = "Hello, world";
|
||||||
@@ -215,23 +138,6 @@ public class HttpRequestSnippetTests extends AbstractSnippetTests {
|
|||||||
.header(HttpHeaders.CONTENT_LENGTH, content.getBytes().length));
|
.header(HttpHeaders.CONTENT_LENGTH, content.getBytes().length));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
public void putRequestWithParameter() throws IOException {
|
|
||||||
new HttpRequestSnippet().document(this.operationBuilder.request("http://localhost/foo").method("PUT")
|
|
||||||
.param("b&r", "baz").param("a", "alpha").build());
|
|
||||||
assertThat(this.generatedSnippets.httpRequest())
|
|
||||||
.is(httpRequest(RequestMethod.PUT, "/foo").header(HttpHeaders.HOST, "localhost")
|
|
||||||
.header("Content-Type", "application/x-www-form-urlencoded").content("b%26r=baz&a=alpha"));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void putRequestWithTotallyOverlappingQueryStringAndParameters() throws IOException {
|
|
||||||
new HttpRequestSnippet().document(this.operationBuilder.request("http://localhost/foo?a=alpha&b=bravo")
|
|
||||||
.method("PUT").param("a", "alpha").param("b", "bravo").build());
|
|
||||||
assertThat(this.generatedSnippets.httpRequest())
|
|
||||||
.is(httpRequest(RequestMethod.PUT, "/foo?a=alpha&b=bravo").header(HttpHeaders.HOST, "localhost"));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void multipartPost() throws IOException {
|
public void multipartPost() throws IOException {
|
||||||
new HttpRequestSnippet().document(this.operationBuilder.request("http://localhost/upload").method("POST")
|
new HttpRequestSnippet().document(this.operationBuilder.request("http://localhost/upload").method("POST")
|
||||||
@@ -256,47 +162,6 @@ public class HttpRequestSnippetTests extends AbstractSnippetTests {
|
|||||||
.header(HttpHeaders.HOST, "localhost").content(expectedContent));
|
.header(HttpHeaders.HOST, "localhost").content(expectedContent));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
public void multipartPostWithParameters() throws IOException {
|
|
||||||
new HttpRequestSnippet().document(this.operationBuilder.request("http://localhost/upload").method("POST")
|
|
||||||
.header(HttpHeaders.CONTENT_TYPE, MediaType.MULTIPART_FORM_DATA_VALUE).param("a", "apple", "avocado")
|
|
||||||
.param("b", "banana").part("image", "<< data >>".getBytes()).build());
|
|
||||||
String param1Part = createPart(String.format("Content-Disposition: form-data; " + "name=a%n%napple"), false);
|
|
||||||
String param2Part = createPart(String.format("Content-Disposition: form-data; " + "name=a%n%navocado"), false);
|
|
||||||
String param3Part = createPart(String.format("Content-Disposition: form-data; " + "name=b%n%nbanana"), false);
|
|
||||||
String filePart = createPart(String.format("Content-Disposition: form-data; " + "name=image%n%n<< data >>"));
|
|
||||||
String expectedContent = param1Part + param2Part + param3Part + filePart;
|
|
||||||
assertThat(this.generatedSnippets.httpRequest()).is(httpRequest(RequestMethod.POST, "/upload")
|
|
||||||
.header("Content-Type", "multipart/form-data; boundary=" + BOUNDARY)
|
|
||||||
.header(HttpHeaders.HOST, "localhost").content(expectedContent));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void multipartPostWithOverlappingPartsAndParameters() throws IOException {
|
|
||||||
new HttpRequestSnippet().document(this.operationBuilder.request("http://localhost/upload").method("POST")
|
|
||||||
.header(HttpHeaders.CONTENT_TYPE, MediaType.MULTIPART_FORM_DATA_VALUE).param("a", "apple")
|
|
||||||
.part("a", "apple".getBytes()).and().part("image", "<< data >>".getBytes()).build());
|
|
||||||
String paramPart = createPart(String.format("Content-Disposition: form-data; " + "name=a%n%napple"), false);
|
|
||||||
String filePart = createPart(String.format("Content-Disposition: form-data; " + "name=image%n%n<< data >>"));
|
|
||||||
String expectedContent = paramPart + filePart;
|
|
||||||
assertThat(this.generatedSnippets.httpRequest()).is(httpRequest(RequestMethod.POST, "/upload")
|
|
||||||
.header("Content-Type", "multipart/form-data; boundary=" + BOUNDARY)
|
|
||||||
.header(HttpHeaders.HOST, "localhost").content(expectedContent));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void multipartPostWithParameterWithNoValue() throws IOException {
|
|
||||||
new HttpRequestSnippet().document(this.operationBuilder.request("http://localhost/upload").method("POST")
|
|
||||||
.header(HttpHeaders.CONTENT_TYPE, MediaType.MULTIPART_FORM_DATA_VALUE).param("a")
|
|
||||||
.part("image", "<< data >>".getBytes()).build());
|
|
||||||
String paramPart = createPart(String.format("Content-Disposition: form-data; " + "name=a%n"), false);
|
|
||||||
String filePart = createPart(String.format("Content-Disposition: form-data; " + "name=image%n%n<< data >>"));
|
|
||||||
String expectedContent = paramPart + filePart;
|
|
||||||
assertThat(this.generatedSnippets.httpRequest()).is(httpRequest(RequestMethod.POST, "/upload")
|
|
||||||
.header("Content-Type", "multipart/form-data; boundary=" + BOUNDARY)
|
|
||||||
.header(HttpHeaders.HOST, "localhost").content(expectedContent));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void multipartPostWithContentType() throws IOException {
|
public void multipartPostWithContentType() throws IOException {
|
||||||
new HttpRequestSnippet().document(this.operationBuilder.request("http://localhost/upload").method("POST")
|
new HttpRequestSnippet().document(this.operationBuilder.request("http://localhost/upload").method("POST")
|
||||||
@@ -328,14 +193,6 @@ public class HttpRequestSnippetTests extends AbstractSnippetTests {
|
|||||||
assertThat(this.generatedSnippets.httpRequest()).contains("Title for the request");
|
assertThat(this.generatedSnippets.httpRequest()).contains("Title for the request");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
public void deleteWithParameters() throws IOException {
|
|
||||||
new HttpRequestSnippet().document(this.operationBuilder.request("http://localhost/foo").method("DELETE")
|
|
||||||
.param("a", "alpha").param("b", "bravo").build());
|
|
||||||
assertThat(this.generatedSnippets.httpRequest())
|
|
||||||
.is(httpRequest(RequestMethod.DELETE, "/foo?a=alpha&b=bravo").header("Host", "localhost"));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void deleteWithQueryString() throws IOException {
|
public void deleteWithQueryString() throws IOException {
|
||||||
new HttpRequestSnippet().document(
|
new HttpRequestSnippet().document(
|
||||||
|
|||||||
@@ -1,75 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2014-2018 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
|
|
||||||
*
|
|
||||||
* https://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.operation;
|
|
||||||
|
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests for {@link Parameters}.
|
|
||||||
*
|
|
||||||
* @author Andy Wilkinson
|
|
||||||
*/
|
|
||||||
public class ParametersTests {
|
|
||||||
|
|
||||||
private final Parameters parameters = new Parameters();
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void queryStringForNoParameters() {
|
|
||||||
assertThat(this.parameters.toQueryString()).isEqualTo("");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void queryStringForSingleParameter() {
|
|
||||||
this.parameters.add("a", "b");
|
|
||||||
assertThat(this.parameters.toQueryString()).isEqualTo("a=b");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void queryStringForSingleParameterWithMultipleValues() {
|
|
||||||
this.parameters.add("a", "b");
|
|
||||||
this.parameters.add("a", "c");
|
|
||||||
assertThat(this.parameters.toQueryString()).isEqualTo("a=b&a=c");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void queryStringForMutipleParameters() {
|
|
||||||
this.parameters.add("a", "alpha");
|
|
||||||
this.parameters.add("b", "bravo");
|
|
||||||
assertThat(this.parameters.toQueryString()).isEqualTo("a=alpha&b=bravo");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void queryStringForParameterWithEmptyValue() {
|
|
||||||
this.parameters.add("a", "");
|
|
||||||
assertThat(this.parameters.toQueryString()).isEqualTo("a=");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void queryStringForParameterWithNullValue() {
|
|
||||||
this.parameters.add("a", null);
|
|
||||||
assertThat(this.parameters.toQueryString()).isEqualTo("a=");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void queryStringForParameterThatRequiresEncoding() {
|
|
||||||
this.parameters.add("a", "alpha&bravo");
|
|
||||||
assertThat(this.parameters.toQueryString()).isEqualTo("a=alpha%26bravo");
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,93 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2014-2019 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
|
|
||||||
*
|
|
||||||
* https://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.operation;
|
|
||||||
|
|
||||||
import java.net.URI;
|
|
||||||
import java.util.Arrays;
|
|
||||||
|
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
|
||||||
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests for {@link QueryStringParser}.
|
|
||||||
*
|
|
||||||
* @author Andy Wilkinson
|
|
||||||
*/
|
|
||||||
public class QueryStringParserTests {
|
|
||||||
|
|
||||||
private final QueryStringParser queryStringParser = new QueryStringParser();
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void noParameters() {
|
|
||||||
Parameters parameters = this.queryStringParser.parse(URI.create("http://localhost"));
|
|
||||||
assertThat(parameters.size()).isEqualTo(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void singleParameter() {
|
|
||||||
Parameters parameters = this.queryStringParser.parse(URI.create("http://localhost?a=alpha"));
|
|
||||||
assertThat(parameters.size()).isEqualTo(1);
|
|
||||||
assertThat(parameters).containsEntry("a", Arrays.asList("alpha"));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void multipleParameters() {
|
|
||||||
Parameters parameters = this.queryStringParser.parse(URI.create("http://localhost?a=alpha&b=bravo&c=charlie"));
|
|
||||||
assertThat(parameters.size()).isEqualTo(3);
|
|
||||||
assertThat(parameters).containsEntry("a", Arrays.asList("alpha"));
|
|
||||||
assertThat(parameters).containsEntry("b", Arrays.asList("bravo"));
|
|
||||||
assertThat(parameters).containsEntry("c", Arrays.asList("charlie"));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void multipleParametersWithSameKey() {
|
|
||||||
Parameters parameters = this.queryStringParser.parse(URI.create("http://localhost?a=apple&a=avocado"));
|
|
||||||
assertThat(parameters.size()).isEqualTo(1);
|
|
||||||
assertThat(parameters).containsEntry("a", Arrays.asList("apple", "avocado"));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void encoded() {
|
|
||||||
Parameters parameters = this.queryStringParser.parse(URI.create("http://localhost?a=al%26%3Dpha"));
|
|
||||||
assertThat(parameters.size()).isEqualTo(1);
|
|
||||||
assertThat(parameters).containsEntry("a", Arrays.asList("al&=pha"));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void malformedParameter() {
|
|
||||||
assertThatIllegalArgumentException()
|
|
||||||
.isThrownBy(() -> this.queryStringParser.parse(URI.create("http://localhost?a=apple=avocado")))
|
|
||||||
.withMessage("The parameter 'a=apple=avocado' is malformed");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void emptyParameter() {
|
|
||||||
Parameters parameters = this.queryStringParser.parse(URI.create("http://localhost?a="));
|
|
||||||
assertThat(parameters.size()).isEqualTo(1);
|
|
||||||
assertThat(parameters).containsEntry("a", Arrays.asList(""));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void emptyAndNotEmptyParameter() {
|
|
||||||
Parameters parameters = this.queryStringParser.parse(URI.create("http://localhost?a=&a=alpha"));
|
|
||||||
assertThat(parameters.size()).isEqualTo(1);
|
|
||||||
assertThat(parameters).containsEntry("a", Arrays.asList("", "alpha"));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2014-2019 the original author or authors.
|
* Copyright 2014-2022 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -30,7 +30,6 @@ import org.springframework.restdocs.operation.OperationRequestFactory;
|
|||||||
import org.springframework.restdocs.operation.OperationRequestPart;
|
import org.springframework.restdocs.operation.OperationRequestPart;
|
||||||
import org.springframework.restdocs.operation.OperationResponse;
|
import org.springframework.restdocs.operation.OperationResponse;
|
||||||
import org.springframework.restdocs.operation.OperationResponseFactory;
|
import org.springframework.restdocs.operation.OperationResponseFactory;
|
||||||
import org.springframework.restdocs.operation.Parameters;
|
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
@@ -59,8 +58,7 @@ public class ContentModifyingOperationPreprocessorTests {
|
|||||||
@Test
|
@Test
|
||||||
public void modifyRequestContent() {
|
public void modifyRequestContent() {
|
||||||
OperationRequest request = this.requestFactory.create(URI.create("http://localhost"), HttpMethod.GET,
|
OperationRequest request = this.requestFactory.create(URI.create("http://localhost"), HttpMethod.GET,
|
||||||
"content".getBytes(), new HttpHeaders(), new Parameters(),
|
"content".getBytes(), new HttpHeaders(), Collections.<OperationRequestPart>emptyList());
|
||||||
Collections.<OperationRequestPart>emptyList());
|
|
||||||
OperationRequest preprocessed = this.preprocessor.preprocess(request);
|
OperationRequest preprocessed = this.preprocessor.preprocess(request);
|
||||||
assertThat(preprocessed.getContent()).isEqualTo("modified".getBytes());
|
assertThat(preprocessed.getContent()).isEqualTo("modified".getBytes());
|
||||||
}
|
}
|
||||||
@@ -78,7 +76,7 @@ public class ContentModifyingOperationPreprocessorTests {
|
|||||||
HttpHeaders httpHeaders = new HttpHeaders();
|
HttpHeaders httpHeaders = new HttpHeaders();
|
||||||
httpHeaders.setContentLength(7);
|
httpHeaders.setContentLength(7);
|
||||||
OperationRequest request = this.requestFactory.create(URI.create("http://localhost"), HttpMethod.GET,
|
OperationRequest request = this.requestFactory.create(URI.create("http://localhost"), HttpMethod.GET,
|
||||||
"content".getBytes(), httpHeaders, new Parameters(), Collections.<OperationRequestPart>emptyList());
|
"content".getBytes(), httpHeaders, Collections.<OperationRequestPart>emptyList());
|
||||||
OperationRequest preprocessed = this.preprocessor.preprocess(request);
|
OperationRequest preprocessed = this.preprocessor.preprocess(request);
|
||||||
assertThat(preprocessed.getHeaders().getContentLength()).isEqualTo(8L);
|
assertThat(preprocessed.getHeaders().getContentLength()).isEqualTo(8L);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,7 +31,6 @@ import org.springframework.restdocs.operation.OperationRequest;
|
|||||||
import org.springframework.restdocs.operation.OperationRequestFactory;
|
import org.springframework.restdocs.operation.OperationRequestFactory;
|
||||||
import org.springframework.restdocs.operation.OperationResponse;
|
import org.springframework.restdocs.operation.OperationResponse;
|
||||||
import org.springframework.restdocs.operation.OperationResponseFactory;
|
import org.springframework.restdocs.operation.OperationResponseFactory;
|
||||||
import org.springframework.restdocs.operation.Parameters;
|
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
@@ -149,7 +148,7 @@ public class HeadersModifyingOperationPreprocessorTests {
|
|||||||
headersCustomizer.accept(headers);
|
headersCustomizer.accept(headers);
|
||||||
}
|
}
|
||||||
return new OperationRequestFactory().create(URI.create("http://localhost:8080"), HttpMethod.GET, new byte[0],
|
return new OperationRequestFactory().create(URI.create("http://localhost:8080"), HttpMethod.GET, new byte[0],
|
||||||
headers, new Parameters(), Collections.emptyList());
|
headers, Collections.emptyList());
|
||||||
}
|
}
|
||||||
|
|
||||||
private OperationResponse createResponse() {
|
private OperationResponse createResponse() {
|
||||||
|
|||||||
@@ -32,7 +32,6 @@ import org.springframework.restdocs.operation.OperationRequestPart;
|
|||||||
import org.springframework.restdocs.operation.OperationRequestPartFactory;
|
import org.springframework.restdocs.operation.OperationRequestPartFactory;
|
||||||
import org.springframework.restdocs.operation.OperationResponse;
|
import org.springframework.restdocs.operation.OperationResponse;
|
||||||
import org.springframework.restdocs.operation.OperationResponseFactory;
|
import org.springframework.restdocs.operation.OperationResponseFactory;
|
||||||
import org.springframework.restdocs.operation.Parameters;
|
|
||||||
import org.springframework.restdocs.operation.RequestCookie;
|
import org.springframework.restdocs.operation.RequestCookie;
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
@@ -304,41 +303,40 @@ public class UriModifyingOperationPreprocessorTests {
|
|||||||
public void resultingRequestHasCookiesFromOriginalRequst() {
|
public void resultingRequestHasCookiesFromOriginalRequst() {
|
||||||
List<RequestCookie> cookies = Arrays.asList(new RequestCookie("a", "alpha"));
|
List<RequestCookie> cookies = Arrays.asList(new RequestCookie("a", "alpha"));
|
||||||
OperationRequest request = this.requestFactory.create(URI.create("http://localhost:12345"), HttpMethod.GET,
|
OperationRequest request = this.requestFactory.create(URI.create("http://localhost:12345"), HttpMethod.GET,
|
||||||
new byte[0], new HttpHeaders(), new Parameters(), Collections.<OperationRequestPart>emptyList(),
|
new byte[0], new HttpHeaders(), Collections.<OperationRequestPart>emptyList(), cookies);
|
||||||
cookies);
|
|
||||||
OperationRequest processed = this.preprocessor.preprocess(request);
|
OperationRequest processed = this.preprocessor.preprocess(request);
|
||||||
assertThat(processed.getCookies().size()).isEqualTo(1);
|
assertThat(processed.getCookies().size()).isEqualTo(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
private OperationRequest createRequestWithUri(String uri) {
|
private OperationRequest createRequestWithUri(String uri) {
|
||||||
return this.requestFactory.create(URI.create(uri), HttpMethod.GET, new byte[0], new HttpHeaders(),
|
return this.requestFactory.create(URI.create(uri), HttpMethod.GET, new byte[0], new HttpHeaders(),
|
||||||
new Parameters(), Collections.<OperationRequestPart>emptyList());
|
Collections.<OperationRequestPart>emptyList());
|
||||||
}
|
}
|
||||||
|
|
||||||
private OperationRequest createRequestWithContent(String content) {
|
private OperationRequest createRequestWithContent(String content) {
|
||||||
return this.requestFactory.create(URI.create("http://localhost"), HttpMethod.GET, content.getBytes(),
|
return this.requestFactory.create(URI.create("http://localhost"), HttpMethod.GET, content.getBytes(),
|
||||||
new HttpHeaders(), new Parameters(), Collections.<OperationRequestPart>emptyList());
|
new HttpHeaders(), Collections.<OperationRequestPart>emptyList());
|
||||||
}
|
}
|
||||||
|
|
||||||
private OperationRequest createRequestWithHeader(String name, String value) {
|
private OperationRequest createRequestWithHeader(String name, String value) {
|
||||||
HttpHeaders headers = new HttpHeaders();
|
HttpHeaders headers = new HttpHeaders();
|
||||||
headers.add(name, value);
|
headers.add(name, value);
|
||||||
return this.requestFactory.create(URI.create("http://localhost"), HttpMethod.GET, new byte[0], headers,
|
return this.requestFactory.create(URI.create("http://localhost"), HttpMethod.GET, new byte[0], headers,
|
||||||
new Parameters(), Collections.<OperationRequestPart>emptyList());
|
Collections.<OperationRequestPart>emptyList());
|
||||||
}
|
}
|
||||||
|
|
||||||
private OperationRequest createRequestWithPartWithHeader(String name, String value) {
|
private OperationRequest createRequestWithPartWithHeader(String name, String value) {
|
||||||
HttpHeaders headers = new HttpHeaders();
|
HttpHeaders headers = new HttpHeaders();
|
||||||
headers.add(name, value);
|
headers.add(name, value);
|
||||||
return this.requestFactory.create(URI.create("http://localhost"), HttpMethod.GET, new byte[0],
|
return this.requestFactory.create(URI.create("http://localhost"), HttpMethod.GET, new byte[0],
|
||||||
new HttpHeaders(), new Parameters(),
|
new HttpHeaders(),
|
||||||
Arrays.asList(new OperationRequestPartFactory().create("part", "fileName", new byte[0], headers)));
|
Arrays.asList(new OperationRequestPartFactory().create("part", "fileName", new byte[0], headers)));
|
||||||
}
|
}
|
||||||
|
|
||||||
private OperationRequest createRequestWithPartWithContent(String content) {
|
private OperationRequest createRequestWithPartWithContent(String content) {
|
||||||
return this.requestFactory.create(URI.create("http://localhost"), HttpMethod.GET, new byte[0],
|
return this.requestFactory.create(URI.create("http://localhost"), HttpMethod.GET, new byte[0],
|
||||||
new HttpHeaders(), new Parameters(), Arrays.asList(new OperationRequestPartFactory().create("part",
|
new HttpHeaders(), Arrays.asList(new OperationRequestPartFactory().create("part", "fileName",
|
||||||
"fileName", content.getBytes(), new HttpHeaders())));
|
content.getBytes(), new HttpHeaders())));
|
||||||
}
|
}
|
||||||
|
|
||||||
private OperationResponse createResponseWithContent(String content) {
|
private OperationResponse createResponseWithContent(String content) {
|
||||||
|
|||||||
@@ -30,12 +30,12 @@ import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
|||||||
import static org.springframework.restdocs.request.RequestDocumentation.parameterWithName;
|
import static org.springframework.restdocs.request.RequestDocumentation.parameterWithName;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests for failures when rendering {@link RequestParametersSnippet} due to missing or
|
* Tests for failures when rendering {@link FormParametersSnippet} due to missing or
|
||||||
* undocumented request parameters.
|
* undocumented form parameters.
|
||||||
*
|
*
|
||||||
* @author Andy Wilkinson
|
* @author Andy Wilkinson
|
||||||
*/
|
*/
|
||||||
public class RequestParametersSnippetFailureTests {
|
public class FormParametersSnippetFailureTests {
|
||||||
|
|
||||||
@Rule
|
@Rule
|
||||||
public OperationBuilder operationBuilder = new OperationBuilder(TemplateFormats.asciidoctor());
|
public OperationBuilder operationBuilder = new OperationBuilder(TemplateFormats.asciidoctor());
|
||||||
@@ -43,25 +43,25 @@ public class RequestParametersSnippetFailureTests {
|
|||||||
@Test
|
@Test
|
||||||
public void undocumentedParameter() {
|
public void undocumentedParameter() {
|
||||||
assertThatExceptionOfType(SnippetException.class)
|
assertThatExceptionOfType(SnippetException.class)
|
||||||
.isThrownBy(() -> new RequestParametersSnippet(Collections.<ParameterDescriptor>emptyList())
|
.isThrownBy(() -> new FormParametersSnippet(Collections.<ParameterDescriptor>emptyList())
|
||||||
.document(this.operationBuilder.request("http://localhost").param("a", "alpha").build()))
|
.document(this.operationBuilder.request("http://localhost").content("a=alpha").build()))
|
||||||
.withMessage("Request parameters with the following names were not documented: [a]");
|
.withMessage("Form parameters with the following names were not documented: [a]");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void missingParameter() {
|
public void missingParameter() {
|
||||||
assertThatExceptionOfType(SnippetException.class)
|
assertThatExceptionOfType(SnippetException.class)
|
||||||
.isThrownBy(() -> new RequestParametersSnippet(Arrays.asList(parameterWithName("a").description("one")))
|
.isThrownBy(() -> new FormParametersSnippet(Arrays.asList(parameterWithName("a").description("one")))
|
||||||
.document(this.operationBuilder.request("http://localhost").build()))
|
.document(this.operationBuilder.request("http://localhost").build()))
|
||||||
.withMessage("Request parameters with the following names were not found in the request: [a]");
|
.withMessage("Form parameters with the following names were not found in the request: [a]");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void undocumentedAndMissingParameters() {
|
public void undocumentedAndMissingParameters() {
|
||||||
assertThatExceptionOfType(SnippetException.class)
|
assertThatExceptionOfType(SnippetException.class)
|
||||||
.isThrownBy(() -> new RequestParametersSnippet(Arrays.asList(parameterWithName("a").description("one")))
|
.isThrownBy(() -> new FormParametersSnippet(Arrays.asList(parameterWithName("a").description("one")))
|
||||||
.document(this.operationBuilder.request("http://localhost").param("b", "bravo").build()))
|
.document(this.operationBuilder.request("http://localhost").content("b=bravo").build()))
|
||||||
.withMessage("Request parameters with the following names were not documented: [b]. Request parameters"
|
.withMessage("Form parameters with the following names were not documented: [b]. Form parameters"
|
||||||
+ " with the following names were not found in the request: [a]");
|
+ " with the following names were not found in the request: [a]");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2014-2020 the original author or authors.
|
* Copyright 2014-2022 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -36,138 +36,134 @@ import static org.springframework.restdocs.snippet.Attributes.attributes;
|
|||||||
import static org.springframework.restdocs.snippet.Attributes.key;
|
import static org.springframework.restdocs.snippet.Attributes.key;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests for {@link RequestParametersSnippet}.
|
* Tests for {@link FormParametersSnippet}.
|
||||||
*
|
*
|
||||||
* @author Andy Wilkinson
|
* @author Andy Wilkinson
|
||||||
*/
|
*/
|
||||||
public class RequestParametersSnippetTests extends AbstractSnippetTests {
|
public class FormParametersSnippetTests extends AbstractSnippetTests {
|
||||||
|
|
||||||
public RequestParametersSnippetTests(String name, TemplateFormat templateFormat) {
|
public FormParametersSnippetTests(String name, TemplateFormat templateFormat) {
|
||||||
super(name, templateFormat);
|
super(name, templateFormat);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void requestParameters() throws IOException {
|
public void formParameters() throws IOException {
|
||||||
new RequestParametersSnippet(
|
new FormParametersSnippet(
|
||||||
Arrays.asList(parameterWithName("a").description("one"), parameterWithName("b").description("two")))
|
Arrays.asList(parameterWithName("a").description("one"), parameterWithName("b").description("two")))
|
||||||
.document(this.operationBuilder.request("http://localhost").param("a", "bravo")
|
.document(this.operationBuilder.request("http://localhost").content("a=alpha&b=bravo").build());
|
||||||
.param("b", "bravo").build());
|
assertThat(this.generatedSnippets.formParameters())
|
||||||
assertThat(this.generatedSnippets.requestParameters())
|
|
||||||
.is(tableWithHeader("Parameter", "Description").row("`a`", "one").row("`b`", "two"));
|
.is(tableWithHeader("Parameter", "Description").row("`a`", "one").row("`b`", "two"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void requestParameterWithNoValue() throws IOException {
|
public void formParameterWithNoValue() throws IOException {
|
||||||
new RequestParametersSnippet(Arrays.asList(parameterWithName("a").description("one")))
|
new FormParametersSnippet(Arrays.asList(parameterWithName("a").description("one")))
|
||||||
.document(this.operationBuilder.request("http://localhost").param("a").build());
|
.document(this.operationBuilder.request("http://localhost").content("a=").build());
|
||||||
assertThat(this.generatedSnippets.requestParameters())
|
assertThat(this.generatedSnippets.formParameters())
|
||||||
.is(tableWithHeader("Parameter", "Description").row("`a`", "one"));
|
.is(tableWithHeader("Parameter", "Description").row("`a`", "one"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void ignoredRequestParameter() throws IOException {
|
public void ignoredFormParameter() throws IOException {
|
||||||
new RequestParametersSnippet(
|
new FormParametersSnippet(
|
||||||
Arrays.asList(parameterWithName("a").ignored(), parameterWithName("b").description("two")))
|
Arrays.asList(parameterWithName("a").ignored(), parameterWithName("b").description("two")))
|
||||||
.document(this.operationBuilder.request("http://localhost").param("a", "bravo")
|
.document(this.operationBuilder.request("http://localhost").content("a=alpha&b=bravo").build());
|
||||||
.param("b", "bravo").build());
|
assertThat(this.generatedSnippets.formParameters())
|
||||||
assertThat(this.generatedSnippets.requestParameters())
|
|
||||||
.is(tableWithHeader("Parameter", "Description").row("`b`", "two"));
|
.is(tableWithHeader("Parameter", "Description").row("`b`", "two"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void allUndocumentedRequestParametersCanBeIgnored() throws IOException {
|
public void allUndocumentedFormParametersCanBeIgnored() throws IOException {
|
||||||
new RequestParametersSnippet(Arrays.asList(parameterWithName("b").description("two")), true).document(
|
new FormParametersSnippet(Arrays.asList(parameterWithName("b").description("two")), true)
|
||||||
this.operationBuilder.request("http://localhost").param("a", "bravo").param("b", "bravo").build());
|
.document(this.operationBuilder.request("http://localhost").content("a=alpha&b=bravo").build());
|
||||||
assertThat(this.generatedSnippets.requestParameters())
|
assertThat(this.generatedSnippets.formParameters())
|
||||||
.is(tableWithHeader("Parameter", "Description").row("`b`", "two"));
|
.is(tableWithHeader("Parameter", "Description").row("`b`", "two"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void missingOptionalRequestParameter() throws IOException {
|
public void missingOptionalFormParameter() throws IOException {
|
||||||
new RequestParametersSnippet(Arrays.asList(parameterWithName("a").description("one").optional(),
|
new FormParametersSnippet(Arrays.asList(parameterWithName("a").description("one").optional(),
|
||||||
parameterWithName("b").description("two")))
|
parameterWithName("b").description("two")))
|
||||||
.document(this.operationBuilder.request("http://localhost").param("b", "bravo").build());
|
.document(this.operationBuilder.request("http://localhost").content("b=bravo").build());
|
||||||
assertThat(this.generatedSnippets.requestParameters())
|
assertThat(this.generatedSnippets.formParameters())
|
||||||
.is(tableWithHeader("Parameter", "Description").row("`a`", "one").row("`b`", "two"));
|
.is(tableWithHeader("Parameter", "Description").row("`a`", "one").row("`b`", "two"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void presentOptionalRequestParameter() throws IOException {
|
public void presentOptionalFormParameter() throws IOException {
|
||||||
new RequestParametersSnippet(Arrays.asList(parameterWithName("a").description("one").optional()))
|
new FormParametersSnippet(Arrays.asList(parameterWithName("a").description("one").optional()))
|
||||||
.document(this.operationBuilder.request("http://localhost").param("a", "one").build());
|
.document(this.operationBuilder.request("http://localhost").content("a=alpha").build());
|
||||||
assertThat(this.generatedSnippets.requestParameters())
|
assertThat(this.generatedSnippets.formParameters())
|
||||||
.is(tableWithHeader("Parameter", "Description").row("`a`", "one"));
|
.is(tableWithHeader("Parameter", "Description").row("`a`", "one"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void requestParametersWithCustomAttributes() throws IOException {
|
public void formParametersWithCustomAttributes() throws IOException {
|
||||||
TemplateResourceResolver resolver = mock(TemplateResourceResolver.class);
|
TemplateResourceResolver resolver = mock(TemplateResourceResolver.class);
|
||||||
given(resolver.resolveTemplateResource("request-parameters"))
|
given(resolver.resolveTemplateResource("form-parameters"))
|
||||||
.willReturn(snippetResource("request-parameters-with-title"));
|
.willReturn(snippetResource("form-parameters-with-title"));
|
||||||
new RequestParametersSnippet(
|
new FormParametersSnippet(
|
||||||
Arrays.asList(parameterWithName("a").description("one").attributes(key("foo").value("alpha")),
|
Arrays.asList(parameterWithName("a").description("one").attributes(key("foo").value("alpha")),
|
||||||
parameterWithName("b").description("two").attributes(key("foo").value("bravo"))),
|
parameterWithName("b").description("two").attributes(key("foo").value("bravo"))),
|
||||||
attributes(key("title").value("The title")))
|
attributes(key("title").value("The title")))
|
||||||
.document(this.operationBuilder
|
.document(this.operationBuilder
|
||||||
.attribute(TemplateEngine.class.getName(), new MustacheTemplateEngine(resolver))
|
.attribute(TemplateEngine.class.getName(), new MustacheTemplateEngine(resolver))
|
||||||
.request("http://localhost").param("a", "alpha").param("b", "bravo").build());
|
.request("http://localhost").content("a=alpha&b=bravo").build());
|
||||||
assertThat(this.generatedSnippets.requestParameters()).contains("The title");
|
assertThat(this.generatedSnippets.formParameters()).contains("The title");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void requestParametersWithCustomDescriptorAttributes() throws IOException {
|
public void formParametersWithCustomDescriptorAttributes() throws IOException {
|
||||||
TemplateResourceResolver resolver = mock(TemplateResourceResolver.class);
|
TemplateResourceResolver resolver = mock(TemplateResourceResolver.class);
|
||||||
given(resolver.resolveTemplateResource("request-parameters"))
|
given(resolver.resolveTemplateResource("form-parameters"))
|
||||||
.willReturn(snippetResource("request-parameters-with-extra-column"));
|
.willReturn(snippetResource("form-parameters-with-extra-column"));
|
||||||
new RequestParametersSnippet(
|
new FormParametersSnippet(
|
||||||
Arrays.asList(parameterWithName("a").description("one").attributes(key("foo").value("alpha")),
|
Arrays.asList(parameterWithName("a").description("one").attributes(key("foo").value("alpha")),
|
||||||
parameterWithName("b").description("two").attributes(key("foo").value("bravo"))))
|
parameterWithName("b").description("two").attributes(key("foo").value("bravo"))))
|
||||||
.document(this.operationBuilder
|
.document(this.operationBuilder
|
||||||
.attribute(TemplateEngine.class.getName(), new MustacheTemplateEngine(resolver))
|
.attribute(TemplateEngine.class.getName(), new MustacheTemplateEngine(resolver))
|
||||||
.request("http://localhost").param("a", "alpha").param("b", "bravo").build());
|
.request("http://localhost").content("a=alpha&b=bravo").build());
|
||||||
assertThat(this.generatedSnippets.requestParameters()).is(
|
assertThat(this.generatedSnippets.formParameters()).is(
|
||||||
tableWithHeader("Parameter", "Description", "Foo").row("a", "one", "alpha").row("b", "two", "bravo"));
|
tableWithHeader("Parameter", "Description", "Foo").row("a", "one", "alpha").row("b", "two", "bravo"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void requestParametersWithOptionalColumn() throws IOException {
|
public void formParametersWithOptionalColumn() throws IOException {
|
||||||
TemplateResourceResolver resolver = mock(TemplateResourceResolver.class);
|
TemplateResourceResolver resolver = mock(TemplateResourceResolver.class);
|
||||||
given(resolver.resolveTemplateResource("request-parameters"))
|
given(resolver.resolveTemplateResource("form-parameters"))
|
||||||
.willReturn(snippetResource("request-parameters-with-optional-column"));
|
.willReturn(snippetResource("form-parameters-with-optional-column"));
|
||||||
new RequestParametersSnippet(Arrays.asList(parameterWithName("a").description("one").optional(),
|
new FormParametersSnippet(Arrays.asList(parameterWithName("a").description("one").optional(),
|
||||||
parameterWithName("b").description("two")))
|
parameterWithName("b").description("two")))
|
||||||
.document(this.operationBuilder
|
.document(this.operationBuilder
|
||||||
.attribute(TemplateEngine.class.getName(), new MustacheTemplateEngine(resolver))
|
.attribute(TemplateEngine.class.getName(), new MustacheTemplateEngine(resolver))
|
||||||
.request("http://localhost").param("a", "alpha").param("b", "bravo").build());
|
.request("http://localhost").content("a=alpha&b=bravo").build());
|
||||||
assertThat(this.generatedSnippets.requestParameters())
|
assertThat(this.generatedSnippets.formParameters()).is(tableWithHeader("Parameter", "Optional", "Description")
|
||||||
.is(tableWithHeader("Parameter", "Optional", "Description").row("a", "true", "one").row("b", "false",
|
.row("a", "true", "one").row("b", "false", "two"));
|
||||||
"two"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void additionalDescriptors() throws IOException {
|
public void additionalDescriptors() throws IOException {
|
||||||
RequestDocumentation.requestParameters(parameterWithName("a").description("one"))
|
RequestDocumentation.formParameters(parameterWithName("a").description("one"))
|
||||||
.and(parameterWithName("b").description("two")).document(this.operationBuilder
|
|
||||||
.request("http://localhost").param("a", "bravo").param("b", "bravo").build());
|
|
||||||
assertThat(this.generatedSnippets.requestParameters())
|
|
||||||
.is(tableWithHeader("Parameter", "Description").row("`a`", "one").row("`b`", "two"));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void additionalDescriptorsWithRelaxedRequestParameters() throws IOException {
|
|
||||||
RequestDocumentation.relaxedRequestParameters(parameterWithName("a").description("one"))
|
|
||||||
.and(parameterWithName("b").description("two"))
|
.and(parameterWithName("b").description("two"))
|
||||||
.document(this.operationBuilder.request("http://localhost").param("a", "bravo").param("b", "bravo")
|
.document(this.operationBuilder.request("http://localhost").content("a=alpha&b=bravo").build());
|
||||||
.param("c", "undocumented").build());
|
assertThat(this.generatedSnippets.formParameters())
|
||||||
assertThat(this.generatedSnippets.requestParameters())
|
|
||||||
.is(tableWithHeader("Parameter", "Description").row("`a`", "one").row("`b`", "two"));
|
.is(tableWithHeader("Parameter", "Description").row("`a`", "one").row("`b`", "two"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void requestParametersWithEscapedContent() throws IOException {
|
public void additionalDescriptorsWithRelaxedFormParameters() throws IOException {
|
||||||
RequestDocumentation.requestParameters(parameterWithName("Foo|Bar").description("one|two"))
|
RequestDocumentation.relaxedFormParameters(parameterWithName("a").description("one"))
|
||||||
.document(this.operationBuilder.request("http://localhost").param("Foo|Bar", "baz").build());
|
.and(parameterWithName("b").description("two")).document(this.operationBuilder
|
||||||
assertThat(this.generatedSnippets.requestParameters()).is(tableWithHeader("Parameter", "Description")
|
.request("http://localhost").content("a=alpha&b=bravo&c=undocumented").build());
|
||||||
|
assertThat(this.generatedSnippets.formParameters())
|
||||||
|
.is(tableWithHeader("Parameter", "Description").row("`a`", "one").row("`b`", "two"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void formParametersWithEscapedContent() throws IOException {
|
||||||
|
RequestDocumentation.formParameters(parameterWithName("Foo|Bar").description("one|two"))
|
||||||
|
.document(this.operationBuilder.request("http://localhost").content("Foo%7CBar=baz").build());
|
||||||
|
assertThat(this.generatedSnippets.formParameters()).is(tableWithHeader("Parameter", "Description")
|
||||||
.row(escapeIfNecessary("`Foo|Bar`"), escapeIfNecessary("one|two")));
|
.row(escapeIfNecessary("`Foo|Bar`"), escapeIfNecessary("one|two")));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,68 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2014-2022 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
|
||||||
|
*
|
||||||
|
* https://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.request;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
|
|
||||||
|
import org.junit.Rule;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import org.springframework.restdocs.snippet.SnippetException;
|
||||||
|
import org.springframework.restdocs.templates.TemplateFormats;
|
||||||
|
import org.springframework.restdocs.testfixtures.OperationBuilder;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||||
|
import static org.springframework.restdocs.request.RequestDocumentation.parameterWithName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests for failures when rendering {@link QueryParametersSnippet} due to missing or
|
||||||
|
* undocumented query parameters.
|
||||||
|
*
|
||||||
|
* @author Andy Wilkinson
|
||||||
|
*/
|
||||||
|
public class QueryParametersSnippetFailureTests {
|
||||||
|
|
||||||
|
@Rule
|
||||||
|
public OperationBuilder operationBuilder = new OperationBuilder(TemplateFormats.asciidoctor());
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void undocumentedParameter() {
|
||||||
|
assertThatExceptionOfType(SnippetException.class)
|
||||||
|
.isThrownBy(() -> new QueryParametersSnippet(Collections.<ParameterDescriptor>emptyList())
|
||||||
|
.document(this.operationBuilder.request("http://localhost?a=alpha").build()))
|
||||||
|
.withMessage("Query parameters with the following names were not documented: [a]");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void missingParameter() {
|
||||||
|
assertThatExceptionOfType(SnippetException.class)
|
||||||
|
.isThrownBy(() -> new QueryParametersSnippet(Arrays.asList(parameterWithName("a").description("one")))
|
||||||
|
.document(this.operationBuilder.request("http://localhost").build()))
|
||||||
|
.withMessage("Query parameters with the following names were not found in the request: [a]");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void undocumentedAndMissingParameters() {
|
||||||
|
assertThatExceptionOfType(SnippetException.class)
|
||||||
|
.isThrownBy(() -> new QueryParametersSnippet(Arrays.asList(parameterWithName("a").description("one")))
|
||||||
|
.document(this.operationBuilder.request("http://localhost?b=bravo").build()))
|
||||||
|
.withMessage("Query parameters with the following names were not documented: [b]. Query parameters"
|
||||||
|
+ " with the following names were not found in the request: [a]");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,177 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2014-2022 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
|
||||||
|
*
|
||||||
|
* https://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.request;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import org.springframework.restdocs.AbstractSnippetTests;
|
||||||
|
import org.springframework.restdocs.templates.TemplateEngine;
|
||||||
|
import org.springframework.restdocs.templates.TemplateFormat;
|
||||||
|
import org.springframework.restdocs.templates.TemplateFormats;
|
||||||
|
import org.springframework.restdocs.templates.TemplateResourceResolver;
|
||||||
|
import org.springframework.restdocs.templates.mustache.MustacheTemplateEngine;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
import static org.mockito.BDDMockito.given;
|
||||||
|
import static org.mockito.Mockito.mock;
|
||||||
|
import static org.springframework.restdocs.request.RequestDocumentation.parameterWithName;
|
||||||
|
import static org.springframework.restdocs.snippet.Attributes.attributes;
|
||||||
|
import static org.springframework.restdocs.snippet.Attributes.key;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests for {@link QueryParametersSnippet}.
|
||||||
|
*
|
||||||
|
* @author Andy Wilkinson
|
||||||
|
*/
|
||||||
|
public class QueryParametersSnippetTests extends AbstractSnippetTests {
|
||||||
|
|
||||||
|
public QueryParametersSnippetTests(String name, TemplateFormat templateFormat) {
|
||||||
|
super(name, templateFormat);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void queryParameters() throws IOException {
|
||||||
|
new QueryParametersSnippet(
|
||||||
|
Arrays.asList(parameterWithName("a").description("one"), parameterWithName("b").description("two")))
|
||||||
|
.document(this.operationBuilder.request("http://localhost?a=alpha&b=bravo").build());
|
||||||
|
assertThat(this.generatedSnippets.queryParameters())
|
||||||
|
.is(tableWithHeader("Parameter", "Description").row("`a`", "one").row("`b`", "two"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void queryParameterWithNoValue() throws IOException {
|
||||||
|
new QueryParametersSnippet(Arrays.asList(parameterWithName("a").description("one")))
|
||||||
|
.document(this.operationBuilder.request("http://localhost?a").build());
|
||||||
|
assertThat(this.generatedSnippets.queryParameters())
|
||||||
|
.is(tableWithHeader("Parameter", "Description").row("`a`", "one"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void ignoredQueryParameter() throws IOException {
|
||||||
|
new QueryParametersSnippet(
|
||||||
|
Arrays.asList(parameterWithName("a").ignored(), parameterWithName("b").description("two")))
|
||||||
|
.document(this.operationBuilder.request("http://localhost?a=alpha&b=bravo").build());
|
||||||
|
assertThat(this.generatedSnippets.queryParameters())
|
||||||
|
.is(tableWithHeader("Parameter", "Description").row("`b`", "two"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void allUndocumentedQueryParametersCanBeIgnored() throws IOException {
|
||||||
|
new QueryParametersSnippet(Arrays.asList(parameterWithName("b").description("two")), true)
|
||||||
|
.document(this.operationBuilder.request("http://localhost?a=alpha&b=bravo").build());
|
||||||
|
assertThat(this.generatedSnippets.queryParameters())
|
||||||
|
.is(tableWithHeader("Parameter", "Description").row("`b`", "two"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void missingOptionalQueryParameter() throws IOException {
|
||||||
|
new QueryParametersSnippet(Arrays.asList(parameterWithName("a").description("one").optional(),
|
||||||
|
parameterWithName("b").description("two")))
|
||||||
|
.document(this.operationBuilder.request("http://localhost?b=bravo").build());
|
||||||
|
assertThat(this.generatedSnippets.queryParameters())
|
||||||
|
.is(tableWithHeader("Parameter", "Description").row("`a`", "one").row("`b`", "two"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void presentOptionalQueryParameter() throws IOException {
|
||||||
|
new QueryParametersSnippet(Arrays.asList(parameterWithName("a").description("one").optional()))
|
||||||
|
.document(this.operationBuilder.request("http://localhost?a=alpha").build());
|
||||||
|
assertThat(this.generatedSnippets.queryParameters())
|
||||||
|
.is(tableWithHeader("Parameter", "Description").row("`a`", "one"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void queryParametersWithCustomAttributes() throws IOException {
|
||||||
|
TemplateResourceResolver resolver = mock(TemplateResourceResolver.class);
|
||||||
|
given(resolver.resolveTemplateResource("query-parameters"))
|
||||||
|
.willReturn(snippetResource("query-parameters-with-title"));
|
||||||
|
new QueryParametersSnippet(
|
||||||
|
Arrays.asList(parameterWithName("a").description("one").attributes(key("foo").value("alpha")),
|
||||||
|
parameterWithName("b").description("two").attributes(key("foo").value("bravo"))),
|
||||||
|
attributes(key("title").value("The title")))
|
||||||
|
.document(this.operationBuilder
|
||||||
|
.attribute(TemplateEngine.class.getName(), new MustacheTemplateEngine(resolver))
|
||||||
|
.request("http://localhost?a=alpha&b=bravo").build());
|
||||||
|
assertThat(this.generatedSnippets.queryParameters()).contains("The title");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void queryParametersWithCustomDescriptorAttributes() throws IOException {
|
||||||
|
TemplateResourceResolver resolver = mock(TemplateResourceResolver.class);
|
||||||
|
given(resolver.resolveTemplateResource("query-parameters"))
|
||||||
|
.willReturn(snippetResource("query-parameters-with-extra-column"));
|
||||||
|
new QueryParametersSnippet(
|
||||||
|
Arrays.asList(parameterWithName("a").description("one").attributes(key("foo").value("alpha")),
|
||||||
|
parameterWithName("b").description("two").attributes(key("foo").value("bravo"))))
|
||||||
|
.document(this.operationBuilder
|
||||||
|
.attribute(TemplateEngine.class.getName(), new MustacheTemplateEngine(resolver))
|
||||||
|
.request("http://localhost?a=alpha&b=bravo").build());
|
||||||
|
assertThat(this.generatedSnippets.queryParameters()).is(
|
||||||
|
tableWithHeader("Parameter", "Description", "Foo").row("a", "one", "alpha").row("b", "two", "bravo"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void queryParametersWithOptionalColumn() throws IOException {
|
||||||
|
TemplateResourceResolver resolver = mock(TemplateResourceResolver.class);
|
||||||
|
given(resolver.resolveTemplateResource("query-parameters"))
|
||||||
|
.willReturn(snippetResource("query-parameters-with-optional-column"));
|
||||||
|
new QueryParametersSnippet(Arrays.asList(parameterWithName("a").description("one").optional(),
|
||||||
|
parameterWithName("b").description("two")))
|
||||||
|
.document(this.operationBuilder
|
||||||
|
.attribute(TemplateEngine.class.getName(), new MustacheTemplateEngine(resolver))
|
||||||
|
.request("http://localhost?a=alpha&b=bravo").build());
|
||||||
|
assertThat(this.generatedSnippets.queryParameters()).is(tableWithHeader("Parameter", "Optional", "Description")
|
||||||
|
.row("a", "true", "one").row("b", "false", "two"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void additionalDescriptors() throws IOException {
|
||||||
|
RequestDocumentation.queryParameters(parameterWithName("a").description("one"))
|
||||||
|
.and(parameterWithName("b").description("two"))
|
||||||
|
.document(this.operationBuilder.request("http://localhost?a=alpha&b=bravo").build());
|
||||||
|
assertThat(this.generatedSnippets.queryParameters())
|
||||||
|
.is(tableWithHeader("Parameter", "Description").row("`a`", "one").row("`b`", "two"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void additionalDescriptorsWithRelaxedQueryParameters() throws IOException {
|
||||||
|
RequestDocumentation.relaxedQueryParameters(parameterWithName("a").description("one"))
|
||||||
|
.and(parameterWithName("b").description("two"))
|
||||||
|
.document(this.operationBuilder.request("http://localhost?a=alpha&b=bravo&c=undocumented").build());
|
||||||
|
assertThat(this.generatedSnippets.queryParameters())
|
||||||
|
.is(tableWithHeader("Parameter", "Description").row("`a`", "one").row("`b`", "two"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void queryParametersWithEscapedContent() throws IOException {
|
||||||
|
RequestDocumentation.queryParameters(parameterWithName("Foo|Bar").description("one|two"))
|
||||||
|
.document(this.operationBuilder.request("http://localhost?Foo%7CBar=baz").build());
|
||||||
|
assertThat(this.generatedSnippets.queryParameters()).is(tableWithHeader("Parameter", "Description")
|
||||||
|
.row(escapeIfNecessary("`Foo|Bar`"), escapeIfNecessary("one|two")));
|
||||||
|
}
|
||||||
|
|
||||||
|
private String escapeIfNecessary(String input) {
|
||||||
|
if (this.templateFormat.getId().equals(TemplateFormats.markdown().getId())) {
|
||||||
|
return input;
|
||||||
|
}
|
||||||
|
return input.replace("|", "\\|");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
|===
|
||||||
|
|Parameter|Description|Foo
|
||||||
|
|
||||||
|
{{#parameters}}
|
||||||
|
|{{name}}
|
||||||
|
|{{description}}
|
||||||
|
|{{foo}}
|
||||||
|
|
||||||
|
{{/parameters}}
|
||||||
|
|===
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
|===
|
||||||
|
|Parameter|Optional|Description
|
||||||
|
|
||||||
|
{{#parameters}}
|
||||||
|
|{{name}}
|
||||||
|
|{{optional}}
|
||||||
|
|{{description}}
|
||||||
|
|
||||||
|
{{/parameters}}
|
||||||
|
|===
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
.{{title}}
|
||||||
|
|===
|
||||||
|
|Parameter|Description
|
||||||
|
|
||||||
|
{{#parameters}}
|
||||||
|
|{{name}}
|
||||||
|
|{{description}}
|
||||||
|
|
||||||
|
{{/parameters}}
|
||||||
|
|===
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
Parameter | Description | Foo
|
||||||
|
--------- | ----------- | ---
|
||||||
|
{{#parameters}}
|
||||||
|
{{name}} | {{description}} | {{foo}}
|
||||||
|
{{/parameters}}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
Parameter | Optional | Description
|
||||||
|
--------- | -------- | -----------
|
||||||
|
{{#parameters}}
|
||||||
|
{{name}} | {{optional}} | {{description}}
|
||||||
|
{{/parameters}}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
{{title}}
|
||||||
|
Parameter | Description
|
||||||
|
--------- | -----------
|
||||||
|
{{#parameters}}
|
||||||
|
{{name}} | {{description}}
|
||||||
|
{{/parameters}}
|
||||||
@@ -110,8 +110,12 @@ public class GeneratedSnippets extends OperationTestRule {
|
|||||||
return snippet("path-parameters");
|
return snippet("path-parameters");
|
||||||
}
|
}
|
||||||
|
|
||||||
public String requestParameters() {
|
public String queryParameters() {
|
||||||
return snippet("request-parameters");
|
return snippet("query-parameters");
|
||||||
|
}
|
||||||
|
|
||||||
|
public String formParameters() {
|
||||||
|
return snippet("form-parameters");
|
||||||
}
|
}
|
||||||
|
|
||||||
public String snippet(String name) {
|
public String snippet(String name) {
|
||||||
|
|||||||
@@ -20,7 +20,6 @@ import java.io.File;
|
|||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -42,7 +41,6 @@ import org.springframework.restdocs.operation.OperationRequestPart;
|
|||||||
import org.springframework.restdocs.operation.OperationRequestPartFactory;
|
import org.springframework.restdocs.operation.OperationRequestPartFactory;
|
||||||
import org.springframework.restdocs.operation.OperationResponse;
|
import org.springframework.restdocs.operation.OperationResponse;
|
||||||
import org.springframework.restdocs.operation.OperationResponseFactory;
|
import org.springframework.restdocs.operation.OperationResponseFactory;
|
||||||
import org.springframework.restdocs.operation.Parameters;
|
|
||||||
import org.springframework.restdocs.operation.RequestCookie;
|
import org.springframework.restdocs.operation.RequestCookie;
|
||||||
import org.springframework.restdocs.operation.ResponseCookie;
|
import org.springframework.restdocs.operation.ResponseCookie;
|
||||||
import org.springframework.restdocs.operation.StandardOperation;
|
import org.springframework.restdocs.operation.StandardOperation;
|
||||||
@@ -147,8 +145,6 @@ public class OperationBuilder extends OperationTestRule {
|
|||||||
|
|
||||||
private HttpHeaders headers = new HttpHeaders();
|
private HttpHeaders headers = new HttpHeaders();
|
||||||
|
|
||||||
private Parameters parameters = new Parameters();
|
|
||||||
|
|
||||||
private List<OperationRequestPartBuilder> partBuilders = new ArrayList<>();
|
private List<OperationRequestPartBuilder> partBuilders = new ArrayList<>();
|
||||||
|
|
||||||
private Collection<RequestCookie> cookies = new ArrayList<>();
|
private Collection<RequestCookie> cookies = new ArrayList<>();
|
||||||
@@ -162,8 +158,8 @@ public class OperationBuilder extends OperationTestRule {
|
|||||||
for (OperationRequestPartBuilder builder : this.partBuilders) {
|
for (OperationRequestPartBuilder builder : this.partBuilders) {
|
||||||
parts.add(builder.buildPart());
|
parts.add(builder.buildPart());
|
||||||
}
|
}
|
||||||
return new OperationRequestFactory().create(this.requestUri, this.method, this.content, this.headers,
|
return new OperationRequestFactory().create(this.requestUri, this.method, this.content, this.headers, parts,
|
||||||
this.parameters, parts, this.cookies);
|
this.cookies);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Operation build() {
|
public Operation build() {
|
||||||
@@ -185,18 +181,6 @@ public class OperationBuilder extends OperationTestRule {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public OperationRequestBuilder param(String name, String... values) {
|
|
||||||
if (values.length > 0) {
|
|
||||||
for (String value : values) {
|
|
||||||
this.parameters.add(name, value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
this.parameters.put(name, Collections.<String>emptyList());
|
|
||||||
}
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public OperationRequestBuilder header(String name, String value) {
|
public OperationRequestBuilder header(String name, String value) {
|
||||||
this.headers.add(name, value);
|
this.headers.add(name, value);
|
||||||
return this;
|
return this;
|
||||||
|
|||||||
@@ -17,14 +17,18 @@
|
|||||||
package org.springframework.restdocs.mockmvc;
|
package org.springframework.restdocs.mockmvc;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.PrintWriter;
|
|
||||||
import java.io.StringWriter;
|
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
|
import java.net.URLDecoder;
|
||||||
|
import java.net.URLEncoder;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
|
import java.util.Scanner;
|
||||||
|
|
||||||
import jakarta.servlet.ServletException;
|
import jakarta.servlet.ServletException;
|
||||||
import jakarta.servlet.http.Part;
|
import jakarta.servlet.http.Part;
|
||||||
@@ -39,10 +43,11 @@ import org.springframework.restdocs.operation.OperationRequest;
|
|||||||
import org.springframework.restdocs.operation.OperationRequestFactory;
|
import org.springframework.restdocs.operation.OperationRequestFactory;
|
||||||
import org.springframework.restdocs.operation.OperationRequestPart;
|
import org.springframework.restdocs.operation.OperationRequestPart;
|
||||||
import org.springframework.restdocs.operation.OperationRequestPartFactory;
|
import org.springframework.restdocs.operation.OperationRequestPartFactory;
|
||||||
import org.springframework.restdocs.operation.Parameters;
|
|
||||||
import org.springframework.restdocs.operation.RequestConverter;
|
import org.springframework.restdocs.operation.RequestConverter;
|
||||||
import org.springframework.restdocs.operation.RequestCookie;
|
import org.springframework.restdocs.operation.RequestCookie;
|
||||||
import org.springframework.util.FileCopyUtils;
|
import org.springframework.util.FileCopyUtils;
|
||||||
|
import org.springframework.util.LinkedMultiValueMap;
|
||||||
|
import org.springframework.util.MultiValueMap;
|
||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
import org.springframework.web.multipart.MultipartFile;
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
|
||||||
@@ -55,36 +60,88 @@ import org.springframework.web.multipart.MultipartFile;
|
|||||||
*/
|
*/
|
||||||
class MockMvcRequestConverter implements RequestConverter<MockHttpServletRequest> {
|
class MockMvcRequestConverter implements RequestConverter<MockHttpServletRequest> {
|
||||||
|
|
||||||
private static final String SCHEME_HTTP = "http";
|
|
||||||
|
|
||||||
private static final String SCHEME_HTTPS = "https";
|
|
||||||
|
|
||||||
private static final int STANDARD_PORT_HTTP = 80;
|
|
||||||
|
|
||||||
private static final int STANDARD_PORT_HTTPS = 443;
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public OperationRequest convert(MockHttpServletRequest mockRequest) {
|
public OperationRequest convert(MockHttpServletRequest mockRequest) {
|
||||||
try {
|
try {
|
||||||
HttpHeaders headers = extractHeaders(mockRequest);
|
HttpHeaders headers = extractHeaders(mockRequest);
|
||||||
Parameters parameters = extractParameters(mockRequest);
|
|
||||||
List<OperationRequestPart> parts = extractParts(mockRequest);
|
List<OperationRequestPart> parts = extractParts(mockRequest);
|
||||||
Collection<RequestCookie> cookies = extractCookies(mockRequest, headers);
|
Collection<RequestCookie> cookies = extractCookies(mockRequest, headers);
|
||||||
String queryString = mockRequest.getQueryString();
|
return new OperationRequestFactory().create(getRequestUri(mockRequest),
|
||||||
if (!StringUtils.hasText(queryString) && "GET".equals(mockRequest.getMethod())) {
|
HttpMethod.valueOf(mockRequest.getMethod()), getRequestContent(mockRequest, headers), headers,
|
||||||
queryString = parameters.toQueryString();
|
parts, cookies);
|
||||||
}
|
|
||||||
return new OperationRequestFactory().create(
|
|
||||||
URI.create(
|
|
||||||
getRequestUri(mockRequest) + (StringUtils.hasText(queryString) ? "?" + queryString : "")),
|
|
||||||
HttpMethod.valueOf(mockRequest.getMethod()), mockRequest.getContentAsByteArray(), headers,
|
|
||||||
parameters, parts, cookies);
|
|
||||||
}
|
}
|
||||||
catch (Exception ex) {
|
catch (Exception ex) {
|
||||||
throw new ConversionException(ex);
|
throw new ConversionException(ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private URI getRequestUri(MockHttpServletRequest mockRequest) {
|
||||||
|
String queryString = "";
|
||||||
|
if (mockRequest.getQueryString() != null) {
|
||||||
|
queryString = mockRequest.getQueryString();
|
||||||
|
}
|
||||||
|
else if ("GET".equals(mockRequest.getMethod()) || mockRequest.getContentLengthLong() > 0) {
|
||||||
|
queryString = urlEncodedParameters(mockRequest);
|
||||||
|
}
|
||||||
|
StringBuffer requestUrlBuffer = mockRequest.getRequestURL();
|
||||||
|
if (queryString.length() > 0) {
|
||||||
|
requestUrlBuffer.append("?").append(queryString.toString());
|
||||||
|
}
|
||||||
|
return URI.create(requestUrlBuffer.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
private String urlEncodedParameters(MockHttpServletRequest mockRequest) {
|
||||||
|
StringBuilder parameters = new StringBuilder();
|
||||||
|
MultiValueMap<String, String> queryParameters = parse(mockRequest.getQueryString());
|
||||||
|
for (String name : IterableEnumeration.of(mockRequest.getParameterNames())) {
|
||||||
|
if (!queryParameters.containsKey(name)) {
|
||||||
|
String[] values = mockRequest.getParameterValues(name);
|
||||||
|
if (values.length == 0) {
|
||||||
|
append(parameters, name);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
for (String value : values) {
|
||||||
|
append(parameters, name, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return parameters.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private byte[] getRequestContent(MockHttpServletRequest mockRequest, HttpHeaders headers) {
|
||||||
|
byte[] content = mockRequest.getContentAsByteArray();
|
||||||
|
if ("GET".equals(mockRequest.getMethod())) {
|
||||||
|
return content;
|
||||||
|
}
|
||||||
|
MediaType contentType = headers.getContentType();
|
||||||
|
if (contentType == null || MediaType.APPLICATION_FORM_URLENCODED.includes(contentType)) {
|
||||||
|
Map<String, String[]> parameters = mockRequest.getParameterMap();
|
||||||
|
if (!parameters.isEmpty() && (content == null || content.length == 0)) {
|
||||||
|
StringBuilder contentBuilder = new StringBuilder();
|
||||||
|
headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
|
||||||
|
MultiValueMap<String, String> queryParameters = parse(mockRequest.getQueryString());
|
||||||
|
mockRequest.getParameterMap().forEach((name, values) -> {
|
||||||
|
List<String> queryParameterValues = queryParameters.get(name);
|
||||||
|
if (values.length == 0) {
|
||||||
|
if (queryParameterValues == null) {
|
||||||
|
append(contentBuilder, name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
for (String value : values) {
|
||||||
|
if (queryParameterValues == null || !queryParameterValues.contains(value)) {
|
||||||
|
append(contentBuilder, name, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return contentBuilder.toString().getBytes(StandardCharsets.UTF_8);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return content;
|
||||||
|
}
|
||||||
|
|
||||||
private Collection<RequestCookie> extractCookies(MockHttpServletRequest mockRequest, HttpHeaders headers) {
|
private Collection<RequestCookie> extractCookies(MockHttpServletRequest mockRequest, HttpHeaders headers) {
|
||||||
if (mockRequest.getCookies() == null || mockRequest.getCookies().length == 0) {
|
if (mockRequest.getCookies() == null || mockRequest.getCookies().length == 0) {
|
||||||
return Collections.emptyList();
|
return Collections.emptyList();
|
||||||
@@ -158,16 +215,6 @@ class MockMvcRequestConverter implements RequestConverter<MockHttpServletRequest
|
|||||||
return partHeaders;
|
return partHeaders;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Parameters extractParameters(MockHttpServletRequest servletRequest) {
|
|
||||||
Parameters parameters = new Parameters();
|
|
||||||
for (String name : IterableEnumeration.of(servletRequest.getParameterNames())) {
|
|
||||||
for (String value : servletRequest.getParameterValues(name)) {
|
|
||||||
parameters.add(name, value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return parameters;
|
|
||||||
}
|
|
||||||
|
|
||||||
private HttpHeaders extractHeaders(MockHttpServletRequest servletRequest) {
|
private HttpHeaders extractHeaders(MockHttpServletRequest servletRequest) {
|
||||||
HttpHeaders headers = new HttpHeaders();
|
HttpHeaders headers = new HttpHeaders();
|
||||||
for (String headerName : IterableEnumeration.of(servletRequest.getHeaderNames())) {
|
for (String headerName : IterableEnumeration.of(servletRequest.getHeaderNames())) {
|
||||||
@@ -178,21 +225,62 @@ class MockMvcRequestConverter implements RequestConverter<MockHttpServletRequest
|
|||||||
return headers;
|
return headers;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isNonStandardPort(MockHttpServletRequest request) {
|
private static void append(StringBuilder sb, String key) {
|
||||||
return (SCHEME_HTTP.equals(request.getScheme()) && request.getServerPort() != STANDARD_PORT_HTTP)
|
append(sb, key, "");
|
||||||
|| (SCHEME_HTTPS.equals(request.getScheme()) && request.getServerPort() != STANDARD_PORT_HTTPS);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getRequestUri(MockHttpServletRequest request) {
|
private static void append(StringBuilder sb, String key, String value) {
|
||||||
StringWriter uriWriter = new StringWriter();
|
doAppend(sb, urlEncode(key) + "=" + urlEncode(value));
|
||||||
PrintWriter printer = new PrintWriter(uriWriter);
|
}
|
||||||
|
|
||||||
printer.printf("%s://%s", request.getScheme(), request.getServerName());
|
private static void doAppend(StringBuilder sb, String toAppend) {
|
||||||
if (isNonStandardPort(request)) {
|
if (sb.length() > 0) {
|
||||||
printer.printf(":%d", request.getServerPort());
|
sb.append("&");
|
||||||
}
|
}
|
||||||
printer.print(request.getRequestURI());
|
sb.append(toAppend);
|
||||||
return uriWriter.toString();
|
}
|
||||||
|
|
||||||
|
private static String urlEncode(String s) {
|
||||||
|
if (!StringUtils.hasLength(s)) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
return URLEncoder.encode(s, StandardCharsets.UTF_8);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static MultiValueMap<String, String> parse(String query) {
|
||||||
|
MultiValueMap<String, String> parameters = new LinkedMultiValueMap<>();
|
||||||
|
if (!StringUtils.hasLength(query)) {
|
||||||
|
return parameters;
|
||||||
|
}
|
||||||
|
try (Scanner scanner = new Scanner(query)) {
|
||||||
|
scanner.useDelimiter("&");
|
||||||
|
while (scanner.hasNext()) {
|
||||||
|
processParameter(scanner.next(), parameters);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return parameters;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void processParameter(String parameter, MultiValueMap<String, String> parameters) {
|
||||||
|
String[] components = parameter.split("=");
|
||||||
|
if (components.length > 0 && components.length < 3) {
|
||||||
|
if (components.length == 2) {
|
||||||
|
String name = components[0];
|
||||||
|
String value = components[1];
|
||||||
|
parameters.add(decode(name), decode(value));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
List<String> values = parameters.computeIfAbsent(components[0], (p) -> new LinkedList<>());
|
||||||
|
values.add("");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw new IllegalArgumentException("The parameter '" + parameter + "' is malformed");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String decode(String encoded) {
|
||||||
|
return URLDecoder.decode(encoded, StandardCharsets.US_ASCII);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -127,31 +127,35 @@ public class MockMvcRequestConverterTests {
|
|||||||
OperationRequest request = createOperationRequest(
|
OperationRequest request = createOperationRequest(
|
||||||
MockMvcRequestBuilders.get("/foo").param("a", "alpha", "apple").param("b", "br&vo"));
|
MockMvcRequestBuilders.get("/foo").param("a", "alpha", "apple").param("b", "br&vo"));
|
||||||
assertThat(request.getUri()).isEqualTo(URI.create("http://localhost/foo?a=alpha&a=apple&b=br%26vo"));
|
assertThat(request.getUri()).isEqualTo(URI.create("http://localhost/foo?a=alpha&a=apple&b=br%26vo"));
|
||||||
assertThat(request.getParameters().size()).isEqualTo(2);
|
|
||||||
assertThat(request.getParameters()).containsEntry("a", Arrays.asList("alpha", "apple"));
|
|
||||||
assertThat(request.getParameters()).containsEntry("b", Arrays.asList("br&vo"));
|
|
||||||
assertThat(request.getMethod()).isEqualTo(HttpMethod.GET);
|
assertThat(request.getMethod()).isEqualTo(HttpMethod.GET);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void getRequestWithQueryStringPopulatesParameters() {
|
public void getRequestWithQueryString() {
|
||||||
OperationRequest request = createOperationRequest(MockMvcRequestBuilders.get("/foo?a=alpha&b=bravo"));
|
MockHttpServletRequestBuilder builder = MockMvcRequestBuilders.get("/foo?a=alpha&b=bravo");
|
||||||
|
OperationRequest request = createOperationRequest(builder);
|
||||||
assertThat(request.getUri()).isEqualTo(URI.create("http://localhost/foo?a=alpha&b=bravo"));
|
assertThat(request.getUri()).isEqualTo(URI.create("http://localhost/foo?a=alpha&b=bravo"));
|
||||||
assertThat(request.getParameters().size()).isEqualTo(2);
|
|
||||||
assertThat(request.getParameters()).containsEntry("a", Arrays.asList("alpha"));
|
|
||||||
assertThat(request.getParameters()).containsEntry("b", Arrays.asList("bravo"));
|
|
||||||
assertThat(request.getMethod()).isEqualTo(HttpMethod.GET);
|
assertThat(request.getMethod()).isEqualTo(HttpMethod.GET);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void postRequestWithParameters() {
|
public void postRequestWithParametersCreatesFormUrlEncodedContent() {
|
||||||
OperationRequest request = createOperationRequest(
|
OperationRequest request = createOperationRequest(
|
||||||
MockMvcRequestBuilders.post("/foo").param("a", "alpha", "apple").param("b", "br&vo"));
|
MockMvcRequestBuilders.post("/foo").param("a", "alpha", "apple").param("b", "br&vo"));
|
||||||
assertThat(request.getUri()).isEqualTo(URI.create("http://localhost/foo"));
|
assertThat(request.getUri()).isEqualTo(URI.create("http://localhost/foo"));
|
||||||
assertThat(request.getMethod()).isEqualTo(HttpMethod.POST);
|
assertThat(request.getMethod()).isEqualTo(HttpMethod.POST);
|
||||||
assertThat(request.getParameters().size()).isEqualTo(2);
|
assertThat(request.getContentAsString()).isEqualTo("a=alpha&a=apple&b=br%26vo");
|
||||||
assertThat(request.getParameters()).containsEntry("a", Arrays.asList("alpha", "apple"));
|
assertThat(request.getHeaders().getContentType()).isEqualTo(MediaType.APPLICATION_FORM_URLENCODED);
|
||||||
assertThat(request.getParameters()).containsEntry("b", Arrays.asList("br&vo"));
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void postRequestWithParametersAndQueryStringCreatesFormUrlEncodedContentWithoutDuplication() {
|
||||||
|
OperationRequest request = createOperationRequest(
|
||||||
|
MockMvcRequestBuilders.post("/foo?a=alpha").param("a", "apple").param("b", "br&vo"));
|
||||||
|
assertThat(request.getUri()).isEqualTo(URI.create("http://localhost/foo?a=alpha"));
|
||||||
|
assertThat(request.getMethod()).isEqualTo(HttpMethod.POST);
|
||||||
|
assertThat(request.getContentAsString()).isEqualTo("a=apple&b=br%26vo");
|
||||||
|
assertThat(request.getHeaders().getContentType()).isEqualTo(MediaType.APPLICATION_FORM_URLENCODED);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
@@ -92,7 +92,7 @@ import static org.springframework.restdocs.payload.PayloadDocumentation.subsecti
|
|||||||
import static org.springframework.restdocs.request.RequestDocumentation.parameterWithName;
|
import static org.springframework.restdocs.request.RequestDocumentation.parameterWithName;
|
||||||
import static org.springframework.restdocs.request.RequestDocumentation.partWithName;
|
import static org.springframework.restdocs.request.RequestDocumentation.partWithName;
|
||||||
import static org.springframework.restdocs.request.RequestDocumentation.pathParameters;
|
import static org.springframework.restdocs.request.RequestDocumentation.pathParameters;
|
||||||
import static org.springframework.restdocs.request.RequestDocumentation.requestParameters;
|
import static org.springframework.restdocs.request.RequestDocumentation.queryParameters;
|
||||||
import static org.springframework.restdocs.request.RequestDocumentation.requestParts;
|
import static org.springframework.restdocs.request.RequestDocumentation.requestParts;
|
||||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.multipart;
|
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.multipart;
|
||||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
|
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
|
||||||
@@ -178,7 +178,7 @@ public class MockMvcRestDocumentationIntegrationTests {
|
|||||||
public void curlSnippetWithQueryStringOnPost() throws Exception {
|
public void curlSnippetWithQueryStringOnPost() throws Exception {
|
||||||
MockMvc mockMvc = MockMvcBuilders.webAppContextSetup(this.context)
|
MockMvc mockMvc = MockMvcBuilders.webAppContextSetup(this.context)
|
||||||
.apply(documentationConfiguration(this.restDocumentation)).build();
|
.apply(documentationConfiguration(this.restDocumentation)).build();
|
||||||
mockMvc.perform(post("/?foo=bar").param("foo", "bar").param("a", "alpha").accept(MediaType.APPLICATION_JSON))
|
mockMvc.perform(post("/?foo=bar").param("a", "alpha").accept(MediaType.APPLICATION_JSON))
|
||||||
.andExpect(status().isOk()).andDo(document("curl-snippet-with-query-string"));
|
.andExpect(status().isOk()).andDo(document("curl-snippet-with-query-string"));
|
||||||
assertThat(new File("build/generated-snippets/curl-snippet-with-query-string/curl-request.adoc"))
|
assertThat(new File("build/generated-snippets/curl-snippet-with-query-string/curl-request.adoc"))
|
||||||
.has(content(codeBlock(TemplateFormats.asciidoctor(), "bash")
|
.has(content(codeBlock(TemplateFormats.asciidoctor(), "bash")
|
||||||
@@ -238,11 +238,11 @@ public class MockMvcRestDocumentationIntegrationTests {
|
|||||||
public void httpieSnippetWithQueryStringOnPost() throws Exception {
|
public void httpieSnippetWithQueryStringOnPost() throws Exception {
|
||||||
MockMvc mockMvc = MockMvcBuilders.webAppContextSetup(this.context)
|
MockMvc mockMvc = MockMvcBuilders.webAppContextSetup(this.context)
|
||||||
.apply(documentationConfiguration(this.restDocumentation)).build();
|
.apply(documentationConfiguration(this.restDocumentation)).build();
|
||||||
mockMvc.perform(post("/?foo=bar").param("foo", "bar").param("a", "alpha").accept(MediaType.APPLICATION_JSON))
|
mockMvc.perform(post("/?foo=bar").param("a", "alpha").accept(MediaType.APPLICATION_JSON))
|
||||||
.andExpect(status().isOk()).andDo(document("httpie-snippet-with-query-string"));
|
.andExpect(status().isOk()).andDo(document("httpie-snippet-with-query-string"));
|
||||||
assertThat(new File("build/generated-snippets/httpie-snippet-with-query-string/httpie-request.adoc"))
|
assertThat(new File("build/generated-snippets/httpie-snippet-with-query-string/httpie-request.adoc"))
|
||||||
.has(content(codeBlock(TemplateFormats.asciidoctor(), "bash")
|
.has(content(codeBlock(TemplateFormats.asciidoctor(), "bash")
|
||||||
.withContent(String.format("$ http " + "--form POST 'http://localhost:8080/?foo=bar' \\%n"
|
.withContent(String.format("$ http --form POST 'http://localhost:8080/?foo=bar' \\%n"
|
||||||
+ " 'Accept:application/json' \\%n 'a=alpha'"))));
|
+ " 'Accept:application/json' \\%n 'a=alpha'"))));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -281,13 +281,13 @@ public class MockMvcRestDocumentationIntegrationTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void requestParametersSnippet() throws Exception {
|
public void queryParametersSnippet() throws Exception {
|
||||||
MockMvc mockMvc = MockMvcBuilders.webAppContextSetup(this.context)
|
MockMvc mockMvc = MockMvcBuilders.webAppContextSetup(this.context)
|
||||||
.apply(documentationConfiguration(this.restDocumentation)).build();
|
.apply(documentationConfiguration(this.restDocumentation)).build();
|
||||||
mockMvc.perform(get("/").param("foo", "bar").accept(MediaType.APPLICATION_JSON)).andExpect(status().isOk())
|
mockMvc.perform(get("/").param("foo", "bar").accept(MediaType.APPLICATION_JSON)).andExpect(status().isOk())
|
||||||
.andDo(document("links", requestParameters(parameterWithName("foo").description("The description"))));
|
.andDo(document("links", queryParameters(parameterWithName("foo").description("The description"))));
|
||||||
assertExpectedSnippetFilesExist(new File("build/generated-snippets/links"), "http-request.adoc",
|
assertExpectedSnippetFilesExist(new File("build/generated-snippets/links"), "http-request.adoc",
|
||||||
"http-response.adoc", "curl-request.adoc", "request-parameters.adoc");
|
"http-response.adoc", "curl-request.adoc", "query-parameters.adoc");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
@@ -21,4 +21,5 @@ dependencies {
|
|||||||
testImplementation("org.assertj:assertj-core")
|
testImplementation("org.assertj:assertj-core")
|
||||||
testImplementation("org.hamcrest:hamcrest-library")
|
testImplementation("org.hamcrest:hamcrest-library")
|
||||||
testImplementation("org.mockito:mockito-core")
|
testImplementation("org.mockito:mockito-core")
|
||||||
|
testImplementation("ch.qos.logback:logback-classic:1.4.1")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,9 +20,12 @@ import java.io.File;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
|
import java.net.URLEncoder;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
|
|
||||||
import io.restassured.http.Cookie;
|
import io.restassured.http.Cookie;
|
||||||
@@ -37,11 +40,11 @@ import org.springframework.restdocs.operation.OperationRequest;
|
|||||||
import org.springframework.restdocs.operation.OperationRequestFactory;
|
import org.springframework.restdocs.operation.OperationRequestFactory;
|
||||||
import org.springframework.restdocs.operation.OperationRequestPart;
|
import org.springframework.restdocs.operation.OperationRequestPart;
|
||||||
import org.springframework.restdocs.operation.OperationRequestPartFactory;
|
import org.springframework.restdocs.operation.OperationRequestPartFactory;
|
||||||
import org.springframework.restdocs.operation.Parameters;
|
|
||||||
import org.springframework.restdocs.operation.RequestConverter;
|
import org.springframework.restdocs.operation.RequestConverter;
|
||||||
import org.springframework.restdocs.operation.RequestCookie;
|
import org.springframework.restdocs.operation.RequestCookie;
|
||||||
import org.springframework.util.FileCopyUtils;
|
import org.springframework.util.FileCopyUtils;
|
||||||
import org.springframework.util.StreamUtils;
|
import org.springframework.util.StreamUtils;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A converter for creating an {@link OperationRequest} from a REST Assured
|
* A converter for creating an {@link OperationRequest} from a REST Assured
|
||||||
@@ -56,7 +59,7 @@ class RestAssuredRequestConverter implements RequestConverter<FilterableRequestS
|
|||||||
public OperationRequest convert(FilterableRequestSpecification requestSpec) {
|
public OperationRequest convert(FilterableRequestSpecification requestSpec) {
|
||||||
return new OperationRequestFactory().create(URI.create(requestSpec.getURI()),
|
return new OperationRequestFactory().create(URI.create(requestSpec.getURI()),
|
||||||
HttpMethod.valueOf(requestSpec.getMethod()), extractContent(requestSpec), extractHeaders(requestSpec),
|
HttpMethod.valueOf(requestSpec.getMethod()), extractContent(requestSpec), extractHeaders(requestSpec),
|
||||||
extractParameters(requestSpec), extractParts(requestSpec), extractCookies(requestSpec));
|
extractParts(requestSpec), extractCookies(requestSpec));
|
||||||
}
|
}
|
||||||
|
|
||||||
private Collection<RequestCookie> extractCookies(FilterableRequestSpecification requestSpec) {
|
private Collection<RequestCookie> extractCookies(FilterableRequestSpecification requestSpec) {
|
||||||
@@ -68,7 +71,36 @@ class RestAssuredRequestConverter implements RequestConverter<FilterableRequestS
|
|||||||
}
|
}
|
||||||
|
|
||||||
private byte[] extractContent(FilterableRequestSpecification requestSpec) {
|
private byte[] extractContent(FilterableRequestSpecification requestSpec) {
|
||||||
return convertContent(requestSpec.getBody());
|
Object body = requestSpec.getBody();
|
||||||
|
if (body != null) {
|
||||||
|
return convertContent(body);
|
||||||
|
}
|
||||||
|
StringBuilder parameters = new StringBuilder();
|
||||||
|
if ("POST".equals(requestSpec.getMethod())) {
|
||||||
|
appendParameters(parameters, requestSpec.getRequestParams());
|
||||||
|
}
|
||||||
|
if (!"GET".equals(requestSpec.getMethod())) {
|
||||||
|
appendParameters(parameters, requestSpec.getFormParams());
|
||||||
|
}
|
||||||
|
return parameters.toString().getBytes(StandardCharsets.ISO_8859_1);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void appendParameters(StringBuilder content, Map<String, ?> parameters) {
|
||||||
|
for (Entry<String, ?> entry : parameters.entrySet()) {
|
||||||
|
String name = entry.getKey();
|
||||||
|
Object value = entry.getValue();
|
||||||
|
if (value instanceof Iterable) {
|
||||||
|
for (Object v : (Iterable<?>) value) {
|
||||||
|
append(content, name, v.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (value != null) {
|
||||||
|
append(content, name, value.toString());
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
append(content, name);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private byte[] convertContent(Object content) {
|
private byte[] convertContent(Object content) {
|
||||||
@@ -131,28 +163,6 @@ class RestAssuredRequestConverter implements RequestConverter<FilterableRequestS
|
|||||||
return HttpHeaders.ACCEPT.equals(header.getName()) && "*/*".equals(header.getValue());
|
return HttpHeaders.ACCEPT.equals(header.getName()) && "*/*".equals(header.getValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
private Parameters extractParameters(FilterableRequestSpecification requestSpec) {
|
|
||||||
Parameters parameters = new Parameters();
|
|
||||||
for (Entry<String, ?> entry : requestSpec.getQueryParams().entrySet()) {
|
|
||||||
if (entry.getValue() instanceof Collection) {
|
|
||||||
Collection<?> queryParams = ((Collection<?>) entry.getValue());
|
|
||||||
for (Object queryParam : queryParams) {
|
|
||||||
parameters.add(entry.getKey(), queryParam.toString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
parameters.add(entry.getKey(), entry.getValue().toString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (Entry<String, ?> entry : requestSpec.getRequestParams().entrySet()) {
|
|
||||||
parameters.add(entry.getKey(), entry.getValue().toString());
|
|
||||||
}
|
|
||||||
for (Entry<String, ?> entry : requestSpec.getFormParams().entrySet()) {
|
|
||||||
parameters.add(entry.getKey(), entry.getValue().toString());
|
|
||||||
}
|
|
||||||
return parameters;
|
|
||||||
}
|
|
||||||
|
|
||||||
private Collection<OperationRequestPart> extractParts(FilterableRequestSpecification requestSpec) {
|
private Collection<OperationRequestPart> extractParts(FilterableRequestSpecification requestSpec) {
|
||||||
List<OperationRequestPart> parts = new ArrayList<>();
|
List<OperationRequestPart> parts = new ArrayList<>();
|
||||||
for (MultiPartSpecification multiPartSpec : requestSpec.getMultiPartParams()) {
|
for (MultiPartSpecification multiPartSpec : requestSpec.getMultiPartParams()) {
|
||||||
@@ -165,4 +175,26 @@ class RestAssuredRequestConverter implements RequestConverter<FilterableRequestS
|
|||||||
return parts;
|
return parts;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void append(StringBuilder sb, String key) {
|
||||||
|
append(sb, key, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void append(StringBuilder sb, String key, String value) {
|
||||||
|
doAppend(sb, urlEncode(key) + "=" + urlEncode(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void doAppend(StringBuilder sb, String toAppend) {
|
||||||
|
if (sb.length() > 0) {
|
||||||
|
sb.append("&");
|
||||||
|
}
|
||||||
|
sb.append(toAppend);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String urlEncode(String s) {
|
||||||
|
if (!StringUtils.hasLength(s)) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
return URLEncoder.encode(s, StandardCharsets.UTF_8);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,220 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2014-2022 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
|
||||||
|
*
|
||||||
|
* https://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.restassured;
|
||||||
|
|
||||||
|
import io.restassured.RestAssured;
|
||||||
|
import io.restassured.specification.RequestSpecification;
|
||||||
|
import org.assertj.core.api.AbstractAssert;
|
||||||
|
import org.junit.ClassRule;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import org.springframework.http.HttpMethod;
|
||||||
|
import org.springframework.http.MediaType;
|
||||||
|
import org.springframework.restdocs.operation.OperationRequest;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests to verify that the understanding of REST Assured's parameter handling behavior is
|
||||||
|
* correct.
|
||||||
|
*
|
||||||
|
* @author Andy Wilkinson
|
||||||
|
*/
|
||||||
|
public class RestAssuredParameterBehaviorTests {
|
||||||
|
|
||||||
|
private static final MediaType APPLICATION_FORM_URLENCODED_ISO_8859_1 = MediaType
|
||||||
|
.parseMediaType(MediaType.APPLICATION_FORM_URLENCODED_VALUE + ";charset=ISO-8859-1");
|
||||||
|
|
||||||
|
@ClassRule
|
||||||
|
public static TomcatServer tomcat = new TomcatServer();
|
||||||
|
|
||||||
|
private final RestAssuredRequestConverter factory = new RestAssuredRequestConverter();
|
||||||
|
|
||||||
|
private OperationRequest request;
|
||||||
|
|
||||||
|
private RequestSpecification spec = RestAssured.given().port(tomcat.getPort())
|
||||||
|
.filter((request, response, context) -> {
|
||||||
|
this.request = this.factory.convert(request);
|
||||||
|
return context.next(request, response);
|
||||||
|
});
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void queryParameterOnGet() {
|
||||||
|
this.spec.queryParam("a", "alpha", "apple").queryParam("b", "bravo").get("/query-parameter").then()
|
||||||
|
.statusCode(200);
|
||||||
|
assertThatRequest(this.request).hasQueryParametersWithMethod(HttpMethod.GET);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void queryParameterOnHead() {
|
||||||
|
this.spec.queryParam("a", "alpha", "apple").queryParam("b", "bravo").head("/query-parameter").then()
|
||||||
|
.statusCode(200);
|
||||||
|
assertThatRequest(this.request).hasQueryParametersWithMethod(HttpMethod.HEAD);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void queryParameterOnPost() {
|
||||||
|
this.spec.queryParam("a", "alpha", "apple").queryParam("b", "bravo").post("/query-parameter").then()
|
||||||
|
.statusCode(200);
|
||||||
|
assertThatRequest(this.request).hasQueryParametersWithMethod(HttpMethod.POST);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void queryParameterOnPut() {
|
||||||
|
this.spec.queryParam("a", "alpha", "apple").queryParam("b", "bravo").put("/query-parameter").then()
|
||||||
|
.statusCode(200);
|
||||||
|
assertThatRequest(this.request).hasQueryParametersWithMethod(HttpMethod.PUT);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void queryParameterOnPatch() {
|
||||||
|
this.spec.queryParam("a", "alpha", "apple").queryParam("b", "bravo").patch("/query-parameter").then()
|
||||||
|
.statusCode(200);
|
||||||
|
assertThatRequest(this.request).hasQueryParametersWithMethod(HttpMethod.PATCH);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void queryParameterOnDelete() {
|
||||||
|
this.spec.queryParam("a", "alpha", "apple").queryParam("b", "bravo").delete("/query-parameter").then()
|
||||||
|
.statusCode(200);
|
||||||
|
assertThatRequest(this.request).hasQueryParametersWithMethod(HttpMethod.DELETE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void queryParameterOnOptions() {
|
||||||
|
this.spec.queryParam("a", "alpha", "apple").queryParam("b", "bravo").options("/query-parameter").then()
|
||||||
|
.statusCode(200);
|
||||||
|
assertThatRequest(this.request).hasQueryParametersWithMethod(HttpMethod.OPTIONS);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void paramOnGet() {
|
||||||
|
this.spec.param("a", "alpha", "apple").param("b", "bravo").get("/query-parameter").then().statusCode(200);
|
||||||
|
assertThatRequest(this.request).hasQueryParametersWithMethod(HttpMethod.GET);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void paramOnHead() {
|
||||||
|
this.spec.param("a", "alpha", "apple").param("b", "bravo").head("/query-parameter").then().statusCode(200);
|
||||||
|
assertThatRequest(this.request).hasQueryParametersWithMethod(HttpMethod.HEAD);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void paramOnPost() {
|
||||||
|
this.spec.param("a", "alpha", "apple").param("b", "bravo").post("/form-url-encoded").then().statusCode(200);
|
||||||
|
assertThatRequest(this.request).isFormUrlEncodedWithMethod(HttpMethod.POST);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void paramOnPut() {
|
||||||
|
this.spec.param("a", "alpha", "apple").param("b", "bravo").put("/query-parameter").then().statusCode(200);
|
||||||
|
assertThatRequest(this.request).hasQueryParametersWithMethod(HttpMethod.PUT);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void paramOnPatch() {
|
||||||
|
this.spec.param("a", "alpha", "apple").param("b", "bravo").patch("/query-parameter").then().statusCode(200);
|
||||||
|
assertThatRequest(this.request).hasQueryParametersWithMethod(HttpMethod.PATCH);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void paramOnDelete() {
|
||||||
|
this.spec.param("a", "alpha", "apple").param("b", "bravo").delete("/query-parameter").then().statusCode(200);
|
||||||
|
assertThatRequest(this.request).hasQueryParametersWithMethod(HttpMethod.DELETE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void paramOnOptions() {
|
||||||
|
this.spec.param("a", "alpha", "apple").param("b", "bravo").options("/query-parameter").then().statusCode(200);
|
||||||
|
assertThatRequest(this.request).hasQueryParametersWithMethod(HttpMethod.OPTIONS);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void formParamOnGet() {
|
||||||
|
this.spec.formParam("a", "alpha", "apple").formParam("b", "bravo").get("/query-parameter").then()
|
||||||
|
.statusCode(200);
|
||||||
|
assertThatRequest(this.request).hasQueryParametersWithMethod(HttpMethod.GET);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void formParamOnHead() {
|
||||||
|
this.spec.formParam("a", "alpha", "apple").formParam("b", "bravo").head("/form-url-encoded").then()
|
||||||
|
.statusCode(200);
|
||||||
|
assertThatRequest(this.request).isFormUrlEncodedWithMethod(HttpMethod.HEAD);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void formParamOnPost() {
|
||||||
|
this.spec.formParam("a", "alpha", "apple").formParam("b", "bravo").post("/form-url-encoded").then()
|
||||||
|
.statusCode(200);
|
||||||
|
assertThatRequest(this.request).isFormUrlEncodedWithMethod(HttpMethod.POST);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void formParamOnPut() {
|
||||||
|
this.spec.formParam("a", "alpha", "apple").formParam("b", "bravo").put("/form-url-encoded").then()
|
||||||
|
.statusCode(200);
|
||||||
|
assertThatRequest(this.request).isFormUrlEncodedWithMethod(HttpMethod.PUT);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void formParamOnPatch() {
|
||||||
|
this.spec.formParam("a", "alpha", "apple").formParam("b", "bravo").patch("/form-url-encoded").then()
|
||||||
|
.statusCode(200);
|
||||||
|
assertThatRequest(this.request).isFormUrlEncodedWithMethod(HttpMethod.PATCH);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void formParamOnDelete() {
|
||||||
|
this.spec.formParam("a", "alpha", "apple").formParam("b", "bravo").delete("/form-url-encoded").then()
|
||||||
|
.statusCode(200);
|
||||||
|
assertThatRequest(this.request).isFormUrlEncodedWithMethod(HttpMethod.DELETE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void formParamOnOptions() {
|
||||||
|
this.spec.formParam("a", "alpha", "apple").formParam("b", "bravo").options("/form-url-encoded").then()
|
||||||
|
.statusCode(200);
|
||||||
|
assertThatRequest(this.request).isFormUrlEncodedWithMethod(HttpMethod.OPTIONS);
|
||||||
|
}
|
||||||
|
|
||||||
|
private OperationRequestAssert assertThatRequest(OperationRequest request) {
|
||||||
|
return new OperationRequestAssert(request);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final class OperationRequestAssert extends AbstractAssert<OperationRequestAssert, OperationRequest> {
|
||||||
|
|
||||||
|
private OperationRequestAssert(OperationRequest actual) {
|
||||||
|
super(actual, OperationRequestAssert.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void isFormUrlEncodedWithMethod(HttpMethod method) {
|
||||||
|
assertThat(this.actual.getMethod()).isEqualTo(method);
|
||||||
|
assertThat(this.actual.getUri().getRawQuery()).isNull();
|
||||||
|
assertThat(this.actual.getContentAsString()).isEqualTo("a=alpha&a=apple&b=bravo");
|
||||||
|
assertThat(this.actual.getHeaders().getContentType()).isEqualTo(APPLICATION_FORM_URLENCODED_ISO_8859_1);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void hasQueryParametersWithMethod(HttpMethod method) {
|
||||||
|
assertThat(this.actual.getMethod()).isEqualTo(method);
|
||||||
|
assertThat(this.actual.getUri().getRawQuery()).isEqualTo("a=alpha&a=apple&b=bravo");
|
||||||
|
assertThat(this.actual.getContentAsString()).isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -21,7 +21,6 @@ import java.io.File;
|
|||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
import java.io.FileNotFoundException;
|
import java.io.FileNotFoundException;
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
@@ -79,8 +78,7 @@ public class RestAssuredRequestConverterTests {
|
|||||||
RequestSpecification requestSpec = RestAssured.given().port(tomcat.getPort()).queryParam("foo", "bar");
|
RequestSpecification requestSpec = RestAssured.given().port(tomcat.getPort()).queryParam("foo", "bar");
|
||||||
requestSpec.get("/");
|
requestSpec.get("/");
|
||||||
OperationRequest request = this.factory.convert((FilterableRequestSpecification) requestSpec);
|
OperationRequest request = this.factory.convert((FilterableRequestSpecification) requestSpec);
|
||||||
assertThat(request.getParameters()).hasSize(1);
|
assertThat(request.getUri().getRawQuery()).isEqualTo("foo=bar");
|
||||||
assertThat(request.getParameters()).containsEntry("foo", Collections.singletonList("bar"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -88,26 +86,15 @@ public class RestAssuredRequestConverterTests {
|
|||||||
RequestSpecification requestSpec = RestAssured.given().port(tomcat.getPort());
|
RequestSpecification requestSpec = RestAssured.given().port(tomcat.getPort());
|
||||||
requestSpec.get("/?foo=bar&foo=qix");
|
requestSpec.get("/?foo=bar&foo=qix");
|
||||||
OperationRequest request = this.factory.convert((FilterableRequestSpecification) requestSpec);
|
OperationRequest request = this.factory.convert((FilterableRequestSpecification) requestSpec);
|
||||||
assertThat(request.getParameters()).hasSize(1);
|
assertThat(request.getUri().getRawQuery()).isEqualTo("foo=bar&foo=qix");
|
||||||
assertThat(request.getParameters()).containsEntry("foo", Arrays.asList("bar", "qix"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void formParameters() {
|
public void paramOnGetRequestIsMappedToQueryString() {
|
||||||
RequestSpecification requestSpec = RestAssured.given().port(tomcat.getPort()).formParam("foo", "bar");
|
|
||||||
requestSpec.get("/");
|
|
||||||
OperationRequest request = this.factory.convert((FilterableRequestSpecification) requestSpec);
|
|
||||||
assertThat(request.getParameters()).hasSize(1);
|
|
||||||
assertThat(request.getParameters()).containsEntry("foo", Collections.singletonList("bar"));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void requestParameters() {
|
|
||||||
RequestSpecification requestSpec = RestAssured.given().port(tomcat.getPort()).param("foo", "bar");
|
RequestSpecification requestSpec = RestAssured.given().port(tomcat.getPort()).param("foo", "bar");
|
||||||
requestSpec.get("/");
|
requestSpec.get("/");
|
||||||
OperationRequest request = this.factory.convert((FilterableRequestSpecification) requestSpec);
|
OperationRequest request = this.factory.convert((FilterableRequestSpecification) requestSpec);
|
||||||
assertThat(request.getParameters()).hasSize(1);
|
assertThat(request.getUri().getRawQuery()).isEqualTo("foo=bar");
|
||||||
assertThat(request.getParameters()).containsEntry("foo", Collections.singletonList("bar"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
@@ -68,7 +68,7 @@ import static org.springframework.restdocs.payload.PayloadDocumentation.subsecti
|
|||||||
import static org.springframework.restdocs.request.RequestDocumentation.parameterWithName;
|
import static org.springframework.restdocs.request.RequestDocumentation.parameterWithName;
|
||||||
import static org.springframework.restdocs.request.RequestDocumentation.partWithName;
|
import static org.springframework.restdocs.request.RequestDocumentation.partWithName;
|
||||||
import static org.springframework.restdocs.request.RequestDocumentation.pathParameters;
|
import static org.springframework.restdocs.request.RequestDocumentation.pathParameters;
|
||||||
import static org.springframework.restdocs.request.RequestDocumentation.requestParameters;
|
import static org.springframework.restdocs.request.RequestDocumentation.queryParameters;
|
||||||
import static org.springframework.restdocs.request.RequestDocumentation.requestParts;
|
import static org.springframework.restdocs.request.RequestDocumentation.requestParts;
|
||||||
import static org.springframework.restdocs.restassured.RestAssuredRestDocumentation.document;
|
import static org.springframework.restdocs.restassured.RestAssuredRestDocumentation.document;
|
||||||
import static org.springframework.restdocs.restassured.RestAssuredRestDocumentation.documentationConfiguration;
|
import static org.springframework.restdocs.restassured.RestAssuredRestDocumentation.documentationConfiguration;
|
||||||
@@ -143,7 +143,7 @@ public class RestAssuredRestDocumentationIntegrationTests {
|
|||||||
.has(content(codeBlock(TemplateFormats.asciidoctor(), "bash")
|
.has(content(codeBlock(TemplateFormats.asciidoctor(), "bash")
|
||||||
.withContent(String.format("$ curl " + "'http://localhost:" + tomcat.getPort()
|
.withContent(String.format("$ curl " + "'http://localhost:" + tomcat.getPort()
|
||||||
+ "/?foo=bar' -i -X POST \\%n" + " -H 'Accept: application/json' \\%n"
|
+ "/?foo=bar' -i -X POST \\%n" + " -H 'Accept: application/json' \\%n"
|
||||||
+ " -H 'Content-Type: " + contentType + "' \\%n" + " -d 'a=alpha'"))));
|
+ " -H 'Content-Type: " + contentType + "' \\%n" + " -d 'foo=bar&a=alpha'"))));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -166,13 +166,13 @@ public class RestAssuredRestDocumentationIntegrationTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void requestParametersSnippet() {
|
public void queryParametersSnippet() {
|
||||||
given().port(tomcat.getPort()).filter(documentationConfiguration(this.restDocumentation))
|
given().port(tomcat.getPort()).filter(documentationConfiguration(this.restDocumentation))
|
||||||
.filter(document("request-parameters",
|
.filter(document("query-parameters",
|
||||||
requestParameters(parameterWithName("foo").description("The description"))))
|
queryParameters(parameterWithName("foo").description("The description"))))
|
||||||
.accept("application/json").param("foo", "bar").get("/").then().statusCode(200);
|
.accept("application/json").param("foo", "bar").get("/").then().statusCode(200);
|
||||||
assertExpectedSnippetFilesExist(new File("build/generated-snippets/request-parameters"), "http-request.adoc",
|
assertExpectedSnippetFilesExist(new File("build/generated-snippets/query-parameters"), "http-request.adoc",
|
||||||
"http-response.adoc", "curl-request.adoc", "request-parameters.adoc");
|
"http-response.adoc", "curl-request.adoc", "query-parameters.adoc");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -385,8 +385,10 @@ public class RestAssuredRestDocumentationIntegrationTests {
|
|||||||
@Override
|
@Override
|
||||||
public boolean matches(File value) {
|
public boolean matches(File value) {
|
||||||
try {
|
try {
|
||||||
return delegate.matches(FileCopyUtils
|
String copyToString = FileCopyUtils
|
||||||
.copyToString(new InputStreamReader(new FileInputStream(value), StandardCharsets.UTF_8)));
|
.copyToString(new InputStreamReader(new FileInputStream(value), StandardCharsets.UTF_8));
|
||||||
|
System.out.println(copyToString);
|
||||||
|
return delegate.matches(copyToString);
|
||||||
}
|
}
|
||||||
catch (IOException ex) {
|
catch (IOException ex) {
|
||||||
fail("Failed to read '" + value + "'", ex);
|
fail("Failed to read '" + value + "'", ex);
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
package org.springframework.restdocs.restassured;
|
package org.springframework.restdocs.restassured;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@@ -33,6 +34,9 @@ import org.apache.catalina.LifecycleException;
|
|||||||
import org.apache.catalina.startup.Tomcat;
|
import org.apache.catalina.startup.Tomcat;
|
||||||
import org.junit.rules.ExternalResource;
|
import org.junit.rules.ExternalResource;
|
||||||
|
|
||||||
|
import org.springframework.http.MediaType;
|
||||||
|
import org.springframework.util.FileCopyUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@link ExternalResource} that starts and stops a Tomcat server.
|
* {@link ExternalResource} that starts and stops a Tomcat server.
|
||||||
*
|
*
|
||||||
@@ -53,6 +57,10 @@ class TomcatServer extends ExternalResource {
|
|||||||
context.addServletMappingDecoded("/", "test");
|
context.addServletMappingDecoded("/", "test");
|
||||||
this.tomcat.addServlet("/", "set-cookie", new CookiesServlet());
|
this.tomcat.addServlet("/", "set-cookie", new CookiesServlet());
|
||||||
context.addServletMappingDecoded("/set-cookie", "set-cookie");
|
context.addServletMappingDecoded("/set-cookie", "set-cookie");
|
||||||
|
this.tomcat.addServlet("/", "query-parameter", new QueryParameterServlet());
|
||||||
|
context.addServletMappingDecoded("/query-parameter", "query-parameter");
|
||||||
|
this.tomcat.addServlet("/", "form-url-encoded", new FormUrlEncodedServlet());
|
||||||
|
context.addServletMappingDecoded("/form-url-encoded", "form-url-encoded");
|
||||||
this.tomcat.start();
|
this.tomcat.start();
|
||||||
this.port = this.tomcat.getConnector().getLocalPort();
|
this.port = this.tomcat.getConnector().getLocalPort();
|
||||||
}
|
}
|
||||||
@@ -121,4 +129,33 @@ class TomcatServer extends ExternalResource {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static final class QueryParameterServlet extends HttpServlet {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
|
||||||
|
if (!req.getQueryString().equals("a=alpha&a=apple&b=bravo")) {
|
||||||
|
throw new ServletException("Incorrect query string");
|
||||||
|
}
|
||||||
|
resp.setStatus(200);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final class FormUrlEncodedServlet extends HttpServlet {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
|
||||||
|
if (!MediaType.APPLICATION_FORM_URLENCODED
|
||||||
|
.isCompatibleWith(MediaType.parseMediaType(req.getContentType()))) {
|
||||||
|
throw new ServletException("Incorrect Content-Type");
|
||||||
|
}
|
||||||
|
String content = FileCopyUtils.copyToString(new InputStreamReader(req.getInputStream()));
|
||||||
|
if (!"a=alpha&a=apple&b=bravo".equals(content)) {
|
||||||
|
throw new ServletException("Incorrect body content");
|
||||||
|
}
|
||||||
|
resp.setStatus(200);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,9 +30,7 @@ import org.springframework.core.io.buffer.DataBufferUtils;
|
|||||||
import org.springframework.core.io.buffer.DefaultDataBuffer;
|
import org.springframework.core.io.buffer.DefaultDataBuffer;
|
||||||
import org.springframework.core.io.buffer.DefaultDataBufferFactory;
|
import org.springframework.core.io.buffer.DefaultDataBufferFactory;
|
||||||
import org.springframework.http.HttpHeaders;
|
import org.springframework.http.HttpHeaders;
|
||||||
import org.springframework.http.MediaType;
|
|
||||||
import org.springframework.http.ReactiveHttpInputMessage;
|
import org.springframework.http.ReactiveHttpInputMessage;
|
||||||
import org.springframework.http.codec.FormHttpMessageReader;
|
|
||||||
import org.springframework.http.codec.HttpMessageReader;
|
import org.springframework.http.codec.HttpMessageReader;
|
||||||
import org.springframework.http.codec.multipart.DefaultPartHttpMessageReader;
|
import org.springframework.http.codec.multipart.DefaultPartHttpMessageReader;
|
||||||
import org.springframework.http.codec.multipart.FilePart;
|
import org.springframework.http.codec.multipart.FilePart;
|
||||||
@@ -42,14 +40,11 @@ import org.springframework.restdocs.operation.OperationRequest;
|
|||||||
import org.springframework.restdocs.operation.OperationRequestFactory;
|
import org.springframework.restdocs.operation.OperationRequestFactory;
|
||||||
import org.springframework.restdocs.operation.OperationRequestPart;
|
import org.springframework.restdocs.operation.OperationRequestPart;
|
||||||
import org.springframework.restdocs.operation.OperationRequestPartFactory;
|
import org.springframework.restdocs.operation.OperationRequestPartFactory;
|
||||||
import org.springframework.restdocs.operation.Parameters;
|
|
||||||
import org.springframework.restdocs.operation.QueryStringParser;
|
|
||||||
import org.springframework.restdocs.operation.RequestConverter;
|
import org.springframework.restdocs.operation.RequestConverter;
|
||||||
import org.springframework.restdocs.operation.RequestCookie;
|
import org.springframework.restdocs.operation.RequestCookie;
|
||||||
import org.springframework.test.web.reactive.server.ExchangeResult;
|
import org.springframework.test.web.reactive.server.ExchangeResult;
|
||||||
import org.springframework.test.web.reactive.server.WebTestClient;
|
import org.springframework.test.web.reactive.server.WebTestClient;
|
||||||
import org.springframework.util.LinkedMultiValueMap;
|
import org.springframework.util.LinkedMultiValueMap;
|
||||||
import org.springframework.util.MultiValueMap;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A {@link RequestConverter} for creating an {@link OperationRequest} derived from an
|
* A {@link RequestConverter} for creating an {@link OperationRequest} derived from an
|
||||||
@@ -59,18 +54,11 @@ import org.springframework.util.MultiValueMap;
|
|||||||
*/
|
*/
|
||||||
class WebTestClientRequestConverter implements RequestConverter<ExchangeResult> {
|
class WebTestClientRequestConverter implements RequestConverter<ExchangeResult> {
|
||||||
|
|
||||||
private static final ResolvableType FORM_DATA_TYPE = ResolvableType.forClassWithGenerics(MultiValueMap.class,
|
|
||||||
String.class, String.class);
|
|
||||||
|
|
||||||
private final QueryStringParser queryStringParser = new QueryStringParser();
|
|
||||||
|
|
||||||
private final FormHttpMessageReader formDataReader = new FormHttpMessageReader();
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public OperationRequest convert(ExchangeResult result) {
|
public OperationRequest convert(ExchangeResult result) {
|
||||||
HttpHeaders headers = extractRequestHeaders(result);
|
HttpHeaders headers = extractRequestHeaders(result);
|
||||||
return new OperationRequestFactory().create(result.getUrl(), result.getMethod(), result.getRequestBodyContent(),
|
return new OperationRequestFactory().create(result.getUrl(), result.getMethod(), result.getRequestBodyContent(),
|
||||||
headers, extractParameters(result), extractRequestParts(result), extractCookies(headers));
|
headers, extractRequestParts(result), extractCookies(headers));
|
||||||
}
|
}
|
||||||
|
|
||||||
private HttpHeaders extractRequestHeaders(ExchangeResult result) {
|
private HttpHeaders extractRequestHeaders(ExchangeResult result) {
|
||||||
@@ -80,16 +68,6 @@ class WebTestClientRequestConverter implements RequestConverter<ExchangeResult>
|
|||||||
return extracted;
|
return extracted;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Parameters extractParameters(ExchangeResult result) {
|
|
||||||
Parameters parameters = new Parameters();
|
|
||||||
parameters.addAll(this.queryStringParser.parse(result.getUrl()));
|
|
||||||
if (MediaType.APPLICATION_FORM_URLENCODED.isCompatibleWith(result.getRequestHeaders().getContentType())) {
|
|
||||||
parameters.addAll(this.formDataReader
|
|
||||||
.readMono(FORM_DATA_TYPE, new ExchangeResultReactiveHttpInputMessage(result), null).block());
|
|
||||||
}
|
|
||||||
return parameters;
|
|
||||||
}
|
|
||||||
|
|
||||||
private List<OperationRequestPart> extractRequestParts(ExchangeResult result) {
|
private List<OperationRequestPart> extractRequestParts(ExchangeResult result) {
|
||||||
HttpMessageReader<Part> partHttpMessageReader = new DefaultPartHttpMessageReader();
|
HttpMessageReader<Part> partHttpMessageReader = new DefaultPartHttpMessageReader();
|
||||||
return new MultipartHttpMessageReader(partHttpMessageReader)
|
return new MultipartHttpMessageReader(partHttpMessageReader)
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
package org.springframework.restdocs.webtestclient;
|
package org.springframework.restdocs.webtestclient;
|
||||||
|
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
@@ -103,15 +104,12 @@ public class WebTestClientRequestConverterTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void getRequestWithQueryStringPopulatesParameters() {
|
public void getRequestWithQueryString() {
|
||||||
ExchangeResult result = WebTestClient.bindToRouterFunction(RouterFunctions.route(GET("/foo"), (req) -> null))
|
ExchangeResult result = WebTestClient.bindToRouterFunction(RouterFunctions.route(GET("/foo"), (req) -> null))
|
||||||
.configureClient().baseUrl("http://localhost").build().get().uri("/foo?a=alpha&b=bravo").exchange()
|
.configureClient().baseUrl("http://localhost").build().get().uri("/foo?a=alpha&b=bravo").exchange()
|
||||||
.expectBody().returnResult();
|
.expectBody().returnResult();
|
||||||
OperationRequest request = this.converter.convert(result);
|
OperationRequest request = this.converter.convert(result);
|
||||||
assertThat(request.getUri()).isEqualTo(URI.create("http://localhost/foo?a=alpha&b=bravo"));
|
assertThat(request.getUri()).isEqualTo(URI.create("http://localhost/foo?a=alpha&b=bravo"));
|
||||||
assertThat(request.getParameters()).hasSize(2);
|
|
||||||
assertThat(request.getParameters()).containsEntry("a", Arrays.asList("alpha"));
|
|
||||||
assertThat(request.getParameters()).containsEntry("b", Arrays.asList("bravo"));
|
|
||||||
assertThat(request.getMethod()).isEqualTo(HttpMethod.GET);
|
assertThat(request.getMethod()).isEqualTo(HttpMethod.GET);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -128,9 +126,9 @@ public class WebTestClientRequestConverterTests {
|
|||||||
OperationRequest request = this.converter.convert(result);
|
OperationRequest request = this.converter.convert(result);
|
||||||
assertThat(request.getUri()).isEqualTo(URI.create("http://localhost/foo"));
|
assertThat(request.getUri()).isEqualTo(URI.create("http://localhost/foo"));
|
||||||
assertThat(request.getMethod()).isEqualTo(HttpMethod.POST);
|
assertThat(request.getMethod()).isEqualTo(HttpMethod.POST);
|
||||||
assertThat(request.getParameters()).hasSize(2);
|
assertThat(request.getContentAsString()).isEqualTo("a=alpha&a=apple&b=br%26vo");
|
||||||
assertThat(request.getParameters()).containsEntry("a", Arrays.asList("alpha", "apple"));
|
assertThat(request.getHeaders().getContentType())
|
||||||
assertThat(request.getParameters()).containsEntry("b", Arrays.asList("br&vo"));
|
.isEqualTo(new MediaType(MediaType.APPLICATION_FORM_URLENCODED, StandardCharsets.UTF_8));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -144,9 +142,6 @@ public class WebTestClientRequestConverterTests {
|
|||||||
OperationRequest request = this.converter.convert(result);
|
OperationRequest request = this.converter.convert(result);
|
||||||
assertThat(request.getUri()).isEqualTo(URI.create("http://localhost/foo?a=alpha&a=apple&b=br%26vo"));
|
assertThat(request.getUri()).isEqualTo(URI.create("http://localhost/foo?a=alpha&a=apple&b=br%26vo"));
|
||||||
assertThat(request.getMethod()).isEqualTo(HttpMethod.POST);
|
assertThat(request.getMethod()).isEqualTo(HttpMethod.POST);
|
||||||
assertThat(request.getParameters()).hasSize(2);
|
|
||||||
assertThat(request.getParameters()).containsEntry("a", Arrays.asList("alpha", "apple"));
|
|
||||||
assertThat(request.getParameters()).containsEntry("b", Arrays.asList("br&vo"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -162,9 +157,9 @@ public class WebTestClientRequestConverterTests {
|
|||||||
OperationRequest request = this.converter.convert(result);
|
OperationRequest request = this.converter.convert(result);
|
||||||
assertThat(request.getUri()).isEqualTo(URI.create("http://localhost/foo?a=alpha&b=br%26vo"));
|
assertThat(request.getUri()).isEqualTo(URI.create("http://localhost/foo?a=alpha&b=br%26vo"));
|
||||||
assertThat(request.getMethod()).isEqualTo(HttpMethod.POST);
|
assertThat(request.getMethod()).isEqualTo(HttpMethod.POST);
|
||||||
assertThat(request.getParameters()).hasSize(2);
|
assertThat(request.getContentAsString()).isEqualTo("a=apple");
|
||||||
assertThat(request.getParameters()).containsEntry("a", Arrays.asList("alpha", "apple"));
|
assertThat(request.getHeaders().getContentType())
|
||||||
assertThat(request.getParameters()).containsEntry("b", Arrays.asList("br&vo"));
|
.isEqualTo(new MediaType(MediaType.APPLICATION_FORM_URLENCODED, StandardCharsets.UTF_8));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ import static org.assertj.core.api.Assertions.fail;
|
|||||||
import static org.springframework.restdocs.request.RequestDocumentation.parameterWithName;
|
import static org.springframework.restdocs.request.RequestDocumentation.parameterWithName;
|
||||||
import static org.springframework.restdocs.request.RequestDocumentation.partWithName;
|
import static org.springframework.restdocs.request.RequestDocumentation.partWithName;
|
||||||
import static org.springframework.restdocs.request.RequestDocumentation.pathParameters;
|
import static org.springframework.restdocs.request.RequestDocumentation.pathParameters;
|
||||||
import static org.springframework.restdocs.request.RequestDocumentation.requestParameters;
|
import static org.springframework.restdocs.request.RequestDocumentation.queryParameters;
|
||||||
import static org.springframework.restdocs.request.RequestDocumentation.requestParts;
|
import static org.springframework.restdocs.request.RequestDocumentation.requestParts;
|
||||||
import static org.springframework.restdocs.webtestclient.WebTestClientRestDocumentation.document;
|
import static org.springframework.restdocs.webtestclient.WebTestClientRestDocumentation.document;
|
||||||
import static org.springframework.restdocs.webtestclient.WebTestClientRestDocumentation.documentationConfiguration;
|
import static org.springframework.restdocs.webtestclient.WebTestClientRestDocumentation.documentationConfiguration;
|
||||||
@@ -122,12 +122,11 @@ public class WebTestClientRestDocumentationIntegrationTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void requestParametersSnippet() {
|
public void queryParametersSnippet() {
|
||||||
this.webTestClient.get().uri("/?a=alpha&b=bravo").exchange().expectStatus().isOk().expectBody()
|
this.webTestClient.get().uri("/?a=alpha&b=bravo").exchange().expectStatus().isOk().expectBody().consumeWith(
|
||||||
.consumeWith(document("request-parameters",
|
document("query-parameters", queryParameters(parameterWithName("a").description("Alpha description"),
|
||||||
requestParameters(parameterWithName("a").description("Alpha description"),
|
parameterWithName("b").description("Bravo description"))));
|
||||||
parameterWithName("b").description("Bravo description"))));
|
assertThat(new File("build/generated-snippets/query-parameters/query-parameters.adoc"))
|
||||||
assertThat(new File("build/generated-snippets/request-parameters/request-parameters.adoc"))
|
|
||||||
.has(content(tableWithHeader(TemplateFormats.asciidoctor(), "Parameter", "Description")
|
.has(content(tableWithHeader(TemplateFormats.asciidoctor(), "Parameter", "Description")
|
||||||
.row("`a`", "Alpha description").row("`b`", "Bravo description")));
|
.row("`a`", "Alpha description").row("`b`", "Bravo description")));
|
||||||
}
|
}
|
||||||
@@ -204,7 +203,7 @@ public class WebTestClientRestDocumentationIntegrationTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private Condition<File> content(final Condition<String> delegate) {
|
private Condition<File> content(final Condition<String> delegate) {
|
||||||
return new Condition<File>() {
|
return new Condition<>() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean matches(File value) {
|
public boolean matches(File value) {
|
||||||
|
|||||||
Reference in New Issue
Block a user