Skip to content

Commit

Permalink
possible fix for #1518
Browse files Browse the repository at this point in the history
In case $ref refers to path with parameter, using whole $ref in processRefSchema as externalFile argument results in URISyntaxException

java.net.URISyntaxException: Illegal character in fragment at index 49: ../v1/checkout.yml#/paths/~1checkout~1orderItem~1{orderItemId}
	at java.base/java.net.URI$Parser.fail(URI.java:2915)
	at java.base/java.net.URI$Parser.checkChars(URI.java:3086)
	at java.base/java.net.URI$Parser.parse(URI.java:3130)
	at java.base/java.net.URI.<init>(URI.java:600)
	at io.swagger.v3.parser.processors.ExternalRefProcessor.join(ExternalRefProcessor.java:977)
	at io.swagger.v3.parser.processors.ExternalRefProcessor.constructRef(ExternalRefProcessor.java:928)
	at io.swagger.v3.parser.processors.ExternalRefProcessor.processRefSchema(ExternalRefProcessor.java:918)
	at io.swagger.v3.parser.processors.ExternalRefProcessor.processRefSchemaObject(ExternalRefProcessor.java:867)
	at io.swagger.v3.parser.processors.ExternalRefProcessor.processRefToExternalPathItem(ExternalRefProcessor.java:280)
	at io.swagger.v3.parser.processors.PathsProcessor.processReferencePath(PathsProcessor.java:299)
	at io.swagger.v3.parser.processors.PathsProcessor.processPaths(PathsProcessor.java:63)
	at io.swagger.v3.parser.OpenAPIResolver.resolve(OpenAPIResolver.java:49)

Using only file part (without fragment) produces expected result.

fixing 1518 test

test for 1518

adding missing fils

removing duplicated code
  • Loading branch information
gracekarina committed May 6, 2021
1 parent 676f323 commit d7b066f
Show file tree
Hide file tree
Showing 28 changed files with 1,012 additions and 77 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,6 @@ public OpenAPI resolve() {
pathProcessor.processPaths();
componentsProcessor.processComponents();


if(openApi.getPaths() != null) {
for(String pathname : openApi.getPaths().keySet()) {
PathItem pathItem = openApi.getPaths().get(pathname);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ public <T> T loadRef(String ref, RefFormat refFormat, Class<T> expectedType) {
//we might have already resolved this ref, so check the resolutionCache
Object previouslyResolvedEntity = resolutionCache.get(ref);

if (previouslyResolvedEntity != null) {
if (previouslyResolvedEntity != null) {
if(expectedType.equals(Header.class)){
if (expectedType.getClass().equals(previouslyResolvedEntity.getClass())) {
return expectedType.cast(previouslyResolvedEntity);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,11 @@ public void processComponents() {
while(schemas.keySet().size() > keySet.size()) {
processSchemas(keySet, schemas);
}
//process any schema property unresolved
//processSchemas(keySet, schemas);



}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,19 +49,31 @@ public ExternalRefProcessor(ResolverCache cache, OpenAPI openAPI) {
this.openAPI = openAPI;
}

private String finalNameRec(Map<String, Schema> schemas, String possiblyConflictingDefinitionName, Schema newScema,
private String finalNameRec(Map<String, Schema> schemas, String possiblyConflictingDefinitionName, Schema newSchema,
int iteration) {
String tryName =
iteration == 0 ? possiblyConflictingDefinitionName : possiblyConflictingDefinitionName + "_" + iteration;
String tryName = null;
if(iteration == 0){
tryName = possiblyConflictingDefinitionName;
}else {
tryName = possiblyConflictingDefinitionName + "_" + iteration;
}

Schema existingModel = schemas.get(tryName);
//validate mayus and min.
if (existingModel != null) {
if (existingModel.get$ref() != null) {
// use the new model
existingModel = null;
} else if (!newScema.equals(existingModel)) {
} else if (!newSchema.equals(existingModel)) {
for(String key :cache.getResolutionCache().keySet()){
if (key.equals(newSchema.get$ref())){
return tryName;
}
}
LOGGER.debug("A model for " + existingModel + " already exists");
return finalNameRec(schemas, possiblyConflictingDefinitionName, newScema, ++iteration);
return finalNameRec(schemas, possiblyConflictingDefinitionName, newSchema, ++iteration);
}

}
return tryName;
}
Expand Down Expand Up @@ -93,104 +105,116 @@ public String processRefToExternalSchema(String $ref, RefFormat refFormat) {

final String possiblyConflictingDefinitionName = computeDefinitionName($ref);
newRef = finalNameRec(schemas, possiblyConflictingDefinitionName, schema, 0);
cache.putRenamedRef($ref, newRef);
Schema existingModel = schemas.get(newRef);
if(existingModel != null && existingModel.get$ref() != null) {
// validate the name
if(existingModel == null){
for(String name: schemas.keySet()){
if(name.toLowerCase().equals(newRef.toLowerCase())){
existingModel = schemas.get(name);
newRef = name;
break;
}
}
}
/*if(existingModel != null && existingModel.get$ref() != null) {
// use the new model
existingModel = null;
}

}*/
String file = $ref.split("#/")[0];
if(existingModel == null) {
cache.putRenamedRef($ref, newRef);
// don't overwrite existing model reference
openAPI.getComponents().addSchemas(newRef, schema);
cache.addReferencedKey(newRef);
}else{
//replace the existing model with the schema to avoid duplicates
openAPI.getComponents().getSchemas().replace(newRef, schema);
}

String file = $ref.split("#/")[0];
if (schema.get$ref() != null) {
RefFormat ref = computeRefFormat(schema.get$ref());
if (isAnExternalRefFormat(ref)) {
if (!ref.equals(RefFormat.URL)) {
String schemaFullRef = schema.get$ref();
String parent = file.substring(0, file.lastIndexOf(File.separatorChar));
if (!parent.isEmpty()) {
schemaFullRef = Paths.get(parent, schemaFullRef).normalize().toString();
}
schema.set$ref(processRefToExternalSchema(schemaFullRef, ref));
if (schema.get$ref() != null) {
RefFormat ref = computeRefFormat(schema.get$ref());
if (isAnExternalRefFormat(ref)) {
if (!ref.equals(RefFormat.URL)) {
String schemaFullRef = schema.get$ref();
String parent = file.substring(0, file.lastIndexOf(File.separatorChar));
if (!parent.isEmpty()) {
schemaFullRef = Paths.get(parent, schemaFullRef).normalize().toString();
}
} else {
processRefToExternalSchema(file + schema.get$ref(), RefFormat.RELATIVE);
schema.set$ref(processRefToExternalSchema(schemaFullRef, ref));
}
} else {
processRefToExternalSchema(file + schema.get$ref(), RefFormat.RELATIVE);
}
}


if(schema instanceof ComposedSchema){
ComposedSchema composedSchema = (ComposedSchema) schema;
if (composedSchema.getAllOf() != null){
for(Schema item : composedSchema.getAllOf()){
if (item.get$ref() != null){
processRefSchema(item,file);
} else if (item.getProperties() != null) {
processProperties(item.getProperties(), file);
}
if(schema instanceof ComposedSchema){
ComposedSchema composedSchema = (ComposedSchema) schema;
if (composedSchema.getAllOf() != null){
for(Schema item : composedSchema.getAllOf()){
if (item.get$ref() != null){
processRefSchema(item,file);
} else if (item.getProperties() != null) {
processProperties(item.getProperties(), file);
}
}

}if (composedSchema.getOneOf() != null){
for(Schema item : composedSchema.getOneOf()){
}if (composedSchema.getOneOf() != null){
for(Schema item : composedSchema.getOneOf()){
if (item.get$ref() != null){
if (item.get$ref() != null){
if (item.get$ref() != null){
processRefSchema(item,file);
}
processRefSchema(item,file);
}
}
}if (composedSchema.getAnyOf() != null){
for(Schema item : composedSchema.getAnyOf()){
}
}if (composedSchema.getAnyOf() != null){
for(Schema item : composedSchema.getAnyOf()){
if (item.get$ref() != null){
if (item.get$ref() != null){
if (item.get$ref() != null){
processRefSchema(item,file);
}
processRefSchema(item,file);
}
}

}

}
//Loop the properties and recursively call this method;
Map<String, Schema> subProps = schema.getProperties();
}
//Loop the properties and recursively call this method;
Map<String, Schema> subProps = schema.getProperties();

processProperties(subProps,file);
processProperties(subProps,file);

processDiscriminator(schema.getDiscriminator(),file);
processDiscriminator(schema.getDiscriminator(),file);

if(schema.getAdditionalProperties() != null && schema.getAdditionalProperties() instanceof Schema){
Schema additionalProperty = (Schema) schema.getAdditionalProperties();
if (additionalProperty.get$ref() != null) {
processRefSchema(additionalProperty, file);
} else if (additionalProperty instanceof ArraySchema) {
ArraySchema arrayProp = (ArraySchema) additionalProperty;
if (arrayProp.getItems() != null && arrayProp.getItems().get$ref() != null &&
StringUtils.isNotBlank(arrayProp.get$ref())) {
processRefSchema(arrayProp.getItems(), file);
}
} else if (additionalProperty.getAdditionalProperties() != null && additionalProperty.getAdditionalProperties() instanceof Schema) {
Schema mapProp = (Schema) additionalProperty.getAdditionalProperties();
if (mapProp.get$ref() != null) {
processRefSchema(mapProp, file);
} else if (mapProp.getAdditionalProperties() instanceof ArraySchema &&
((ArraySchema) mapProp).getItems() != null &&
((ArraySchema) mapProp).getItems().get$ref() != null
&& StringUtils.isNotBlank(((ArraySchema) mapProp).getItems().get$ref())) {
processRefSchema(((ArraySchema) mapProp).getItems(), file);
}
if(schema.getAdditionalProperties() != null && schema.getAdditionalProperties() instanceof Schema){
Schema additionalProperty = (Schema) schema.getAdditionalProperties();
if (additionalProperty.get$ref() != null) {
processRefSchema(additionalProperty, file);
} else if (additionalProperty instanceof ArraySchema) {
ArraySchema arrayProp = (ArraySchema) additionalProperty;
if (arrayProp.getItems() != null && arrayProp.getItems().get$ref() != null &&
StringUtils.isNotBlank(arrayProp.get$ref())) {
processRefSchema(arrayProp.getItems(), file);
}

}
if (schema instanceof ArraySchema && ((ArraySchema) schema).getItems() != null) {
ArraySchema arraySchema = (ArraySchema) schema;
if (StringUtils.isNotBlank(arraySchema.getItems().get$ref())) {
processRefSchema(((ArraySchema) schema).getItems(), file);
} else {
processProperties(arraySchema.getItems().getProperties() ,file);
} else if (additionalProperty.getAdditionalProperties() != null && additionalProperty.getAdditionalProperties() instanceof Schema) {
Schema mapProp = (Schema) additionalProperty.getAdditionalProperties();
if (mapProp.get$ref() != null) {
processRefSchema(mapProp, file);
} else if (mapProp.getAdditionalProperties() instanceof ArraySchema &&
((ArraySchema) mapProp).getItems() != null &&
((ArraySchema) mapProp).getItems().get$ref() != null
&& StringUtils.isNotBlank(((ArraySchema) mapProp).getItems().get$ref())) {
processRefSchema(((ArraySchema) mapProp).getItems(), file);
}
}

}
if (schema instanceof ArraySchema && ((ArraySchema) schema).getItems() != null) {
ArraySchema arraySchema = (ArraySchema) schema;
if (StringUtils.isNotBlank(arraySchema.getItems().get$ref())) {
processRefSchema(((ArraySchema) schema).getItems(), file);
} else {
processProperties(arraySchema.getItems().getProperties() ,file);
}
}

return newRef;
Expand Down Expand Up @@ -866,7 +890,7 @@ private void processRefSchemaObject(Schema schema, String $ref) {
if (schema.get$ref() != null) {
RefFormat ref = computeRefFormat(schema.get$ref());
if (isAnExternalRefFormat(ref)) {
processRefSchema(schema, $ref);
processRefSchema(schema, file);
} else {
processRefToExternalSchema(file + schema.get$ref(), RefFormat.RELATIVE);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,8 @@ String getRenamedRef(String ref) {

schemaProcessor.processSchema(refModel);
times = 1;


}};

new ComponentsProcessor(openAPI, mockResolverCache).processComponents();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,20 @@ public class OpenAPIV3ParserTest {
protected int serverPort = getDynamicPort();
protected WireMockServer wireMockServer;

@Test
public void testIssue1518() {
ParseOptions options = new ParseOptions();
options.setResolve(true);
SwaggerParseResult result = new OpenAPIV3Parser().readLocation("jim/api.json", null, options);
OpenAPI openAPI = result.getOpenAPI();
Yaml.prettyPrint(openAPI.getComponents());
assertTrue(openAPI.getComponents().getSchemas().get("TashotSipe_1") == null);

assertTrue(((Schema)openAPI.getComponents().getSchemas().get("Analemmata").getProperties().get("tashotSipe")).get$ref().equals("#/components/schemas/TashotSipe"));
assertTrue(openAPI.getComponents().getSchemas().get("Stunts_1") == null);
assertTrue(openAPI.getComponents().getSchemas().get("analemmata") == null);
}

@Test
public void testIssue251() throws IOException {
String pathFile = FileUtils.readFileToString(new File("src/test/resources/domain.yaml"), "UTF-8");
Expand Down
Loading

0 comments on commit d7b066f

Please sign in to comment.