Skip to content

Commit

Permalink
Merge pull request #1557 from johanra/master
Browse files Browse the repository at this point in the history
fix handling of relative references
  • Loading branch information
gracekarina authored Apr 27, 2021
2 parents aef028f + 167c386 commit 676f323
Show file tree
Hide file tree
Showing 8 changed files with 152 additions and 40 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ public void processPaths() {
String pathRef = pathItem.get$ref().split("#")[0];

if (resolvedPath != null) {
updateLocalRefs(resolvedPath, pathRef);
updateRefs(resolvedPath, pathRef);
//we need to put the resolved path into swagger object
openAPI.path(pathStr, resolvedPath);
pathItem = resolvedPath;
Expand Down Expand Up @@ -124,27 +124,27 @@ private void addParametersToEachOperation(PathItem pathItem) {
}
}

protected void updateLocalRefs(PathItem path, String pathRef) {
protected void updateRefs(PathItem path, String pathRef) {
if(path.getParameters() != null) {
List<Parameter> params = path.getParameters();
for(Parameter param : params) {
updateLocalRefs(param, pathRef);
updateRefs(param, pathRef);
}
}
List<Operation> ops = path.readOperations();
for(Operation op : ops) {
if(op.getParameters() != null) {
for (Parameter param : op.getParameters()) {
updateLocalRefs(param, pathRef);
updateRefs(param, pathRef);
}
}
if(op.getResponses() != null) {
for(ApiResponse response : op.getResponses().values()) {
updateLocalRefs(response, pathRef);
updateRefs(response, pathRef);
}
}
if (op.getRequestBody() != null){
updateLocalRefs(op.getRequestBody(),pathRef);
updateRefs(op.getRequestBody(),pathRef);
}
if (op.getCallbacks() != null){
Map<String,Callback> callbacks = op.getCallbacks();
Expand All @@ -153,83 +153,75 @@ protected void updateLocalRefs(PathItem path, String pathRef) {
if (callback != null) {
for(String callbackName : callback.keySet()) {
PathItem pathItem = callback.get(callbackName);
updateLocalRefs(pathItem,pathRef);
updateRefs(pathItem,pathRef);
}
}
}
}
}
}

protected void updateLocalRefs(ApiResponse response, String pathRef) {
protected void updateRefs(ApiResponse response, String pathRef) {
if (response.get$ref() != null){
if(isLocalRef(response.get$ref())) {
response.set$ref(computeLocalRef(response.get$ref(), pathRef));
}
response.set$ref(computeRef(response.get$ref(), pathRef));
}
if(response.getContent() != null) {
Map<String, MediaType> content = response.getContent();
for (String key: content.keySet()) {
MediaType mediaType = content.get(key);
if (mediaType.getSchema() != null) {
updateLocalRefs(mediaType.getSchema(), pathRef);
updateRefs(mediaType.getSchema(), pathRef);
}
Map<String, Example> examples = content.get(key).getExamples();
if (examples != null) {
for( Example example:examples.values()){
updateLocalRefs(example, pathRef);
updateRefs(example, pathRef);
}
}
}
}
}

protected void updateLocalRefs(Example example, String pathRef) {
protected void updateRefs(Example example, String pathRef) {
if(example.get$ref() != null) {
if(isLocalRef(example.get$ref())) {
example.set$ref(computeLocalRef(example.get$ref(), pathRef));
}
example.set$ref(computeRef(example.get$ref(), pathRef));
}
}

protected void updateLocalRefs(Parameter param, String pathRef) {
protected void updateRefs(Parameter param, String pathRef) {
if (param.get$ref() != null){
if(isLocalRef(param.get$ref())) {
param.set$ref(computeLocalRef(param.get$ref(), pathRef));
}
param.set$ref(computeRef(param.get$ref(), pathRef));
}
if(param.getSchema() != null) {
updateLocalRefs(param.getSchema(), pathRef);
updateRefs(param.getSchema(), pathRef);
}
if(param.getContent() != null) {
Map<String, MediaType> content = param.getContent();
for (String key: content.keySet()) {
MediaType mediaType = content.get(key);
if (mediaType.getSchema() != null) {
updateLocalRefs(mediaType.getSchema(), pathRef);
updateRefs(mediaType.getSchema(), pathRef);
}
}
}

}

protected void updateLocalRefs(RequestBody body, String pathRef) {
protected void updateRefs(RequestBody body, String pathRef) {
if (body.get$ref() != null){
if(isLocalRef(body.get$ref())) {
body.set$ref(computeLocalRef(body.get$ref(), pathRef));
}
body.set$ref(computeRef(body.get$ref(), pathRef));
}
if(body.getContent() != null) {
Map<String, MediaType> content = body.getContent();
for (String key: content.keySet()) {
MediaType mediaType = content.get(key);
if (mediaType.getSchema() != null) {
updateLocalRefs(mediaType.getSchema(), pathRef);
updateRefs(mediaType.getSchema(), pathRef);
}
Map<String, Example> examples = content.get(key).getExamples();
if (examples != null) {
for (Example example : examples.values()) {
updateLocalRefs(example, pathRef);
updateRefs(example, pathRef);
}
}
}
Expand All @@ -238,11 +230,9 @@ protected void updateLocalRefs(RequestBody body, String pathRef) {
}
}

protected void updateLocalRefs(Schema model, String pathRef) {
protected void updateRefs(Schema model, String pathRef) {
if(model.get$ref() != null) {
if(isLocalRef(model.get$ref())) {
model.set$ref(computeLocalRef(model.get$ref(), pathRef));
}
model.set$ref(computeRef(model.get$ref(), pathRef));
}
else if(model.getProperties() != null) {
// process properties
Expand All @@ -251,7 +241,7 @@ else if(model.getProperties() != null) {
for(String key : properties.keySet()) {
Schema property = properties.get(key);
if (property != null) {
updateLocalRefs(property, pathRef);
updateRefs(property, pathRef);
}
}
}
Expand All @@ -260,22 +250,22 @@ else if(model instanceof ComposedSchema) {
ComposedSchema composedSchema = (ComposedSchema) model;
if (composedSchema.getAllOf() != null) {
for (Schema innerModel : composedSchema.getAllOf()) {
updateLocalRefs(innerModel, pathRef);
updateRefs(innerModel, pathRef);
}
}if (composedSchema.getAnyOf() != null) {
for(Schema innerModel : composedSchema.getAnyOf()) {
updateLocalRefs(innerModel, pathRef);
updateRefs(innerModel, pathRef);
}
}if (composedSchema.getOneOf() != null) {
for (Schema innerModel : composedSchema.getOneOf()) {
updateLocalRefs(innerModel, pathRef);
updateRefs(innerModel, pathRef);
}
}
}
else if(model instanceof ArraySchema) {
ArraySchema arraySchema = (ArraySchema) model;
if(arraySchema.getItems() != null) {
updateLocalRefs(arraySchema.getItems(), pathRef);
updateRefs(arraySchema.getItems(), pathRef);
}
}
}
Expand All @@ -287,6 +277,27 @@ protected boolean isLocalRef(String ref) {
}
return false;
}

protected boolean isAbsoluteRef(String ref) {
if(ref.startsWith("./")) {
return true;
}
return false;
}

protected String computeRef(String ref, String prefix) {
if(isLocalRef(ref)) return computeLocalRef(ref, prefix);
if(isAbsoluteRef(ref)) return ref;
return computeRelativeRef(ref, prefix);
}

protected String computeRelativeRef(String ref, String prefix) {
int iIdxOfSlash = prefix.lastIndexOf('/');
if(iIdxOfSlash != -1) {
return prefix.substring(0, iIdxOfSlash+1) + ref;
}
return prefix + ref;
}

protected String computeLocalRef(String ref, String prefix) {
return prefix + ref;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
package io.swagger.v3.parser.test;




import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.parameters.RequestBody;
import io.swagger.v3.parser.OpenAPIV3Parser;
Expand All @@ -12,9 +10,15 @@
import io.swagger.v3.parser.util.RemoteUrl;
import mockit.Expectations;
import mockit.Mocked;

import org.testng.Assert;
import org.testng.annotations.Test;

import java.io.File;
import java.net.MalformedURLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;

import static org.testng.Assert.assertNotNull;
import static org.testng.Assert.assertTrue;
Expand Down Expand Up @@ -134,4 +138,21 @@ public void testIssue409() {
OpenAPI swagger = (new OpenAPIV3Parser().readContents(yaml,null, null)).getOpenAPI();
assertNotNull(swagger.getComponents().getSchemas().get("ID"));
}

@Test
public void testResolveRelativePaths() {
ParseOptions options = new ParseOptions();
options.setResolve(true);
SwaggerParseResult parseResult = new OpenAPIV3Parser().readLocation("/relative-references-example/openapi.yaml", null, options);

Assert.assertNotNull(parseResult.getOpenAPI());

HashSet<String> validationMessages = new HashSet<>(null != parseResult.getMessages() ? parseResult.getMessages() : new ArrayList<>());


//validationMessages.forEach(msg->System.out.println(msg));
//OpenAPI specification = parseResult.getOpenAPI();
Assert.assertTrue(validationMessages.isEmpty(), validationMessages.toString());

}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
description: unexpected error
content:
application/json:
schema:
$ref : "../_schemas/error.yaml"
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
type: object
properties:
code:
type: string
message:
type: string
required:
- code
- message
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
openapi: 3.0.1
info:
version: 1.0.0
title: x
description: desc
license:
name: public domain
contact:
name: API Support
url: http://www.example.com/support
email: [email protected]
paths:
/authorize:
$ref: 'security/_resources/authorize.yaml'
/login:
$ref: 'security/_resources/login.yaml'
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
post:
tags:
- Security
description: authorize the user
summary: authorize the user
operationId: authorize.user
responses:
"200":
description: authorize 200 response
content:
text/plain:
schema:
type: string
default:
$ref: '../../_responses/UnexpectedError.yaml'
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
post:
tags:
- Security
description: login
summary: login
operationId: login
parameters: []
requestBody:
content:
application/json:
schema:
$ref: '../_schemas/usernamepasswordcredentials.yaml'
application/x-www-form-urlencoded:
schema:
$ref: '../_schemas/usernamepasswordcredentials.yaml'
required: true
responses:
"200":
description: login 200 response
content:
application/json:
schema:
type: object
security: []
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
required:
- password
- username
type: object
properties:
password:
minLength: 1
type: string
username:
minLength: 1
type: string

0 comments on commit 676f323

Please sign in to comment.