Repository: getkin/kin-openapi
Pull request #832 (2023-08-30 13:51:45)

openapi3: fix ref internalization
#831


Patch:
diff --git a/openapi3/internalize_refs.go b/openapi3/internalize_refs.go
index cf212c6..30088ce 100644
--- a/openapi3/internalize_refs.go
+++ b/openapi3/internalize_refs.go
@@ -338,32 +338,30 @@ func (doc *T) derefRequestBody(r RequestBody, refNameResolver RefNameResolver, p
 
 func (doc *T) derefPaths(paths map[string]*PathItem, refNameResolver RefNameResolver, parentIsExternal bool) {
 	for _, ops := range paths {
-		if isExternalRef(ops.Ref, parentIsExternal) {
-			parentIsExternal = true
-		}
+		pathIsExternal := isExternalRef(ops.Ref, parentIsExternal)
 		// inline full operations
 		ops.Ref = ""
 
 		for _, param := range ops.Parameters {
-			doc.addParameterToSpec(param, refNameResolver, parentIsExternal)
+			doc.addParameterToSpec(param, refNameResolver, pathIsExternal)
 		}
 
 		for _, op := range ops.Operations() {
-			isExternal := doc.addRequestBodyToSpec(op.RequestBody, refNameResolver, parentIsExternal)
+			isExternal := doc.addRequestBodyToSpec(op.RequestBody, refNameResolver, pathIsExternal)
 			if op.RequestBody != nil && op.RequestBody.Value != nil {
-				doc.derefRequestBody(*op.RequestBody.Value, refNameResolver, parentIsExternal || isExternal)
+				doc.derefRequestBody(*op.RequestBody.Value, refNameResolver, pathIsExternal || isExternal)
 			}
 			for _, cb := range op.Callbacks {
-				isExternal := doc.addCallbackToSpec(cb, refNameResolver, parentIsExternal)
+				isExternal := doc.addCallbackToSpec(cb, refNameResolver, pathIsExternal)
 				if cb.Value != nil {
-					doc.derefPaths(*cb.Value, refNameResolver, parentIsExternal || isExternal)
+					doc.derefPaths(*cb.Value, refNameResolver, pathIsExternal || isExternal)
 				}
 			}
-			doc.derefResponses(op.Responses, refNameResolver, parentIsExternal)
+			doc.derefResponses(op.Responses, refNameResolver, pathIsExternal)
 			for _, param := range op.Parameters {
-				isExternal := doc.addParameterToSpec(param, refNameResolver, parentIsExternal)
+				isExternal := doc.addParameterToSpec(param, refNameResolver, pathIsExternal)
 				if param.Value != nil {
-					doc.derefParameter(*param.Value, refNameResolver, parentIsExternal || isExternal)
+					doc.derefParameter(*param.Value, refNameResolver, pathIsExternal || isExternal)
 				}
 			}
 		}


Test patch:
diff --git a/openapi3/internalize_refs_test.go b/openapi3/internalize_refs_test.go
index ab91ff1..b5ceb69 100644
--- a/openapi3/internalize_refs_test.go
+++ b/openapi3/internalize_refs_test.go
@@ -22,6 +22,7 @@ func TestInternalizeRefs(t *testing.T) {
 		{"testdata/recursiveRef/openapi.yml"},
 		{"testdata/spec.yaml"},
 		{"testdata/callbacks.yml"},
+		{"testdata/issue831/testref.internalizepath.openapi.yml"},
 	}
 
 	for _, test := range tests {
diff --git a/openapi3/testdata/issue831/path.yml b/openapi3/testdata/issue831/path.yml
new file mode 100644
index 0000000..99229bb
--- /dev/null
+++ b/openapi3/testdata/issue831/path.yml
@@ -0,0 +1,4 @@
+get:
+  responses:
+    "200":
+      description: OK
\ No newline at end of file
diff --git a/openapi3/testdata/issue831/testref.internalizepath.openapi.yml b/openapi3/testdata/issue831/testref.internalizepath.openapi.yml
new file mode 100644
index 0000000..74862b5
--- /dev/null
+++ b/openapi3/testdata/issue831/testref.internalizepath.openapi.yml
@@ -0,0 +1,24 @@
+openapi: "3.0.3"
+info:
+  title: Recursive refs example
+  version: "1.0"
+paths:
+  /bar:
+    $ref: ./path.yml
+  /foo:
+    post:
+      requestBody:
+        content:
+          application/json:
+            schema:
+              $ref: "#/components/requestBodies/test/content/application~1json/schema"
+      responses:
+        '200':
+          description: Expected response to a valid request
+components:
+  requestBodies:
+    test:
+      content:
+        application/json:
+          schema:
+            type: string
\ No newline at end of file
diff --git a/openapi3/testdata/issue831/testref.internalizepath.openapi.yml.internalized.yml b/openapi3/testdata/issue831/testref.internalizepath.openapi.yml.internalized.yml
new file mode 100644
index 0000000..c32f690
--- /dev/null
+++ b/openapi3/testdata/issue831/testref.internalizepath.openapi.yml.internalized.yml
@@ -0,0 +1,49 @@
+{
+    "openapi": "3.0.3",
+    "info": {
+        "title": "Recursive refs example",
+        "version": "1.0"
+    },
+    "paths": {
+        "/bar": {
+            "get": {
+                "responses": {
+                    "200": {
+                        "description": "OK"
+                    }
+                }
+            }
+        },
+        "/foo": {
+            "post": {
+                "requestBody": {
+                    "content": {
+                        "application/json": {
+                            "schema": {
+                                "$ref": "#/components/requestBodies/test/content/application~1json/schema"
+                            }
+                        }
+                    }
+                },
+                "responses": {
+                    "200": {
+                        "description": "Expected response to a valid request"
+                    }
+                }
+            }
+        }
+    },
+    "components": {
+        "requestBodies": {
+            "test": {
+                "content": {
+                    "application/json": {
+                        "schema": {
+                            "type": "string"
+                        }
+                    }
+                }
+            }
+        }
+    }
+}
\ No newline at end of file