Skip to content

Commit 081aca1

Browse files
authored
Merge branch 'master' into issue-1715
2 parents e0fdd8f + e31007f commit 081aca1

File tree

10 files changed

+205
-12
lines changed

10 files changed

+205
-12
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,4 @@ modules/swagger-parser/src/test/resources/relative-file-references/yaml
1212
**/test-output/*
1313
dependency-reduced-pom.xml
1414
*.pyc
15+
/bin/

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -261,7 +261,7 @@ components:
261261
example: Example value
262262
```
263263

264-
#### 3. flatten :
264+
#### 3. flatten:
265265

266266
```java
267267
ParseOptions parseOptions = new ParseOptions();

modules/swagger-parser-core/src/main/java/io/swagger/v3/parser/core/models/ParseOptions.java

+15-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@ public class ParseOptions {
1212
private boolean validateExternalRefs = false;
1313
private boolean validateInternalRefs = true;
1414
private boolean legacyYamlDeserialization = false;
15-
15+
private boolean resolveRequestBody = false;
16+
1617
public boolean isResolve() {
1718
return resolve;
1819
}
@@ -36,6 +37,19 @@ public boolean isResolveFully() {
3637
public void setResolveFully(boolean resolveFully) {
3738
this.resolveFully = resolveFully;
3839
}
40+
41+
public boolean isResolveRequestBody() {
42+
return resolveRequestBody;
43+
}
44+
45+
/**
46+
* If set to true, will help resolving the requestBody as inline, provided
47+
* resolve is also set to true. Default is false because of the existing
48+
* behaviour.
49+
*/
50+
public void setResolveRequestBody(boolean resolveRequestBody) {
51+
this.resolveRequestBody = resolveRequestBody;
52+
}
3953

4054
public boolean isFlatten() { return flatten; }
4155

modules/swagger-parser-v3/src/main/java/io/swagger/v3/parser/ResolverCache.java

+6-2
Original file line numberDiff line numberDiff line change
@@ -68,12 +68,12 @@ public class ResolverCache {
6868
private Map<String, String> externalFileCache = new HashMap<>();
6969
private List<String> referencedModelKeys = new ArrayList<>();
7070
private Set<String> resolveValidationMessages;
71-
7271
private final ParseOptions parseOptions;
7372

7473

7574
/*
76-
a map that stores original external references, and their associated renamed references
75+
* a map that stores original external references, and their associated renamed
76+
* references
7777
*/
7878
private Map<String, String> renameCache = new HashMap<>();
7979

@@ -394,4 +394,8 @@ public Map<String, String> getExternalFileCache() {
394394
public Map<String, String> getRenameCache() {
395395
return Collections.unmodifiableMap(renameCache);
396396
}
397+
398+
public ParseOptions getParseOptions() {
399+
return parseOptions;
400+
}
397401
}

modules/swagger-parser-v3/src/main/java/io/swagger/v3/parser/processors/OperationProcessor.java

+16-5
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@ public OperationProcessor(ResolverCache cache, OpenAPI openAPI) {
3131
this.responseProcessor = new ResponseProcessor(cache,openAPI);
3232
this.requestBodyProcessor = new RequestBodyProcessor(cache,openAPI);
3333
this.externalRefProcessor = new ExternalRefProcessor(cache, openAPI);
34-
3534
this.cache = cache;
3635
}
3736

@@ -40,18 +39,30 @@ public void processOperation(Operation operation) {
4039
if(processedOperationParameters != null) {
4140
operation.setParameters(processedOperationParameters);
4241
}
43-
final RequestBody requestBody = operation.getRequestBody();
44-
if(requestBody != null) {
42+
43+
RequestBody requestBody = operation.getRequestBody();
44+
if (requestBody != null) {
45+
// This part allows paser to put requestBody inline without the resolveFully
46+
// option set to true
47+
if (requestBody.get$ref() != null && cache != null && cache.getParseOptions() != null && cache.getParseOptions().isResolveRequestBody()) {
48+
requestBodyProcessor.processRequestBody(requestBody);
49+
RefFormat refFormat = computeRefFormat(requestBody.get$ref());
50+
RequestBody resolvedRequestBody = cache.loadRef(requestBody.get$ref(), refFormat, RequestBody.class);
51+
52+
if (resolvedRequestBody != null) {
53+
requestBody = resolvedRequestBody;
54+
operation.setRequestBody(resolvedRequestBody);
55+
}
56+
}
4557
requestBodyProcessor.processRequestBody(requestBody);
4658
}
4759

48-
4960
final Map<String, ApiResponse> responses = operation.getResponses();
5061
if (responses != null) {
5162
for (String responseCode : responses.keySet()) {
5263
ApiResponse response = responses.get(responseCode);
5364
if(response != null) {
54-
//This part allows parser to put response schema inline without the resolveFully option set to true
65+
//This part allows parser to put response inline without the resolveFully option set to true
5566
if (response.get$ref() != null) {
5667

5768
responseProcessor.processResponse(response);

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

+6-3
Original file line numberDiff line numberDiff line change
@@ -621,9 +621,12 @@ public Paths getPaths(ObjectNode obj, String location, ParseResult result) {
621621
}
622622
ObjectNode path = (ObjectNode) pathValue;
623623
PathItem pathObj = getPathItem(path, String.format("%s.'%s'", location, pathName), result);
624-
String[] eachPart = pathName.split("[-/.]+");
625-
Arrays.stream(eachPart)
626-
.filter(part -> part.startsWith("{") && part.endsWith("}") && part.length() > 2)
624+
List<String> eachPart = new ArrayList<>();
625+
Matcher m = Pattern.compile("\\{(.+?)\\}").matcher(pathName);
626+
while (m.find()) {
627+
eachPart.add(m.group());
628+
}
629+
eachPart.stream()
627630
.forEach(part -> {
628631
String pathParam = part.substring(1, part.length() - 1);
629632
boolean definedInPathLevel = isPathParamDefined(pathParam,

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

+24
Original file line numberDiff line numberDiff line change
@@ -595,6 +595,30 @@ public void testIssue1170(@Injectable final List<AuthorizationValue> auths) {
595595
assertTrue(colouringPropertySchema == colouringsSchema);
596596

597597
}
598+
599+
@Test
600+
public void testIssue1706() {
601+
String path = "/issue-1706/SimpleRequestResponseRef.json";
602+
603+
ParseOptions options = new ParseOptions();
604+
options.setResolve(true);
605+
// Added this parseOption to make requestBody inline in the operation resolve processing flow.
606+
options.setResolveRequestBody(true);
607+
608+
OpenAPI openAPI = new OpenAPIV3Parser().readLocation(path, null, options).getOpenAPI();
609+
610+
// RequestBody should be inline
611+
assertTrue(openAPI.getPaths().get("/resource").getPost().getRequestBody().get$ref() == null);
612+
assertTrue(openAPI.getPaths().get("/resource").getPost().getRequestBody().getContent() != null);
613+
assertTrue(openAPI.getPaths().get("/resource").getPost().getRequestBody().getContent().get("application/json").getSchema() instanceof ObjectSchema);
614+
615+
// Responses are already by default made inline in case referenced.
616+
assertTrue(openAPI.getPaths().get("/resource").getPost().getResponses().get("200").get$ref() == null);
617+
assertTrue(openAPI.getPaths().get("/resource").getPost().getResponses().get("200").getContent() != null);
618+
assertTrue(openAPI.getPaths().get("/resource").getPost().getResponses().get("200").getContent().get("application/json").getSchema() instanceof ObjectSchema);
619+
}
620+
621+
598622

599623
@Test
600624
public void selfReferenceTest(@Injectable final List<AuthorizationValue> auths) {

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

+12
Original file line numberDiff line numberDiff line change
@@ -806,6 +806,18 @@ public void testIssue1169() {
806806
assertNotNull(apispec);
807807
}
808808

809+
@Test
810+
public void testIssue1169noSplit() {
811+
ParseOptions options = new ParseOptions();
812+
options.setResolve(true);
813+
SwaggerParseResult parseResult = new OpenAPIV3Parser().readLocation("issue1169-noSplit.yaml", null, options);
814+
assertTrue(parseResult.getMessages().size() == 0);
815+
OpenAPI apispec = parseResult.getOpenAPI();
816+
assertNotNull(apispec);
817+
}
818+
819+
820+
809821
@Test
810822
public void testIssue339() throws Exception {
811823
OpenAPIV3Parser openAPIV3Parser = new OpenAPIV3Parser();
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
{
2+
"openapi": "3.0.0",
3+
"info": {
4+
"version": "1.0",
5+
"title": "Resource service",
6+
"description": "Resource service"
7+
},
8+
"servers": [
9+
{
10+
"url": "http://localhost:8088/"
11+
}
12+
],
13+
"paths": {
14+
"/resource": {
15+
"post": {
16+
"summary": "postResource",
17+
"description": "postResource",
18+
"operationId": "post-resource",
19+
"parameters": [],
20+
"requestBody": {
21+
"$ref": "#/components/requestBodies/ResourceBodyPost"
22+
},
23+
"responses": {
24+
"200": {
25+
"$ref": "#/components/responses/ResourceSuccessResponse"
26+
}
27+
}
28+
}
29+
}
30+
},
31+
"components": {
32+
"requestBodies": {
33+
"ResourceBodyPost": {
34+
"content": {
35+
"application/json": {
36+
"schema": {
37+
"type": "object",
38+
"required": [
39+
"rqname"
40+
],
41+
"properties": {
42+
"rqname": {
43+
"type": "string"
44+
},
45+
"rqnumber": {
46+
"type": "integer",
47+
"format": "int32"
48+
},
49+
"rqflag": {
50+
"type": "boolean"
51+
}
52+
}
53+
}
54+
}
55+
}
56+
}
57+
},
58+
"responses": {
59+
"ResourceSuccessResponse": {
60+
"description": "a Element to be returned",
61+
"content": {
62+
"application/json": {
63+
"schema": {
64+
"type": "object",
65+
"required": [
66+
"rname"
67+
],
68+
"properties": {
69+
"rname": {
70+
"type": "string"
71+
},
72+
"rnumber": {
73+
"type": "integer",
74+
"format": "int32"
75+
},
76+
"rflag": {
77+
"type": "boolean"
78+
}
79+
}
80+
}
81+
}
82+
}
83+
}
84+
},
85+
"schemas": {
86+
87+
}
88+
}
89+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
openapi: 3.0.1
2+
info:
3+
title: Sample title
4+
version: 1.0.0
5+
servers:
6+
- url: /
7+
paths:
8+
/path_{p0}/{p1}{p2}/another-{p3}:
9+
put:
10+
parameters:
11+
- name: p0
12+
in: path
13+
required: true
14+
schema:
15+
type: string
16+
- name: p1
17+
in: path
18+
required: true
19+
schema:
20+
type: string
21+
- name: p2
22+
in: path
23+
required: true
24+
schema:
25+
type: string
26+
- name: p3
27+
in: path
28+
required: true
29+
schema:
30+
type: string
31+
responses:
32+
200:
33+
description: sample desc
34+
content: {}
35+
components: {}

0 commit comments

Comments
 (0)