Repository: swagger-api/swagger-parser
Pull request #826 (2018-09-03 23:21:30)

Fix issue #811 OAS3 - RefResponse -> RefSchema external Resolving
Fix issue #811 OAS3


Patch:
diff --git a/modules/swagger-parser-v3/src/main/java/io/swagger/v3/parser/processors/ExternalRefProcessor.java b/modules/swagger-parser-v3/src/main/java/io/swagger/v3/parser/processors/ExternalRefProcessor.java
index 12c7d253..fb402d32 100644
--- a/modules/swagger-parser-v3/src/main/java/io/swagger/v3/parser/processors/ExternalRefProcessor.java
+++ b/modules/swagger-parser-v3/src/main/java/io/swagger/v3/parser/processors/ExternalRefProcessor.java
@@ -9,6 +9,7 @@ import io.swagger.v3.oas.models.headers.Header;
 import io.swagger.v3.oas.models.links.Link;
 import io.swagger.v3.oas.models.media.ArraySchema;
 import io.swagger.v3.oas.models.media.ComposedSchema;
+import io.swagger.v3.oas.models.media.MediaType;
 import io.swagger.v3.oas.models.media.Schema;
 import io.swagger.v3.oas.models.parameters.Parameter;
 import io.swagger.v3.oas.models.parameters.RequestBody;
@@ -199,62 +200,33 @@ public final class ExternalRefProcessor {
         }
     }
 
-    public String processRefToExternalResponse(String $ref, RefFormat refFormat) {
-        String renamedRef = cache.getRenamedRef($ref);
-        if(renamedRef != null) {
-            return renamedRef;
-        }
+    public void processRefToExternalResponse(String $ref, RefFormat refFormat) {
 
         final ApiResponse response = cache.loadRef($ref, refFormat, ApiResponse.class);
 
-        if(response == null) {
-            // stop!  There's a problem.  retain the original ref
-            LOGGER.warn("unable to load model reference from `" + $ref + "`.  It may not be available " +
-                    "or the reference isn't a valid model schema");
-            return $ref;
-        }
-        String newRef;
-
-        if (openAPI.getComponents() == null) {
-            openAPI.setComponents(new Components());
-        }
-        Map<String, ApiResponse> responses = openAPI.getComponents().getResponses();
-
-        if (responses == null) {
-            responses = new LinkedHashMap<>();
-        }
-
-        final String possiblyConflictingDefinitionName = computeDefinitionName($ref);
-
-        ApiResponse existingResponse = responses.get(possiblyConflictingDefinitionName);
-
-        if (existingResponse != null) {
-            LOGGER.debug("A model for " + existingResponse + " already exists");
-            if(existingResponse.get$ref() != null) {
-                // use the new model
-                existingResponse = null;
-            }
-        }
-        newRef = possiblyConflictingDefinitionName;
-        cache.putRenamedRef($ref, newRef);
-
-        if(existingResponse == null) {
-            // don't overwrite existing model reference
-            openAPI.getComponents().addResponses(newRef, response);
-            cache.addReferencedKey(newRef);
-
-            String file = $ref.split("#/")[0];
-            if (response.get$ref() != null) {
-                RefFormat format = computeRefFormat(response.get$ref());
-                if (isAnExternalRefFormat(format)) {
-                    response.set$ref(processRefToExternalResponse(response.get$ref(), format));
-                } else {
-                    processRefToExternalResponse(file + response.get$ref(), RefFormat.RELATIVE);
+        if(response != null) {
+
+        String file = $ref.split("#/")[0];
+
+            Schema schema = null;
+            if(response.getContent() != null){
+                Map<String, MediaType> content = response.getContent();
+                for( String mediaName : content.keySet()) {
+                    MediaType mediaType = content.get(mediaName);
+                    if(mediaType.getSchema()!= null) {
+                        schema = mediaType.getSchema();
+                        if (schema.get$ref() != null) {
+                            RefFormat ref = computeRefFormat(schema.get$ref());
+                            if (isAnExternalRefFormat(ref)) {
+                               processRefSchema(schema, $ref);
+                            } else {
+                                processRefToExternalSchema(file + schema.get$ref(), RefFormat.RELATIVE);
+                            }
+                        }
+                    }
                 }
             }
         }
-
-        return newRef;
     }
 
     public String processRefToExternalRequestBody(String $ref, RefFormat refFormat) {
diff --git a/modules/swagger-parser-v3/src/main/java/io/swagger/v3/parser/processors/OperationProcessor.java b/modules/swagger-parser-v3/src/main/java/io/swagger/v3/parser/processors/OperationProcessor.java
index e269e32f..e6ad4a5a 100644
--- a/modules/swagger-parser-v3/src/main/java/io/swagger/v3/parser/processors/OperationProcessor.java
+++ b/modules/swagger-parser-v3/src/main/java/io/swagger/v3/parser/processors/OperationProcessor.java
@@ -51,7 +51,10 @@ public class OperationProcessor {
             for (String responseCode : responses.keySet()) {
                 ApiResponse response = responses.get(responseCode);
                 if(response != null) {
-                    if (response.get$ref() != null){
+                    if (response.get$ref() != null) {
+
+                        responseProcessor.processResponse(response);
+
                         RefFormat refFormat = computeRefFormat(response.get$ref());
                         ApiResponse resolvedResponse = cache.loadRef(response.get$ref(), refFormat, ApiResponse.class);
 
@@ -60,7 +63,9 @@ public class OperationProcessor {
                             responses.put(responseCode, resolvedResponse);
                         }
                     }
+
                     responseProcessor.processResponse(response);
+
                 }
             }
         }
diff --git a/modules/swagger-parser-v3/src/main/java/io/swagger/v3/parser/processors/ResponseProcessor.java b/modules/swagger-parser-v3/src/main/java/io/swagger/v3/parser/processors/ResponseProcessor.java
index b08ed955..036c3489 100644
--- a/modules/swagger-parser-v3/src/main/java/io/swagger/v3/parser/processors/ResponseProcessor.java
+++ b/modules/swagger-parser-v3/src/main/java/io/swagger/v3/parser/processors/ResponseProcessor.java
@@ -37,6 +37,7 @@ public class ResponseProcessor {
         if (response.get$ref() != null){
             processReferenceResponse(response);
         }
+
         Schema schema = null;
         if(response.getContent() != null){
             Map<String,MediaType> content = response.getContent();
@@ -72,11 +73,7 @@ public class ResponseProcessor {
         RefFormat refFormat = computeRefFormat(response.get$ref());
         String $ref = response.get$ref();
         if (isAnExternalRefFormat(refFormat)){
-            final String newRef = externalRefProcessor.processRefToExternalResponse($ref, refFormat);
-
-            if (newRef != null) {
-                response.set$ref(newRef);
-            }
+            externalRefProcessor.processRefToExternalResponse($ref, refFormat);
         }
     }
 }
\ No newline at end of file


Test patch:
diff --git a/modules/swagger-parser-v3/src/test/java/io/swagger/v3/parser/processors/OperationProcessorTest.java b/modules/swagger-parser-v3/src/test/java/io/swagger/v3/parser/processors/OperationProcessorTest.java
index bbe1bcfd..3ec013be 100644
--- a/modules/swagger-parser-v3/src/test/java/io/swagger/v3/parser/processors/OperationProcessorTest.java
+++ b/modules/swagger-parser-v3/src/test/java/io/swagger/v3/parser/processors/OperationProcessorTest.java
@@ -49,10 +49,12 @@ public class OperationProcessorTest {
         operation.responses(new ApiResponses().addApiResponse("200", refResponse));
         operation.getResponses().addApiResponse("400", incomingResponse);
 
+
         new Expectations() {{
             new ParameterProcessor(cache, openAPI);
             times = 1;
             result = parameterProcessor;
+
             new ResponseProcessor(cache, openAPI);
             times = 1;
             result = responseProcessor;
@@ -61,6 +63,9 @@ public class OperationProcessorTest {
             times = 1;
             result = outputParameterList;
 
+            responseProcessor.processResponse(refResponse);
+            times = 1;
+
             RefUtils.computeRefFormat(ref);
             times = 1;
 
@@ -78,10 +83,14 @@ public class OperationProcessorTest {
             times = 1;
             responseProcessor.processResponse(resolvedResponse);
             times = 1;
+
         }};
 
+
+
         new OperationProcessor(cache, openAPI).processOperation(operation);
 
+
         new FullVerifications() {{}};
 
         assertEquals(operation.getResponses().get("200"), resolvedResponse);
diff --git a/modules/swagger-parser-v3/src/test/java/io/swagger/v3/parser/test/OpenAPIResolverTest.java b/modules/swagger-parser-v3/src/test/java/io/swagger/v3/parser/test/OpenAPIResolverTest.java
index dd3d1868..1d42b0d0 100644
--- a/modules/swagger-parser-v3/src/test/java/io/swagger/v3/parser/test/OpenAPIResolverTest.java
+++ b/modules/swagger-parser-v3/src/test/java/io/swagger/v3/parser/test/OpenAPIResolverTest.java
@@ -252,11 +252,6 @@ public class OpenAPIResolverTest {
 
         Map<String, ApiResponse> responses = openAPI.getComponents().getResponses();
 
-        //remote url response
-        ApiResponse found = responses.get("Found");
-        assertEquals(openAPI.getComponents().getResponses().get("RemoteResponse").getDescription(),"Remote Description");
-        assertEquals(found.get$ref(), "#/components/responses/RemoteResponse");
-
         //internal response headers
         ApiResponse illegalInput = responses.get("IllegalInput");
         assertEquals(illegalInput.getHeaders().get("X-Ref-Limit-Limit").get$ref(),"#/components/headers/X-Rate-Limit-Reset");
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 145b3593..10430fc9 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
@@ -56,6 +56,30 @@ public class OpenAPIV3ParserTest {
     protected int serverPort = getDynamicPort();
     protected WireMockServer wireMockServer;
 
+    @Test
+    public void testIssue811_RefSchema_ToRefSchema() {
+        ParseOptions options = new ParseOptions();
+        options.setResolve(true);
+        final OpenAPI openAPI = new OpenAPIV3Parser().readLocation("oapi-reference-test2/index.yaml", null, options).getOpenAPI();
+
+        Assert.assertNotNull(openAPI);
+        Assert.assertEquals(openAPI.getPaths().get("/").getGet().getResponses().get("200").getContent().get("application/json").getSchema().get$ref(),"#/components/schemas/schema-with-reference");
+
+
+    }
+
+    @Test
+    public void testIssue811() {
+        ParseOptions options = new ParseOptions();
+        options.setResolve(true);
+        final OpenAPI openAPI = new OpenAPIV3Parser().readLocation("oapi-reference-test/index.yaml", null, options).getOpenAPI();
+
+        Assert.assertNotNull(openAPI);
+
+        Assert.assertEquals(openAPI.getPaths().get("/").getGet().getResponses().get("200").getContent().get("application/json").getSchema().get$ref(),"#/components/schemas/schema-with-reference");
+
+    }
+
     @Test
     public void testIssue719() {
         final OpenAPI openAPI = new OpenAPIV3Parser().readLocation("extensions-responses.yaml", null, new ParseOptions()).getOpenAPI();
diff --git a/modules/swagger-parser-v3/src/test/java/io/swagger/v3/parser/util/OpenAPIDeserializerTest.java b/modules/swagger-parser-v3/src/test/java/io/swagger/v3/parser/util/OpenAPIDeserializerTest.java
index 4f877d98..ba96b1f2 100644
--- a/modules/swagger-parser-v3/src/test/java/io/swagger/v3/parser/util/OpenAPIDeserializerTest.java
+++ b/modules/swagger-parser-v3/src/test/java/io/swagger/v3/parser/util/OpenAPIDeserializerTest.java
@@ -57,6 +57,7 @@ import static org.testng.Assert.assertFalse;
 
 public class OpenAPIDeserializerTest {
 
+
     @Test
     public void testEmptyDefinitions() throws Exception {
         String yaml = "openapi: 3.0.0\n" +
diff --git a/modules/swagger-parser-v3/src/test/resources/oapi-reference-test/components/referent.yaml b/modules/swagger-parser-v3/src/test/resources/oapi-reference-test/components/referent.yaml
new file mode 100644
index 00000000..80ef5680
--- /dev/null
+++ b/modules/swagger-parser-v3/src/test/resources/oapi-reference-test/components/referent.yaml
@@ -0,0 +1,2 @@
+---
+type: object
diff --git a/modules/swagger-parser-v3/src/test/resources/oapi-reference-test/components/response-with-reference.yaml b/modules/swagger-parser-v3/src/test/resources/oapi-reference-test/components/response-with-reference.yaml
new file mode 100644
index 00000000..00db562a
--- /dev/null
+++ b/modules/swagger-parser-v3/src/test/resources/oapi-reference-test/components/response-with-reference.yaml
@@ -0,0 +1,6 @@
+---
+description: Response with schema containing reference
+content:
+  application/json:
+    schema:
+      $ref: "./schema-with-reference.yaml"
diff --git a/modules/swagger-parser-v3/src/test/resources/oapi-reference-test/components/schema-with-reference.yaml b/modules/swagger-parser-v3/src/test/resources/oapi-reference-test/components/schema-with-reference.yaml
new file mode 100644
index 00000000..4a896cc6
--- /dev/null
+++ b/modules/swagger-parser-v3/src/test/resources/oapi-reference-test/components/schema-with-reference.yaml
@@ -0,0 +1,7 @@
+---
+type: object
+properties:
+  reference_array:
+    type: array
+    items:
+      $ref: "./referent.yaml"
diff --git a/modules/swagger-parser-v3/src/test/resources/oapi-reference-test/index.yaml b/modules/swagger-parser-v3/src/test/resources/oapi-reference-test/index.yaml
new file mode 100644
index 00000000..1405cd06
--- /dev/null
+++ b/modules/swagger-parser-v3/src/test/resources/oapi-reference-test/index.yaml
@@ -0,0 +1,22 @@
+---
+openapi: "3.0.0"
+externalDocs:
+  description: Test
+  url: http://test.com/test
+info:
+  version: 0.0.1
+  title: Test
+  license:
+    name: Test
+    url: http://test.com/test
+servers:
+  - url: http://test.com/test
+paths:
+  /:
+    get:
+      description: Test
+      summary: Test
+      operationId: getTest
+      responses:
+        200:
+          $ref: "./components/response-with-reference.yaml"
diff --git a/modules/swagger-parser-v3/src/test/resources/oapi-reference-test2/components/referent.yaml b/modules/swagger-parser-v3/src/test/resources/oapi-reference-test2/components/referent.yaml
new file mode 100644
index 00000000..80ef5680
--- /dev/null
+++ b/modules/swagger-parser-v3/src/test/resources/oapi-reference-test2/components/referent.yaml
@@ -0,0 +1,2 @@
+---
+type: object
diff --git a/modules/swagger-parser-v3/src/test/resources/oapi-reference-test2/components/schema-with-reference.yaml b/modules/swagger-parser-v3/src/test/resources/oapi-reference-test2/components/schema-with-reference.yaml
new file mode 100644
index 00000000..4a896cc6
--- /dev/null
+++ b/modules/swagger-parser-v3/src/test/resources/oapi-reference-test2/components/schema-with-reference.yaml
@@ -0,0 +1,7 @@
+---
+type: object
+properties:
+  reference_array:
+    type: array
+    items:
+      $ref: "./referent.yaml"
diff --git a/modules/swagger-parser-v3/src/test/resources/oapi-reference-test2/index.yaml b/modules/swagger-parser-v3/src/test/resources/oapi-reference-test2/index.yaml
new file mode 100644
index 00000000..7fe10b4e
--- /dev/null
+++ b/modules/swagger-parser-v3/src/test/resources/oapi-reference-test2/index.yaml
@@ -0,0 +1,26 @@
+---
+openapi: "3.0.0"
+externalDocs:
+  description: Test
+  url: http://test.com/test
+info:
+  version: 0.0.1
+  title: Test
+  license:
+    name: Test
+    url: http://test.com/test
+servers:
+  - url: http://test.com/test
+paths:
+  /:
+    get:
+      description: Test
+      summary: Test
+      operationId: getTest
+      responses:
+        200:
+          description: Response with schema containing reference
+          content:
+            application/json:
+              schema:
+                $ref: "./components/schema-with-reference.yaml"
diff --git a/modules/swagger-parser-v3/src/test/resources/relative-file-references/json/paths/healthPath.json b/modules/swagger-parser-v3/src/test/resources/relative-file-references/json/paths/healthPath.json
index 8f191cfe..283316c7 100644
--- a/modules/swagger-parser-v3/src/test/resources/relative-file-references/json/paths/healthPath.json
+++ b/modules/swagger-parser-v3/src/test/resources/relative-file-references/json/paths/healthPath.json
@@ -1,10 +1,10 @@
 {
 	"parameters": [
 		{
-			"$ref": "./parameters/params.json#/param1"
+			"$ref": "../parameters/params.json#/param1"
 		},
 		{
-			"$ref": "./parameters/params.json#/param2"
+			"$ref": "../parameters/params.json#/param2"
 		}
 	],
 	"get": {
@@ -12,10 +12,10 @@
 		"operationId": "getHealth",
 		"parameters": [
 			{
-				"$ref": "./parameters/params.json#/param3"
+				"$ref": "../parameters/params.json#/param3"
 			},
 			{
-				"$ref": "./parameters/params.json#/param4"
+				"$ref": "../parameters/params.json#/param4"
 			}
 		],
 		"requestBody": {
@@ -23,7 +23,7 @@
 			"content": {
 				"application/json": {
 					"schema": {
-						"$ref": "./models/health.json"
+						"$ref": "../models/health.json"
 					}
 				}
 			}
@@ -34,16 +34,16 @@
 				"content": {
 					"application/json": {
 						"schema": {
-							"$ref": "./models/health.json"
+							"$ref": "../models/health.json"
 						}
 					}
 				}
 			},
 			"400": {
-				"$ref": "./responses/errorResponses.json#/bad-request"
+				"$ref": "../responses/errorResponses.json#/bad-request"
 			},
 			"500": {
-				"$ref": "./responses/errorResponses.json#/internal-server-error"
+				"$ref": "../responses/errorResponses.json#/internal-server-error"
 			}
 		}
 	}
diff --git a/modules/swagger-parser-v3/src/test/resources/relative-file-references/json/responses/errorResponses.json b/modules/swagger-parser-v3/src/test/resources/relative-file-references/json/responses/errorResponses.json
index 2f0b597c..9cd2792f 100644
--- a/modules/swagger-parser-v3/src/test/resources/relative-file-references/json/responses/errorResponses.json
+++ b/modules/swagger-parser-v3/src/test/resources/relative-file-references/json/responses/errorResponses.json
@@ -4,7 +4,7 @@
 		"content": {
 			"*/*": {
 				"schema": {
-					"$ref": "./models/error.json"
+					"$ref": "../models/error.json"
 				}
 			}
 		}
@@ -14,7 +14,7 @@
 		"content": {
 			"*/*": {
 				"schema": {
-					"$ref": "./models/error.json"
+					"$ref": "../models/error.json"
 				}
 			}
 		}
diff --git a/modules/swagger-parser-v3/src/test/resources/relative-file-references/yaml/paths/healthPath.yaml b/modules/swagger-parser-v3/src/test/resources/relative-file-references/yaml/paths/healthPath.yaml
index 11254c96..20d3e95b 100644
--- a/modules/swagger-parser-v3/src/test/resources/relative-file-references/yaml/paths/healthPath.yaml
+++ b/modules/swagger-parser-v3/src/test/resources/relative-file-references/yaml/paths/healthPath.yaml
@@ -1,26 +1,26 @@
 parameters:
-- $ref: ./parameters/params.yaml#/param1
-- $ref: ./parameters/params.yaml#/param2
+- $ref: ../parameters/params.yaml#/param1
+- $ref: ../parameters/params.yaml#/param2
 get:
   summary: Returns server health information
   operationId: getHealth
   parameters:
-  - $ref: ./parameters/params.yaml#/param3
-  - $ref: ./parameters/params.yaml#/param4
+  - $ref: ../parameters/params.yaml#/param3
+  - $ref: ../parameters/params.yaml#/param4
   requestBody:
     required: true
     content:
       application/json:
         schema:
-          $ref: ./models/health.yaml
+          $ref: ../models/health.yaml
   responses:
     200:
       description: Health information from the server
       content:
         application/json:
           schema:
-            $ref: ./models/health.yaml
+            $ref: ../models/health.yaml
     400:
-      $ref: ./responses/errorResponses.yaml#/bad-request
+      $ref: ../responses/errorResponses.yaml#/bad-request
     500:
-      $ref: ./responses/errorResponses.yaml#/internal-server-error
+      $ref: ../responses/errorResponses.yaml#/internal-server-error
diff --git a/modules/swagger-parser-v3/src/test/resources/relative-file-references/yaml/responses/errorResponses.yaml b/modules/swagger-parser-v3/src/test/resources/relative-file-references/yaml/responses/errorResponses.yaml
index ca00946c..bd51c698 100644
--- a/modules/swagger-parser-v3/src/test/resources/relative-file-references/yaml/responses/errorResponses.yaml
+++ b/modules/swagger-parser-v3/src/test/resources/relative-file-references/yaml/responses/errorResponses.yaml
@@ -3,10 +3,10 @@ bad-request:
   content:
     '*/*':
       schema:
-        $ref: ./models/error.yaml
+        $ref: ../models/error.yaml
 internal-server-error:
   description: An unexpected error occur during processing
   content:
     '*/*':
       schema:
-        $ref: ./models/error.yaml
+        $ref: ../models/error.yaml