Skip to content

Commit f238561

Browse files
committed
Fix for issue 911 in swagger parser v1
1 parent ed90b5d commit f238561

File tree

3 files changed

+111
-2
lines changed

3 files changed

+111
-2
lines changed

modules/swagger-parser/src/main/java/io/swagger/parser/util/SwaggerDeserializer.java

Lines changed: 59 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -186,16 +186,63 @@ public Map<String,Path> paths(ObjectNode obj, String location, ParseResult resul
186186
} else {
187187
ObjectNode path = (ObjectNode) pathValue;
188188
Path pathObj = path(path, location + ".'" + pathName + "'", result);
189+
String[] eachPart = pathName.split("/");
190+
for (String part : eachPart) {
191+
if (part.startsWith("{") && part.endsWith("}") && part.length() > 2) {
192+
String pathParam = part.substring(1, part.length() - 1);
193+
boolean definedInPathLevel = isPathParamDefined(pathParam, pathObj.getParameters());
194+
if (definedInPathLevel) {
195+
continue;
196+
}
197+
List<Operation> operationsInAPath = getAllOperationsInAPath(pathObj);
198+
for (Operation operation : operationsInAPath) {
199+
if (!isPathParamDefined(pathParam, operation.getParameters())) {
200+
result.warning(location + ".'" + pathName + "'"," Declared path parameter " + pathParam + " needs to be defined as a path parameter in path or operation level");
201+
break;
202+
}
203+
}
204+
}
205+
}
189206
output.put(pathName, pathObj);
190207
}
191208
}
192209
}
193210
return output;
194211
}
195212

213+
private boolean isPathParamDefined(String pathParam, List<Parameter> parameters) {
214+
if (parameters == null || parameters.isEmpty()) {
215+
return false;
216+
} else {
217+
for (Parameter parameter : parameters) {
218+
if (pathParam.equals(parameter.getName()) && "path".equals(parameter.getIn())) {
219+
return true;
220+
}
221+
}
222+
}
223+
return false;
224+
}
225+
226+
private void addToOperationsList(List<Operation> operationsList, Operation operation) {
227+
if (operation == null) {
228+
return;
229+
}
230+
operationsList.add(operation);
231+
}
232+
233+
private List<Operation> getAllOperationsInAPath(Path pathObj) {
234+
List<Operation> operations = new ArrayList<>();
235+
addToOperationsList(operations, pathObj.getGet());
236+
addToOperationsList(operations, pathObj.getPut());
237+
addToOperationsList(operations, pathObj.getPost());
238+
addToOperationsList(operations, pathObj.getPatch());
239+
addToOperationsList(operations, pathObj.getDelete());
240+
addToOperationsList(operations, pathObj.getOptions());
241+
addToOperationsList(operations, pathObj.getHead());
242+
return operations;
243+
}
244+
196245
public Path path(ObjectNode obj, String location, ParseResult result) {
197-
boolean hasRef = false;
198-
Path output = null;
199246
if(obj.get("$ref") != null) {
200247
JsonNode ref = obj.get("$ref");
201248
if(ref.getNodeType().equals(JsonNodeType.STRING)) {
@@ -1579,6 +1626,7 @@ protected static class ParseResult {
15791626
private Map<Location, JsonNode> extra = new LinkedHashMap<Location, JsonNode>();
15801627
private Map<Location, JsonNode> unsupported = new LinkedHashMap<Location, JsonNode>();
15811628
private Map<Location, String> invalidType = new LinkedHashMap<Location, String>();
1629+
private List<Location> warnings = new ArrayList<>();
15821630
private List<Location> missing = new ArrayList<Location>();
15831631

15841632
public ParseResult() {
@@ -1596,6 +1644,10 @@ public void missing(String location, String key) {
15961644
missing.add(new Location(location, key));
15971645
}
15981646

1647+
public void warning(String location, String key) {
1648+
warnings.add(new Location(location, key));
1649+
}
1650+
15991651
public void invalidType(String location, String key, String expectedType, JsonNode value){
16001652
invalidType.put(new Location(location, key), expectedType);
16011653
}
@@ -1661,6 +1713,11 @@ public List<String> getMessages() {
16611713
String message = "attribute " + location + l.key + " is missing";
16621714
messages.add(message);
16631715
}
1716+
for (Location l : warnings) {
1717+
String location = l.location.equals("") ? "" : l.location + ".";
1718+
String message = "attribute " + location +l.key;
1719+
messages.add(message);
1720+
}
16641721
for(Location l : unsupported.keySet()) {
16651722
String location = l.location.equals("") ? "" : l.location + ".";
16661723
String message = "attribute " + location + l.key + " is unsupported";

modules/swagger-parser/src/test/java/io/swagger/parser/util/SwaggerDeserializerTest.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1558,4 +1558,12 @@ public void testUntypedAdditionalProperties() {
15581558
assertTrue(additionalProperties instanceof UntypedProperty);
15591559
assertEquals(additionalProperties.getType(), null);
15601560
}
1561+
1562+
@Test
1563+
public void testIssue911() {
1564+
SwaggerDeserializationResult result = new SwaggerParser().readWithInfo("issue_911.yaml", null, true);
1565+
System.out.println(result.getMessages());
1566+
assertEquals(result.getMessages().size(),1);
1567+
assertNotNull(result.getSwagger());
1568+
}
15611569
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
swagger: 2.0
2+
info:
3+
description: >-
4+
This is a sample server Petstore server. You can find out more about
5+
Swagger at http://swagger.io or on
6+
irc.freenode.net, #swagger. For this sample, you can use the api key
7+
"special-key" to test the authorization filters
8+
version: 1.0.0
9+
title: Swagger Petstore
10+
termsOfService: 'http://swagger.io/terms/'
11+
contact:
12+
13+
license:
14+
name: Apache 2.0
15+
url: 'http://www.apache.org/licenses/LICENSE-2.0.html'
16+
externalDocs:
17+
description: Find more info here
18+
url: 'https://swagger.io'
19+
tags:
20+
- name: pet
21+
description: Pet Operations
22+
externalDocs:
23+
url: 'http://swagger.io'
24+
- name: user
25+
description: All about the Users
26+
paths:
27+
'/pet/{petId}/{pathParamNotDefined}':
28+
get:
29+
tags:
30+
- pet
31+
summary: Find pet by ID
32+
description: >-
33+
Returns a pet when ID < 10. ID > 10 or nonintegers will simulate API
34+
error conditions
35+
operationId: getPetById
36+
responses:
37+
200:
38+
description: 200 ok
39+
parameters:
40+
- name: petId
41+
in: path
42+
description: ID of pet that needs to be fetched
43+
required: true
44+
type: integer

0 commit comments

Comments
 (0)