From 2d48b610f589a1488f1ddf9ca087b28c6685a592 Mon Sep 17 00:00:00 2001 From: Maggie Kimani Date: Fri, 18 Nov 2022 12:35:54 +0300 Subject: [PATCH 1/4] Adds a flag for identifying whether an external reference is a fragment --- .../V3/OpenApiV3VersionService.cs | 16 ++++++++++------ src/Microsoft.OpenApi/Models/OpenApiReference.cs | 12 +++++++++++- 2 files changed, 21 insertions(+), 7 deletions(-) diff --git a/src/Microsoft.OpenApi.Readers/V3/OpenApiV3VersionService.cs b/src/Microsoft.OpenApi.Readers/V3/OpenApiV3VersionService.cs index 1e729f30a..742b64388 100644 --- a/src/Microsoft.OpenApi.Readers/V3/OpenApiV3VersionService.cs +++ b/src/Microsoft.OpenApi.Readers/V3/OpenApiV3VersionService.cs @@ -71,6 +71,7 @@ public OpenApiReference ConvertToOpenApiReference( string reference, ReferenceType? type) { + var openApiReference = new OpenApiReference(); if (!string.IsNullOrWhiteSpace(reference)) { var segments = reference.Split('#'); @@ -127,13 +128,16 @@ public OpenApiReference ConvertToOpenApiReference( } id = localSegments[3]; } - - return new OpenApiReference + else { - ExternalResource = segments[0], - Type = type, - Id = id - }; + openApiReference.IsFragrament = true; + } + + openApiReference.ExternalResource = segments[0]; + openApiReference.Type = type; + openApiReference.Id = id; + + return openApiReference; } } diff --git a/src/Microsoft.OpenApi/Models/OpenApiReference.cs b/src/Microsoft.OpenApi/Models/OpenApiReference.cs index ecc643dc3..e8798cc64 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiReference.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiReference.cs @@ -45,6 +45,11 @@ public class OpenApiReference : IOpenApiSerializable /// public bool IsLocal => ExternalResource == null; + /// + /// Gets a flag indicating whether a file is a valid OpenAPI document or a fragment + /// + public bool IsFragrament = false; + /// /// The OpenApiDocument that is hosting the OpenApiReference instance. This is used to enable dereferencing the reference. /// @@ -196,7 +201,12 @@ private string GetExternalReferenceV3() { if (Id != null) { - return ExternalResource + "#/components/" + Type.GetDisplayName() + "/"+ Id; + if (IsFragrament) + { + return ExternalResource + "#" + Id; + } + + return ExternalResource + "#/components/" + Type.GetDisplayName() + "/"+ Id; } return ExternalResource; From 901346c404b711c6b5b85edff35f63c41ada976b Mon Sep 17 00:00:00 2001 From: Maggie Kimani Date: Fri, 18 Nov 2022 12:36:26 +0300 Subject: [PATCH 2/4] Adds tests to verify external references that are fragments aren't rewritten --- .../Microsoft.OpenApi.Readers.Tests.csproj | 3 +++ .../V3Tests/OpenApiDocumentTests.cs | 20 +++++++++++++++++++ .../documentWithExternalRefs.yaml | 16 +++++++++++++++ 3 files changed, 39 insertions(+) create mode 100644 test/Microsoft.OpenApi.Readers.Tests/V3Tests/Samples/OpenApiDocument/documentWithExternalRefs.yaml diff --git a/test/Microsoft.OpenApi.Readers.Tests/Microsoft.OpenApi.Readers.Tests.csproj b/test/Microsoft.OpenApi.Readers.Tests/Microsoft.OpenApi.Readers.Tests.csproj index 2e73118b2..b5d1167f3 100644 --- a/test/Microsoft.OpenApi.Readers.Tests/Microsoft.OpenApi.Readers.Tests.csproj +++ b/test/Microsoft.OpenApi.Readers.Tests/Microsoft.OpenApi.Readers.Tests.csproj @@ -149,6 +149,9 @@ Never + + Never + Never diff --git a/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiDocumentTests.cs b/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiDocumentTests.cs index 6fbb7065a..362609291 100644 --- a/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiDocumentTests.cs +++ b/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiDocumentTests.cs @@ -6,6 +6,7 @@ using System.Globalization; using System.IO; using System.Linq; +using System.Text; using System.Threading; using FluentAssertions; using Microsoft.OpenApi.Any; @@ -1327,5 +1328,24 @@ public void HeaderParameterShouldAllowExample() }); } } + + [Fact] + public void DoesNotChangeExternalReferences() + { + // Arrange + using var stream = Resources.GetStream(Path.Combine(SampleFolderPath, "documentWithExternalRefs.yaml")); + + // Act + var doc = new OpenApiStreamReader( + new OpenApiReaderSettings { ReferenceResolution = ReferenceResolutionSetting.DoNotResolveReferences}) + .Read(stream, out var diagnostic); + + var externalRef = doc.Components.Schemas["Nested"].Properties["AnyOf"].AnyOf.First().Reference.ReferenceV3; + var externalRef2 = doc.Components.Schemas["Nested"].Properties["AnyOf"].AnyOf.Last().Reference.ReferenceV3; + + // Assert + Assert.Equal("file:///C:/MySchemas.json#/definitions/ArrayObject", externalRef); + Assert.Equal("../foo/schemas.yaml#/components/schemas/Number", externalRef2); + } } } diff --git a/test/Microsoft.OpenApi.Readers.Tests/V3Tests/Samples/OpenApiDocument/documentWithExternalRefs.yaml b/test/Microsoft.OpenApi.Readers.Tests/V3Tests/Samples/OpenApiDocument/documentWithExternalRefs.yaml new file mode 100644 index 000000000..c0b7b3a25 --- /dev/null +++ b/test/Microsoft.OpenApi.Readers.Tests/V3Tests/Samples/OpenApiDocument/documentWithExternalRefs.yaml @@ -0,0 +1,16 @@ + openapi: 3.0.1 + info: + title: anyOf-oneOf + license: + name: MIT + version: 1.0.0 + paths: { } + components: + schemas: + Nested: + type: object + properties: + AnyOf: + anyOf: + - $ref: file:///C:/MySchemas.json#/definitions/ArrayObject + - $ref: ../foo/schemas.yaml#/components/schemas/Number \ No newline at end of file From f73e673ac00b5a1d1e3e9c51bd27c57631f6bbe9 Mon Sep 17 00:00:00 2001 From: Maggie Kimani Date: Fri, 18 Nov 2022 12:57:52 +0300 Subject: [PATCH 3/4] Update public API --- test/Microsoft.OpenApi.Tests/PublicApi/PublicApi.approved.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/test/Microsoft.OpenApi.Tests/PublicApi/PublicApi.approved.txt b/test/Microsoft.OpenApi.Tests/PublicApi/PublicApi.approved.txt index 75e12f480..4eb7a060d 100755 --- a/test/Microsoft.OpenApi.Tests/PublicApi/PublicApi.approved.txt +++ b/test/Microsoft.OpenApi.Tests/PublicApi/PublicApi.approved.txt @@ -773,6 +773,7 @@ namespace Microsoft.OpenApi.Models } public class OpenApiReference : Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiSerializable { + public bool IsFragrament; public OpenApiReference() { } public OpenApiReference(Microsoft.OpenApi.Models.OpenApiReference reference) { } public string ExternalResource { get; set; } From 4428e67a9d61c69d9b77bd526e94b6c9ae42c0b7 Mon Sep 17 00:00:00 2001 From: Maggie Kimani Date: Fri, 18 Nov 2022 16:13:22 +0300 Subject: [PATCH 4/4] Move variable declaration closer to assignment --- src/Microsoft.OpenApi.Readers/V3/OpenApiV3VersionService.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Microsoft.OpenApi.Readers/V3/OpenApiV3VersionService.cs b/src/Microsoft.OpenApi.Readers/V3/OpenApiV3VersionService.cs index 742b64388..ebe372d40 100644 --- a/src/Microsoft.OpenApi.Readers/V3/OpenApiV3VersionService.cs +++ b/src/Microsoft.OpenApi.Readers/V3/OpenApiV3VersionService.cs @@ -71,7 +71,6 @@ public OpenApiReference ConvertToOpenApiReference( string reference, ReferenceType? type) { - var openApiReference = new OpenApiReference(); if (!string.IsNullOrWhiteSpace(reference)) { var segments = reference.Split('#'); @@ -110,6 +109,8 @@ public OpenApiReference ConvertToOpenApiReference( } // Where fragments point into a non-OpenAPI document, the id will be the complete fragment identifier string id = segments[1]; + var openApiReference = new OpenApiReference(); + // $ref: externalSource.yaml#/Pet if (id.StartsWith("/components/")) {