Skip to content

Commit 4ebf8c6

Browse files
authored
Merge branch 'master' into patch-1
2 parents c458b65 + 676f323 commit 4ebf8c6

File tree

8 files changed

+152
-40
lines changed

8 files changed

+152
-40
lines changed

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

Lines changed: 49 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ public void processPaths() {
6565
String pathRef = pathItem.get$ref().split("#")[0];
6666

6767
if (resolvedPath != null) {
68-
updateLocalRefs(resolvedPath, pathRef);
68+
updateRefs(resolvedPath, pathRef);
6969
//we need to put the resolved path into swagger object
7070
openAPI.path(pathStr, resolvedPath);
7171
pathItem = resolvedPath;
@@ -124,27 +124,27 @@ private void addParametersToEachOperation(PathItem pathItem) {
124124
}
125125
}
126126

127-
protected void updateLocalRefs(PathItem path, String pathRef) {
127+
protected void updateRefs(PathItem path, String pathRef) {
128128
if(path.getParameters() != null) {
129129
List<Parameter> params = path.getParameters();
130130
for(Parameter param : params) {
131-
updateLocalRefs(param, pathRef);
131+
updateRefs(param, pathRef);
132132
}
133133
}
134134
List<Operation> ops = path.readOperations();
135135
for(Operation op : ops) {
136136
if(op.getParameters() != null) {
137137
for (Parameter param : op.getParameters()) {
138-
updateLocalRefs(param, pathRef);
138+
updateRefs(param, pathRef);
139139
}
140140
}
141141
if(op.getResponses() != null) {
142142
for(ApiResponse response : op.getResponses().values()) {
143-
updateLocalRefs(response, pathRef);
143+
updateRefs(response, pathRef);
144144
}
145145
}
146146
if (op.getRequestBody() != null){
147-
updateLocalRefs(op.getRequestBody(),pathRef);
147+
updateRefs(op.getRequestBody(),pathRef);
148148
}
149149
if (op.getCallbacks() != null){
150150
Map<String,Callback> callbacks = op.getCallbacks();
@@ -153,83 +153,75 @@ protected void updateLocalRefs(PathItem path, String pathRef) {
153153
if (callback != null) {
154154
for(String callbackName : callback.keySet()) {
155155
PathItem pathItem = callback.get(callbackName);
156-
updateLocalRefs(pathItem,pathRef);
156+
updateRefs(pathItem,pathRef);
157157
}
158158
}
159159
}
160160
}
161161
}
162162
}
163163

164-
protected void updateLocalRefs(ApiResponse response, String pathRef) {
164+
protected void updateRefs(ApiResponse response, String pathRef) {
165165
if (response.get$ref() != null){
166-
if(isLocalRef(response.get$ref())) {
167-
response.set$ref(computeLocalRef(response.get$ref(), pathRef));
168-
}
166+
response.set$ref(computeRef(response.get$ref(), pathRef));
169167
}
170168
if(response.getContent() != null) {
171169
Map<String, MediaType> content = response.getContent();
172170
for (String key: content.keySet()) {
173171
MediaType mediaType = content.get(key);
174172
if (mediaType.getSchema() != null) {
175-
updateLocalRefs(mediaType.getSchema(), pathRef);
173+
updateRefs(mediaType.getSchema(), pathRef);
176174
}
177175
Map<String, Example> examples = content.get(key).getExamples();
178176
if (examples != null) {
179177
for( Example example:examples.values()){
180-
updateLocalRefs(example, pathRef);
178+
updateRefs(example, pathRef);
181179
}
182180
}
183181
}
184182
}
185183
}
186184

187-
protected void updateLocalRefs(Example example, String pathRef) {
185+
protected void updateRefs(Example example, String pathRef) {
188186
if(example.get$ref() != null) {
189-
if(isLocalRef(example.get$ref())) {
190-
example.set$ref(computeLocalRef(example.get$ref(), pathRef));
191-
}
187+
example.set$ref(computeRef(example.get$ref(), pathRef));
192188
}
193189
}
194190

195-
protected void updateLocalRefs(Parameter param, String pathRef) {
191+
protected void updateRefs(Parameter param, String pathRef) {
196192
if (param.get$ref() != null){
197-
if(isLocalRef(param.get$ref())) {
198-
param.set$ref(computeLocalRef(param.get$ref(), pathRef));
199-
}
193+
param.set$ref(computeRef(param.get$ref(), pathRef));
200194
}
201195
if(param.getSchema() != null) {
202-
updateLocalRefs(param.getSchema(), pathRef);
196+
updateRefs(param.getSchema(), pathRef);
203197
}
204198
if(param.getContent() != null) {
205199
Map<String, MediaType> content = param.getContent();
206200
for (String key: content.keySet()) {
207201
MediaType mediaType = content.get(key);
208202
if (mediaType.getSchema() != null) {
209-
updateLocalRefs(mediaType.getSchema(), pathRef);
203+
updateRefs(mediaType.getSchema(), pathRef);
210204
}
211205
}
212206
}
213207

214208
}
215209

216-
protected void updateLocalRefs(RequestBody body, String pathRef) {
210+
protected void updateRefs(RequestBody body, String pathRef) {
217211
if (body.get$ref() != null){
218-
if(isLocalRef(body.get$ref())) {
219-
body.set$ref(computeLocalRef(body.get$ref(), pathRef));
220-
}
212+
body.set$ref(computeRef(body.get$ref(), pathRef));
221213
}
222214
if(body.getContent() != null) {
223215
Map<String, MediaType> content = body.getContent();
224216
for (String key: content.keySet()) {
225217
MediaType mediaType = content.get(key);
226218
if (mediaType.getSchema() != null) {
227-
updateLocalRefs(mediaType.getSchema(), pathRef);
219+
updateRefs(mediaType.getSchema(), pathRef);
228220
}
229221
Map<String, Example> examples = content.get(key).getExamples();
230222
if (examples != null) {
231223
for (Example example : examples.values()) {
232-
updateLocalRefs(example, pathRef);
224+
updateRefs(example, pathRef);
233225
}
234226
}
235227
}
@@ -238,11 +230,9 @@ protected void updateLocalRefs(RequestBody body, String pathRef) {
238230
}
239231
}
240232

241-
protected void updateLocalRefs(Schema model, String pathRef) {
233+
protected void updateRefs(Schema model, String pathRef) {
242234
if(model.get$ref() != null) {
243-
if(isLocalRef(model.get$ref())) {
244-
model.set$ref(computeLocalRef(model.get$ref(), pathRef));
245-
}
235+
model.set$ref(computeRef(model.get$ref(), pathRef));
246236
}
247237
else if(model.getProperties() != null) {
248238
// process properties
@@ -251,7 +241,7 @@ else if(model.getProperties() != null) {
251241
for(String key : properties.keySet()) {
252242
Schema property = properties.get(key);
253243
if (property != null) {
254-
updateLocalRefs(property, pathRef);
244+
updateRefs(property, pathRef);
255245
}
256246
}
257247
}
@@ -260,22 +250,22 @@ else if(model instanceof ComposedSchema) {
260250
ComposedSchema composedSchema = (ComposedSchema) model;
261251
if (composedSchema.getAllOf() != null) {
262252
for (Schema innerModel : composedSchema.getAllOf()) {
263-
updateLocalRefs(innerModel, pathRef);
253+
updateRefs(innerModel, pathRef);
264254
}
265255
}if (composedSchema.getAnyOf() != null) {
266256
for(Schema innerModel : composedSchema.getAnyOf()) {
267-
updateLocalRefs(innerModel, pathRef);
257+
updateRefs(innerModel, pathRef);
268258
}
269259
}if (composedSchema.getOneOf() != null) {
270260
for (Schema innerModel : composedSchema.getOneOf()) {
271-
updateLocalRefs(innerModel, pathRef);
261+
updateRefs(innerModel, pathRef);
272262
}
273263
}
274264
}
275265
else if(model instanceof ArraySchema) {
276266
ArraySchema arraySchema = (ArraySchema) model;
277267
if(arraySchema.getItems() != null) {
278-
updateLocalRefs(arraySchema.getItems(), pathRef);
268+
updateRefs(arraySchema.getItems(), pathRef);
279269
}
280270
}
281271
}
@@ -287,6 +277,27 @@ protected boolean isLocalRef(String ref) {
287277
}
288278
return false;
289279
}
280+
281+
protected boolean isAbsoluteRef(String ref) {
282+
if(ref.startsWith("./")) {
283+
return true;
284+
}
285+
return false;
286+
}
287+
288+
protected String computeRef(String ref, String prefix) {
289+
if(isLocalRef(ref)) return computeLocalRef(ref, prefix);
290+
if(isAbsoluteRef(ref)) return ref;
291+
return computeRelativeRef(ref, prefix);
292+
}
293+
294+
protected String computeRelativeRef(String ref, String prefix) {
295+
int iIdxOfSlash = prefix.lastIndexOf('/');
296+
if(iIdxOfSlash != -1) {
297+
return prefix.substring(0, iIdxOfSlash+1) + ref;
298+
}
299+
return prefix + ref;
300+
}
290301

291302
protected String computeLocalRef(String ref, String prefix) {
292303
return prefix + ref;

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

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
package io.swagger.v3.parser.test;
22

33

4-
5-
64
import io.swagger.v3.oas.models.OpenAPI;
75
import io.swagger.v3.oas.models.parameters.RequestBody;
86
import io.swagger.v3.parser.OpenAPIV3Parser;
@@ -12,9 +10,15 @@
1210
import io.swagger.v3.parser.util.RemoteUrl;
1311
import mockit.Expectations;
1412
import mockit.Mocked;
13+
14+
import org.testng.Assert;
1515
import org.testng.annotations.Test;
1616

17+
import java.io.File;
18+
import java.net.MalformedURLException;
19+
import java.util.ArrayList;
1720
import java.util.Arrays;
21+
import java.util.HashSet;
1822

1923
import static org.testng.Assert.assertNotNull;
2024
import static org.testng.Assert.assertTrue;
@@ -134,4 +138,21 @@ public void testIssue409() {
134138
OpenAPI swagger = (new OpenAPIV3Parser().readContents(yaml,null, null)).getOpenAPI();
135139
assertNotNull(swagger.getComponents().getSchemas().get("ID"));
136140
}
141+
142+
@Test
143+
public void testResolveRelativePaths() {
144+
ParseOptions options = new ParseOptions();
145+
options.setResolve(true);
146+
SwaggerParseResult parseResult = new OpenAPIV3Parser().readLocation("/relative-references-example/openapi.yaml", null, options);
147+
148+
Assert.assertNotNull(parseResult.getOpenAPI());
149+
150+
HashSet<String> validationMessages = new HashSet<>(null != parseResult.getMessages() ? parseResult.getMessages() : new ArrayList<>());
151+
152+
153+
//validationMessages.forEach(msg->System.out.println(msg));
154+
//OpenAPI specification = parseResult.getOpenAPI();
155+
Assert.assertTrue(validationMessages.isEmpty(), validationMessages.toString());
156+
157+
}
137158
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
description: unexpected error
2+
content:
3+
application/json:
4+
schema:
5+
$ref : "../_schemas/error.yaml"
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
type: object
2+
properties:
3+
code:
4+
type: string
5+
message:
6+
type: string
7+
required:
8+
- code
9+
- message
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
openapi: 3.0.1
2+
info:
3+
version: 1.0.0
4+
title: x
5+
description: desc
6+
license:
7+
name: public domain
8+
contact:
9+
name: API Support
10+
url: http://www.example.com/support
11+
12+
paths:
13+
/authorize:
14+
$ref: 'security/_resources/authorize.yaml'
15+
/login:
16+
$ref: 'security/_resources/login.yaml'
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
post:
2+
tags:
3+
- Security
4+
description: authorize the user
5+
summary: authorize the user
6+
operationId: authorize.user
7+
responses:
8+
"200":
9+
description: authorize 200 response
10+
content:
11+
text/plain:
12+
schema:
13+
type: string
14+
default:
15+
$ref: '../../_responses/UnexpectedError.yaml'
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
post:
2+
tags:
3+
- Security
4+
description: login
5+
summary: login
6+
operationId: login
7+
parameters: []
8+
requestBody:
9+
content:
10+
application/json:
11+
schema:
12+
$ref: '../_schemas/usernamepasswordcredentials.yaml'
13+
application/x-www-form-urlencoded:
14+
schema:
15+
$ref: '../_schemas/usernamepasswordcredentials.yaml'
16+
required: true
17+
responses:
18+
"200":
19+
description: login 200 response
20+
content:
21+
application/json:
22+
schema:
23+
type: object
24+
security: []
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
required:
2+
- password
3+
- username
4+
type: object
5+
properties:
6+
password:
7+
minLength: 1
8+
type: string
9+
username:
10+
minLength: 1
11+
type: string

0 commit comments

Comments
 (0)