Skip to content

Commit 280905b

Browse files
committed
Capturing pattern in identical paths only renders the path element of one method. Fixes #2823
1 parent 915a071 commit 280905b

File tree

4 files changed

+247
-12
lines changed

4 files changed

+247
-12
lines changed

springdoc-openapi-starter-common/src/main/java/org/springdoc/api/AbstractOpenApiResource.java

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
* * * *
2222
* * *
2323
* *
24-
*
24+
*
2525
*/
2626

2727
package org.springdoc.api;
@@ -635,19 +635,18 @@ protected void calculatePath(HandlerMethod handlerMethod, RouterOperation router
635635
// allow for customisation
636636
operation = customizeOperation(operation, handlerMethod);
637637

638-
PathItem pathItemObject = buildPathItem(requestMethod, operation, operationPath, paths);
639-
640-
if (!StringUtils.contains(operationPath, "**")) {
641-
if(StringUtils.contains(operationPath,"*")){
642-
Matcher matcher = pathPattern.matcher(operationPath);
643-
while (matcher.find()) {
644-
String pathParam = matcher.group(1);
645-
String newPathParam = pathParam.replace("*", "");
646-
operationPath = operationPath.replace("{" + pathParam + "}", "{" + newPathParam + "}");
647-
}
638+
if (StringUtils.contains(operationPath, "*")) {
639+
Matcher matcher = pathPattern.matcher(operationPath);
640+
while (matcher.find()) {
641+
String pathParam = matcher.group(1);
642+
String newPathParam = pathParam.replace("*", "");
643+
operationPath = operationPath.replace("{" + pathParam + "}", "{" + newPathParam + "}");
648644
}
649-
paths.addPathItem(operationPath, pathItemObject);
650645
}
646+
647+
PathItem pathItemObject = buildPathItem(requestMethod, operation, operationPath, paths);
648+
if (!StringUtils.contains(operationPath, "**"))
649+
paths.addPathItem(operationPath, pathItemObject);
651650
}
652651
}
653652

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
/*
2+
*
3+
* *
4+
* * *
5+
* * * *
6+
* * * * *
7+
* * * * * * Copyright 2019-2024 the original author or authors.
8+
* * * * * *
9+
* * * * * * Licensed under the Apache License, Version 2.0 (the "License");
10+
* * * * * * you may not use this file except in compliance with the License.
11+
* * * * * * You may obtain a copy of the License at
12+
* * * * * *
13+
* * * * * * https://www.apache.org/licenses/LICENSE-2.0
14+
* * * * * *
15+
* * * * * * Unless required by applicable law or agreed to in writing, software
16+
* * * * * * distributed under the License is distributed on an "AS IS" BASIS,
17+
* * * * * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18+
* * * * * * See the License for the specific language governing permissions and
19+
* * * * * * limitations under the License.
20+
* * * * *
21+
* * * *
22+
* * *
23+
* *
24+
*
25+
*/
26+
27+
package test.org.springdoc.api.v30.app235;
28+
29+
import io.swagger.v3.oas.annotations.tags.Tag;
30+
31+
import org.springframework.http.HttpStatus;
32+
import org.springframework.http.ResponseEntity;
33+
import org.springframework.validation.annotation.Validated;
34+
import org.springframework.web.bind.annotation.GetMapping;
35+
import org.springframework.web.bind.annotation.PostMapping;
36+
import org.springframework.web.bind.annotation.RequestMapping;
37+
import org.springframework.web.bind.annotation.RestController;
38+
39+
/**
40+
* @author bnasslahsen
41+
*/
42+
@Validated
43+
@RestController
44+
@RequestMapping("/api")
45+
@Tag(name = "Lorem ipsum")
46+
public class MyDebugController {
47+
@GetMapping(value = "/debug/{*wildcard}")
48+
public ResponseEntity<String> getWildcard(String wildcard) {
49+
return new ResponseEntity<>("", HttpStatus.NO_CONTENT);
50+
}
51+
52+
// THIS ONE IS MISSING
53+
@PostMapping(value = "/debug/{*wildcard}")
54+
public ResponseEntity<String> postWildcard(String wildcard) {
55+
return new ResponseEntity<>("", HttpStatus.NO_CONTENT);
56+
}
57+
58+
@GetMapping(value = "/debug/{simple}")
59+
public ResponseEntity<String> get(String simple) {
60+
return new ResponseEntity<>("", HttpStatus.NO_CONTENT);
61+
}
62+
63+
@PostMapping(value = "/debug/{simple}")
64+
public ResponseEntity<String> post(String simple) {
65+
return new ResponseEntity<>("", HttpStatus.NO_CONTENT);
66+
}
67+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
/*
2+
*
3+
* *
4+
* * *
5+
* * * *
6+
* * * * *
7+
* * * * * * Copyright 2019-2024 the original author or authors.
8+
* * * * * *
9+
* * * * * * Licensed under the Apache License, Version 2.0 (the "License");
10+
* * * * * * you may not use this file except in compliance with the License.
11+
* * * * * * You may obtain a copy of the License at
12+
* * * * * *
13+
* * * * * * https://www.apache.org/licenses/LICENSE-2.0
14+
* * * * * *
15+
* * * * * * Unless required by applicable law or agreed to in writing, software
16+
* * * * * * distributed under the License is distributed on an "AS IS" BASIS,
17+
* * * * * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18+
* * * * * * See the License for the specific language governing permissions and
19+
* * * * * * limitations under the License.
20+
* * * * *
21+
* * * *
22+
* * *
23+
* *
24+
*
25+
*/
26+
27+
package test.org.springdoc.api.v30.app235;
28+
29+
import test.org.springdoc.api.v30.AbstractSpringDocV30Test;
30+
31+
import org.springframework.boot.autoconfigure.SpringBootApplication;
32+
33+
public class SpringDocApp235Test extends AbstractSpringDocV30Test {
34+
35+
@SpringBootApplication
36+
static class SpringDocTestApp {}
37+
}
Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
{
2+
"openapi": "3.0.1",
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+
"/api/debug/{simple}": {
15+
"get": {
16+
"tags": [
17+
"Lorem ipsum"
18+
],
19+
"operationId": "get",
20+
"parameters": [
21+
{
22+
"name": "simple",
23+
"in": "query",
24+
"required": true,
25+
"schema": {
26+
"type": "string"
27+
}
28+
}
29+
],
30+
"responses": {
31+
"200": {
32+
"description": "OK",
33+
"content": {
34+
"*/*": {
35+
"schema": {
36+
"type": "string"
37+
}
38+
}
39+
}
40+
}
41+
}
42+
},
43+
"post": {
44+
"tags": [
45+
"Lorem ipsum"
46+
],
47+
"operationId": "post",
48+
"parameters": [
49+
{
50+
"name": "simple",
51+
"in": "query",
52+
"required": true,
53+
"schema": {
54+
"type": "string"
55+
}
56+
}
57+
],
58+
"responses": {
59+
"200": {
60+
"description": "OK",
61+
"content": {
62+
"*/*": {
63+
"schema": {
64+
"type": "string"
65+
}
66+
}
67+
}
68+
}
69+
}
70+
}
71+
},
72+
"/api/debug/{wildcard}": {
73+
"get": {
74+
"tags": [
75+
"Lorem ipsum"
76+
],
77+
"operationId": "getWildcard",
78+
"parameters": [
79+
{
80+
"name": "wildcard",
81+
"in": "query",
82+
"required": true,
83+
"schema": {
84+
"type": "string"
85+
}
86+
}
87+
],
88+
"responses": {
89+
"200": {
90+
"description": "OK",
91+
"content": {
92+
"*/*": {
93+
"schema": {
94+
"type": "string"
95+
}
96+
}
97+
}
98+
}
99+
}
100+
},
101+
"post": {
102+
"tags": [
103+
"Lorem ipsum"
104+
],
105+
"operationId": "postWildcard",
106+
"parameters": [
107+
{
108+
"name": "wildcard",
109+
"in": "query",
110+
"required": true,
111+
"schema": {
112+
"type": "string"
113+
}
114+
}
115+
],
116+
"responses": {
117+
"200": {
118+
"description": "OK",
119+
"content": {
120+
"*/*": {
121+
"schema": {
122+
"type": "string"
123+
}
124+
}
125+
}
126+
}
127+
}
128+
}
129+
}
130+
},
131+
"components": {}
132+
}

0 commit comments

Comments
 (0)