Repository: swagger-api/swagger-parser
Pull request #1521 (2021-01-22 13:18:40)

#SWOS-242: test cases for ClassCastException when resolving external refs
I'm facing `java.lang.ClassCastException` when my specification has two similar $refs for different models. When $refs point to components from the same specification everything works fine.

`
java.lang.ClassCastException: Cannot cast io.swagger.v3.oas.models.parameters.HeaderParameter to io.swagger.v3.oas.models.headers.Header
	at java.base/java.lang.Class.cast(Class.java:3816)
	at io.swagger.v3.parser.ResolverCache.loadRef(ResolverCache.java:110)
	at io.swagger.v3.parser.processors.ExternalRefProcessor.processRefToExternalHeader(ExternalRefProcessor.java:455)
	at io.swagger.v3.parser.processors.HeaderProcessor.processHeader(HeaderProcessor.java:42)
	at io.swagger.v3.parser.processors.ResponseProcessor.processResponse(ResponseProcessor.java:66)
	at io.swagger.v3.parser.processors.OperationProcessor.processOperation(OperationProcessor.java:67)
	at io.swagger.v3.parser.processors.PathsProcessor.processPaths(PathsProcessor.java:84)
	at io.swagger.v3.parser.OpenAPIResolver.resolve(OpenAPIResolver.java:49)
	at io.swagger.v3.parser.OpenAPIV3Parser.resolve(OpenAPIV3Parser.java:175)
	at io.swagger.v3.parser.OpenAPIV3Parser.readContents(OpenAPIV3Parser.java:154)
	at io.swagger.v3.parser.OpenAPIV3Parser.readContents(OpenAPIV3Parser.java:99)
`



Patch:
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 3850eca1..a5d2d938 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
@@ -3,6 +3,7 @@ package io.swagger.v3.parser;
 import com.fasterxml.jackson.databind.JsonNode;
 import com.fasterxml.jackson.databind.node.ObjectNode;
 import io.swagger.v3.oas.models.OpenAPI;
+import io.swagger.v3.oas.models.headers.Header;
 import io.swagger.v3.oas.models.media.Schema;
 import io.swagger.v3.oas.models.parameters.Parameter;
 import io.swagger.v3.oas.models.responses.ApiResponse;
@@ -107,7 +108,13 @@ public class ResolverCache {
         Object previouslyResolvedEntity = resolutionCache.get(ref);
 
         if (previouslyResolvedEntity != null) {
-            return expectedType.cast(previouslyResolvedEntity);
+            if(expectedType.equals(Header.class)){
+                if (expectedType.getClass().equals(previouslyResolvedEntity.getClass())) {
+                    return expectedType.cast(previouslyResolvedEntity);
+                }
+            }else {
+                return expectedType.cast(previouslyResolvedEntity);
+            }
         }
 
         //we have not resolved this particular ref


Test patch:
diff --git a/modules/swagger-parser-v3/src/test/java/io/swagger/v3/parser/test/OpenAPIV3ParserTest.java b/modules/swagger-parser-v3/src/test/java/io/swagger/v3/parser/test/OpenAPIV3ParserTest.java
index 4568b04b..37f15742 100644
--- a/modules/swagger-parser-v3/src/test/java/io/swagger/v3/parser/test/OpenAPIV3ParserTest.java
+++ b/modules/swagger-parser-v3/src/test/java/io/swagger/v3/parser/test/OpenAPIV3ParserTest.java
@@ -82,6 +82,42 @@ public class OpenAPIV3ParserTest {
     protected int serverPort = getDynamicPort();
     protected WireMockServer wireMockServer;
 
+    @Test
+    public void testIssueSameRefsDifferentModel() throws IOException {
+        String pathFile = FileUtils.readFileToString(new File("src/test/resources/same-refs-different-model-domain.yaml"), "UTF-8");
+        WireMock.stubFor(get(urlPathMatching("/issue-domain"))
+                .willReturn(aResponse()
+                        .withStatus(HttpURLConnection.HTTP_OK)
+                        .withHeader("Content-type", "application/json")
+                        .withBody(pathFile
+                                .getBytes(StandardCharsets.UTF_8))));
+
+        pathFile = FileUtils.readFileToString(new File("src/test/resources/same-refs-different-model.yaml"), "UTF-8");
+        pathFile = pathFile.replace("${dynamicPort}", String.valueOf(this.serverPort));
+
+        OpenAPIV3Parser parser = new OpenAPIV3Parser();
+        ParseOptions options = new ParseOptions();
+        options.setResolve(true);
+        options.setResolveFully(true);
+
+        final SwaggerParseResult openAPI = parser.readContents(pathFile, null, options);
+        Yaml.prettyPrint(openAPI);
+
+        assertEquals(openAPI.getMessages().size(), 0);
+    }
+
+    @Test
+    public void testIssueSameRefsDifferentModelValid() {
+        OpenAPIV3Parser parser = new OpenAPIV3Parser();
+        ParseOptions options = new ParseOptions();
+        options.setResolve(true);
+        options.setResolveFully(true);
+
+        final SwaggerParseResult openAPI = parser.readLocation("src/test/resources/same-refs-different-model-valid.yaml", null, options);
+        Yaml.prettyPrint(openAPI);
+        assertEquals(openAPI.getMessages().size(), 0);
+    }
+
     @Test
     public void testIssue1398() {
         ParseOptions options = new ParseOptions();
diff --git a/modules/swagger-parser-v3/src/test/resources/same-refs-different-model-domain.yaml b/modules/swagger-parser-v3/src/test/resources/same-refs-different-model-domain.yaml
new file mode 100644
index 00000000..a02d2bec
--- /dev/null
+++ b/modules/swagger-parser-v3/src/test/resources/same-refs-different-model-domain.yaml
@@ -0,0 +1,11 @@
+openapi: 3.0.0
+
+components:
+  parameters:
+    requestid:
+      name: X-requestid
+      in: header
+      required: false
+      schema:
+        type: string
+        format: uuid
\ No newline at end of file
diff --git a/modules/swagger-parser-v3/src/test/resources/same-refs-different-model-valid.yaml b/modules/swagger-parser-v3/src/test/resources/same-refs-different-model-valid.yaml
new file mode 100644
index 00000000..ab069038
--- /dev/null
+++ b/modules/swagger-parser-v3/src/test/resources/same-refs-different-model-valid.yaml
@@ -0,0 +1,26 @@
+openapi: 3.0.0
+info:
+  title: issue
+  version: 1.0.01
+
+paths:
+  /bar:
+    parameters:
+      - $ref: '#/components/parameters/requestid'
+    delete:
+      responses:
+        '204':
+          description: Deleted
+          headers:
+            X-requestid:
+              $ref: '#/components/parameters/requestid'
+
+components:
+  parameters:
+    requestid:
+      name: X-requestid
+      in: header
+      required: false
+      schema:
+        type: string
+        format: uuid
\ No newline at end of file
diff --git a/modules/swagger-parser-v3/src/test/resources/same-refs-different-model.yaml b/modules/swagger-parser-v3/src/test/resources/same-refs-different-model.yaml
new file mode 100644
index 00000000..c3a1ad27
--- /dev/null
+++ b/modules/swagger-parser-v3/src/test/resources/same-refs-different-model.yaml
@@ -0,0 +1,16 @@
+openapi: 3.0.0
+info:
+  title: issue
+  version: 1.0.01
+
+paths:
+  /bar:
+    parameters:
+      - $ref: 'http://localhost:${dynamicPort}/issue-domain/#/components/parameters/requestid'
+    delete:
+      responses:
+        '204':
+          description: Deleted
+          headers:
+            X-requestid:
+              $ref: 'http://localhost:${dynamicPort}/issue-domain/#/components/parameters/requestid'
\ No newline at end of file