Skip to content

Commit

Permalink
Correctly resolve externalRefs that point to the root path
Browse files Browse the repository at this point in the history
Previously, if OpenAPI v3 document A loads document B, and B refers
to schemas in document A, swagger-parser would not resolve references
to schemas in A as internal refs, even though they refer to the root
OpenAPI v3 document (document A). This would result in the creation of
duplicate schemas for those schemas in document A. Now, we resolve these
"external" refs as internal refs, preventing the duplication of these
schemas by the ExternalRefProcessor.
  • Loading branch information
AmateurECE committed Nov 9, 2023
1 parent 258ed4b commit 471a6c9
Showing 1 changed file with 23 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
Expand Down Expand Up @@ -106,17 +107,25 @@ public ResolverCache(OpenAPI openApi, List<AuthorizationValue> auths, String par

}

private <T> T loadSchemaForInternalRef(String ref, Class<T> expectedType) {
Object loadedRef = loadInternalRef(ref);

try{
return expectedType.cast(loadedRef);
}
catch (Exception e) {
return null;
}
}

private boolean fileIsRootPath(Path file) {
return this.rootPath != null && file.normalize().equals(Paths.get(this.rootPath).toAbsolutePath().normalize());
}

public <T> T loadRef(String ref, RefFormat refFormat, Class<T> expectedType) {
if (refFormat == RefFormat.INTERNAL) {
//we don't need to go get anything for internal refs
Object loadedRef = loadInternalRef(ref);

try{
return expectedType.cast(loadedRef);
}
catch (Exception e) {
return null;
}
return loadSchemaForInternalRef(ref, expectedType);
}

final String[] refParts = ref.split("#/");
Expand All @@ -128,6 +137,12 @@ public <T> T loadRef(String ref, RefFormat refFormat, Class<T> expectedType) {
final String file = refParts[0];
final String definitionPath = refParts.length == 2 ? refParts[1] : null;

if (this.parentDirectory != null && fileIsRootPath(this.parentDirectory.resolve(file))) {
// If the file part of this external ref refers to the same file as the root path, we can treat it like an
// internal ref.
return loadSchemaForInternalRef("#/" + definitionPath, expectedType);
}

//we might have already resolved this ref, so check the resolutionCache
Object previouslyResolvedEntity = resolutionCache.get(ref);

Expand Down

0 comments on commit 471a6c9

Please sign in to comment.