Skip to content

Commit eed8227

Browse files
committed
Fix for issue 911
Not able to identify the missed path variables
1 parent a566237 commit eed8227

File tree

3 files changed

+119
-9
lines changed

3 files changed

+119
-9
lines changed

modules/swagger-parser-v3/src/main/java/io/swagger/v3/parser/util/OpenAPIDeserializer.java

Lines changed: 62 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -52,15 +52,7 @@
5252
import java.net.URI;
5353
import java.net.URISyntaxException;
5454
import java.net.URL;
55-
import java.util.ArrayList;
56-
import java.util.Arrays;
57-
import java.util.Iterator;
58-
import java.util.LinkedHashMap;
59-
import java.util.LinkedHashSet;
60-
import java.util.List;
61-
import java.util.Map;
62-
import java.util.Optional;
63-
import java.util.Set;
55+
import java.util.*;
6456
import java.util.stream.Collectors;
6557
import java.util.stream.Stream;
6658

@@ -526,13 +518,64 @@ public Paths getPaths(ObjectNode obj, String location, ParseResult result) {
526518
} else {
527519
ObjectNode path = (ObjectNode) pathValue;
528520
PathItem pathObj = getPathItem(path,String.format("%s.'%s'", location,pathName), result);
521+
String[] eachPart = pathName.split("/");
522+
Arrays.stream(eachPart)
523+
.filter(part -> part.startsWith("{") && part.endsWith("}") && part.length() > 2)
524+
.forEach(part -> {
525+
String pathParam = part.substring(1, part.length() - 1);
526+
boolean definedInPathLevel = isPathParamDefined(pathParam, pathObj.getParameters());
527+
if (!definedInPathLevel) {
528+
List<Operation> operationsInAPath = getAllOperationsInAPath(pathObj);
529+
operationsInAPath.forEach(operation -> {
530+
if (!isPathParamDefined(pathParam, operation.getParameters())) {
531+
result.warning(location + ".'" + pathName + "'"," Declared path parameter " + pathParam + " needs to be defined as a path parameter in path or operation level");
532+
return;
533+
}
534+
});
535+
}
536+
});
529537
paths.put(pathName, pathObj);
530538
}
531539
}
532540
}
533541
return paths;
534542
}
535543

544+
private boolean isPathParamDefined(String pathParam, List<Parameter> parameters) {
545+
if (parameters == null || parameters.isEmpty()) {
546+
return false;
547+
} else {
548+
Parameter pathParamDefined = parameters.stream()
549+
.filter(parameter -> pathParam.equals(parameter.getName()))
550+
.findFirst()
551+
.orElse(null);
552+
if (pathParamDefined == null) {
553+
return false;
554+
}
555+
}
556+
return true;
557+
}
558+
559+
private void addToOperationsList(List<Operation> operationsList, Operation operation) {
560+
if (operation == null) {
561+
return;
562+
}
563+
operationsList.add(operation);
564+
}
565+
566+
public List<Operation> getAllOperationsInAPath(PathItem pathObj) {
567+
List<Operation> operations = new ArrayList<>();
568+
addToOperationsList(operations, pathObj.getGet());
569+
addToOperationsList(operations, pathObj.getPut());
570+
addToOperationsList(operations, pathObj.getPost());
571+
addToOperationsList(operations, pathObj.getPatch());
572+
addToOperationsList(operations, pathObj.getDelete());
573+
addToOperationsList(operations, pathObj.getTrace());
574+
addToOperationsList(operations, pathObj.getOptions());
575+
addToOperationsList(operations, pathObj.getHead());
576+
return operations;
577+
}
578+
536579
public PathItem getPathItem(ObjectNode obj, String location, ParseResult result) {
537580

538581

@@ -2669,6 +2712,7 @@ protected static class ParseResult {
26692712
private Map<Location, JsonNode> extra = new LinkedHashMap<>();
26702713
private Map<Location, JsonNode> unsupported = new LinkedHashMap<>();
26712714
private Map<Location, String> invalidType = new LinkedHashMap<>();
2715+
private List<Location> warnings = new ArrayList<>();
26722716
private List<Location> missing = new ArrayList<>();
26732717

26742718
public ParseResult() {
@@ -2686,6 +2730,10 @@ public void missing(String location, String key) {
26862730
missing.add(new Location(location, key));
26872731
}
26882732

2733+
public void warning(String location, String key) {
2734+
warnings.add(new Location(location, key));
2735+
}
2736+
26892737
public void invalidType(String location, String key, String expectedType, JsonNode value) {
26902738
invalidType.put(new Location(location, key), expectedType);
26912739
}
@@ -2715,6 +2763,11 @@ public List<String> getMessages() {
27152763
String message = "attribute " + location + l.key + " is missing";
27162764
messages.add(message);
27172765
}
2766+
for (Location l : warnings) {
2767+
String location = l.location.equals("") ? "" : l.location + ".";
2768+
String message = "attribute " + location +l.key;
2769+
messages.add(message);
2770+
}
27182771
for (Location l : unsupported.keySet()) {
27192772
String location = l.location.equals("") ? "" : l.location + ".";
27202773
String message = "attribute " + location + l.key + " is unsupported";

modules/swagger-parser-v3/src/test/java/io/swagger/v3/parser/test/OAIDeserializationTest.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import org.testng.annotations.Test;
88

99
import static org.testng.Assert.assertNotNull;
10+
import static org.testng.AssertJUnit.assertEquals;
1011

1112
public class OAIDeserializationTest {
1213
@Test
@@ -34,4 +35,12 @@ public void testDeserializeSimpleDefinition() throws Exception {
3435

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

0 commit comments

Comments
 (0)