Skip to content

Commit 3d3e327

Browse files
committed
Allow requestBody creation for GET on openapi resource endpoint
1 parent fd2f9a4 commit 3d3e327

File tree

6 files changed

+208
-7
lines changed

6 files changed

+208
-7
lines changed

springdoc-openapi-common/src/main/java/org/springdoc/core/AbstractRequestService.java

+11-6
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@
6464
import org.apache.commons.lang3.ArrayUtils;
6565
import org.apache.commons.lang3.StringUtils;
6666
import org.apache.commons.lang3.reflect.FieldUtils;
67+
import org.springdoc.core.SpringDocConfigProperties.ApiDocs.OpenApiVersion;
6768
import org.springdoc.core.customizers.ParameterCustomizer;
6869
import org.springdoc.core.providers.JavadocProvider;
6970

@@ -291,7 +292,8 @@ public Operation build(HandlerMethod handlerMethod, RequestMethod requestMethod,
291292
}
292293

293294
if (!isParamToIgnore(methodParameter)) {
294-
parameter = buildParams(parameterInfo, components, requestMethod, methodAttributes.getJsonViewAnnotation());
295+
parameter = buildParams(parameterInfo, components, requestMethod, methodAttributes.getJsonViewAnnotation(),
296+
openAPI.getOpenapi());
295297
// Merge with the operation parameters
296298
parameter = GenericParameterService.mergeParameter(operationParameters, parameter);
297299
List<Annotation> parameterAnnotations = Arrays.asList(methodParameter.getParameterAnnotations());
@@ -305,7 +307,7 @@ public Operation build(HandlerMethod handlerMethod, RequestMethod requestMethod,
305307
}
306308
applyBeanValidatorAnnotations(parameter, parameterAnnotations);
307309
}
308-
else if (!RequestMethod.GET.equals(requestMethod)) {
310+
else if (!RequestMethod.GET.equals(requestMethod) || OpenApiVersion.OPENAPI_3_1.getVersion().equals(openAPI.getOpenapi())) {
309311
if (operation.getRequestBody() != null)
310312
requestBodyInfo.setRequestBody(operation.getRequestBody());
311313
requestBodyService.calculateRequestBodyInfo(components, methodAttributes,
@@ -488,10 +490,11 @@ public boolean isValidParameter(Parameter parameter) {
488490
* @param components the components
489491
* @param requestMethod the request method
490492
* @param jsonView the json view
493+
* @param openApiVersion the open api version
491494
* @return the parameter
492495
*/
493496
public Parameter buildParams(ParameterInfo parameterInfo, Components components,
494-
RequestMethod requestMethod, JsonView jsonView) {
497+
RequestMethod requestMethod, JsonView jsonView, String openApiVersion) {
495498
MethodParameter methodParameter = parameterInfo.getMethodParameter();
496499
if (parameterInfo.getParamType() != null) {
497500
if (!ValueConstants.DEFAULT_NONE.equals(parameterInfo.getDefaultValue()))
@@ -501,7 +504,7 @@ public Parameter buildParams(ParameterInfo parameterInfo, Components components,
501504
return this.buildParam(parameterInfo, components, jsonView);
502505
}
503506
// By default
504-
if (!isRequestBodyParam(requestMethod, parameterInfo)) {
507+
if (!isRequestBodyParam(requestMethod, parameterInfo, openApiVersion)) {
505508
parameterInfo.setRequired(!((DelegatingMethodParameter) methodParameter).isNotRequired() && !methodParameter.isOptional());
506509
parameterInfo.setParamType(QUERY_PARAM);
507510
parameterInfo.setDefaultValue(null);
@@ -715,13 +718,15 @@ private void applyValidationsToSchema(Map<String, Annotation> annos, Schema<?> s
715718
*
716719
* @param requestMethod the request method
717720
* @param parameterInfo the parameter info
721+
* @param openApiVersion the open api version
718722
* @return the boolean
719723
*/
720-
private boolean isRequestBodyParam(RequestMethod requestMethod, ParameterInfo parameterInfo) {
724+
private boolean isRequestBodyParam(RequestMethod requestMethod, ParameterInfo parameterInfo, String openApiVersion) {
721725
MethodParameter methodParameter = parameterInfo.getMethodParameter();
722726
DelegatingMethodParameter delegatingMethodParameter = (DelegatingMethodParameter) methodParameter;
727+
Boolean isBodyAllowed = !RequestMethod.GET.equals(requestMethod) || OpenApiVersion.OPENAPI_3_1.getVersion().equals(openApiVersion);
723728

724-
return (!RequestMethod.GET.equals(requestMethod) && (parameterInfo.getParameterModel() == null || parameterInfo.getParameterModel().getIn() == null) && !delegatingMethodParameter.isParameterObject())
729+
return (isBodyAllowed && (parameterInfo.getParameterModel() == null || parameterInfo.getParameterModel().getIn() == null) && !delegatingMethodParameter.isParameterObject())
725730
&&
726731
((methodParameter.getParameterAnnotation(io.swagger.v3.oas.annotations.parameters.RequestBody.class) != null
727732
|| methodParameter.getParameterAnnotation(org.springframework.web.bind.annotation.RequestBody.class) != null

springdoc-openapi-data-rest/src/main/java/org/springdoc/data/rest/core/DataRestRequestService.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,8 @@ else if (methodParameter.getParameterAnnotation(BackendId.class) != null) {
173173
parameterInfo.setParameterModel(parameter);
174174
}
175175
if (!ArrayUtils.isEmpty(methodParameter.getParameterAnnotations()))
176-
parameter = requestBuilder.buildParams(parameterInfo, openAPI.getComponents(), requestMethod, null);
176+
parameter = requestBuilder.buildParams(parameterInfo, openAPI.getComponents(), requestMethod, null,
177+
openAPI.getOpenapi());
177178

178179
addParameters(openAPI, requestMethod, methodAttributes, operation, methodParameter, parameterInfo, parameter);
179180
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
/*
2+
*
3+
* *
4+
* * *
5+
* * * * Copyright 2019-2022 the original author or authors.
6+
* * * *
7+
* * * * Licensed under the Apache License, Version 2.0 (the "License");
8+
* * * * you may not use this file except in compliance with the License.
9+
* * * * You may obtain a copy of the License at
10+
* * * *
11+
* * * * https://www.apache.org/licenses/LICENSE-2.0
12+
* * * *
13+
* * * * Unless required by applicable law or agreed to in writing, software
14+
* * * * distributed under the License is distributed on an "AS IS" BASIS,
15+
* * * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16+
* * * * See the License for the specific language governing permissions and
17+
* * * * limitations under the License.
18+
* * *
19+
* *
20+
*
21+
*/
22+
23+
package test.org.springdoc.api.v31.app6;
24+
25+
import java.time.Instant;
26+
27+
public class DummyData {
28+
29+
String trackerId;
30+
31+
Instant timestamp;
32+
33+
Double value;
34+
35+
public String getTrackerId() {
36+
return trackerId;
37+
}
38+
39+
public void setTrackerId(String trackerId) {
40+
this.trackerId = trackerId;
41+
}
42+
43+
public Instant getTimestamp() {
44+
return timestamp;
45+
}
46+
47+
public void setTimestamp(Instant timestamp) {
48+
this.timestamp = timestamp;
49+
}
50+
51+
public Double getValue() {
52+
return value;
53+
}
54+
55+
public void setValue(Double value) {
56+
this.value = value;
57+
}
58+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
/*
2+
*
3+
* *
4+
* * *
5+
* * * * Copyright 2019-2022 the original author or authors.
6+
* * * *
7+
* * * * Licensed under the Apache License, Version 2.0 (the "License");
8+
* * * * you may not use this file except in compliance with the License.
9+
* * * * You may obtain a copy of the License at
10+
* * * *
11+
* * * * https://www.apache.org/licenses/LICENSE-2.0
12+
* * * *
13+
* * * * Unless required by applicable law or agreed to in writing, software
14+
* * * * distributed under the License is distributed on an "AS IS" BASIS,
15+
* * * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16+
* * * * See the License for the specific language governing permissions and
17+
* * * * limitations under the License.
18+
* * *
19+
* *
20+
*
21+
*/
22+
23+
package test.org.springdoc.api.v31.app6;
24+
25+
import org.springframework.web.bind.annotation.GetMapping;
26+
import org.springframework.web.bind.annotation.RequestBody;
27+
import org.springframework.web.bind.annotation.RestController;
28+
import test.org.springdoc.api.v31.app4.TrackerData;
29+
30+
@RestController
31+
public class GetBodyController {
32+
33+
@GetMapping(value = "/get/body")
34+
DummyData getBody(@RequestBody DummyData dummyData) {
35+
return dummyData;
36+
37+
}
38+
39+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
/*
2+
*
3+
* *
4+
* * *
5+
* * * * Copyright 2019-2022 the original author or authors.
6+
* * * *
7+
* * * * Licensed under the Apache License, Version 2.0 (the "License");
8+
* * * * you may not use this file except in compliance with the License.
9+
* * * * You may obtain a copy of the License at
10+
* * * *
11+
* * * * https://www.apache.org/licenses/LICENSE-2.0
12+
* * * *
13+
* * * * Unless required by applicable law or agreed to in writing, software
14+
* * * * distributed under the License is distributed on an "AS IS" BASIS,
15+
* * * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16+
* * * * See the License for the specific language governing permissions and
17+
* * * * limitations under the License.
18+
* * *
19+
* *
20+
*
21+
*/
22+
23+
package test.org.springdoc.api.v31.app6;
24+
25+
import org.springframework.boot.autoconfigure.SpringBootApplication;
26+
import test.org.springdoc.api.v31.AbstractSpringDocV31Test;
27+
28+
public class SpringDocApp6Test extends AbstractSpringDocV31Test {
29+
30+
@SpringBootApplication
31+
static class SpringDocTestApp {
32+
33+
}
34+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
{
2+
"openapi": "3.1.0",
3+
"info": {
4+
"title": "OpenAPI definition",
5+
"version": "v0"
6+
},
7+
"servers": [
8+
{
9+
"url": "http://localhost",
10+
"description": "Generated server url"
11+
}
12+
],
13+
"paths": {
14+
"/get/body": {
15+
"get": {
16+
"tags": [
17+
"get-body-controller"
18+
],
19+
"operationId": "getBody",
20+
"requestBody": {
21+
"content": {
22+
"application/json": {
23+
"schema": {
24+
"$ref": "#/components/schemas/DummyData"
25+
}
26+
}
27+
},
28+
"required": true
29+
},
30+
"responses": {
31+
"200": {
32+
"description": "OK",
33+
"content": {
34+
"*/*": {
35+
"schema": {
36+
"$ref": "#/components/schemas/DummyData"
37+
}
38+
}
39+
}
40+
}
41+
}
42+
}
43+
}
44+
},
45+
"components": {
46+
"schemas": {
47+
"DummyData": {
48+
"properties": {
49+
"trackerId": {
50+
"type": "string"
51+
},
52+
"timestamp": {
53+
"type": "string",
54+
"format": "date-time"
55+
},
56+
"value": {
57+
"type": "number",
58+
"format": "double"
59+
}
60+
}
61+
}
62+
}
63+
}
64+
}

0 commit comments

Comments
 (0)