From 471a6c980e01eabdfc2bb91933c731d0cbf56e82 Mon Sep 17 00:00:00 2001 From: "Ethan D. Twardy" Date: Wed, 16 Aug 2023 20:46:57 -0500 Subject: [PATCH] Correctly resolve externalRefs that point to the root path 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. --- .../io/swagger/v3/parser/ResolverCache.java | 31 ++++++++++++++----- 1 file changed, 23 insertions(+), 8 deletions(-) diff --git a/modules/swagger-parser-v3/src/main/java/io/swagger/v3/parser/ResolverCache.java b/modules/swagger-parser-v3/src/main/java/io/swagger/v3/parser/ResolverCache.java index 382ede57be..d83173cd52 100644 --- a/modules/swagger-parser-v3/src/main/java/io/swagger/v3/parser/ResolverCache.java +++ b/modules/swagger-parser-v3/src/main/java/io/swagger/v3/parser/ResolverCache.java @@ -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; @@ -106,17 +107,25 @@ public ResolverCache(OpenAPI openApi, List auths, String par } + private T loadSchemaForInternalRef(String ref, Class 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 loadRef(String ref, RefFormat refFormat, Class 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("#/"); @@ -128,6 +137,12 @@ public T loadRef(String ref, RefFormat refFormat, Class 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);