diff --git a/src/Microsoft.OpenApi.Readers/V3/OpenApiV3VersionService.cs b/src/Microsoft.OpenApi.Readers/V3/OpenApiV3VersionService.cs index 1e729f30a..ebe372d40 100644 --- a/src/Microsoft.OpenApi.Readers/V3/OpenApiV3VersionService.cs +++ b/src/Microsoft.OpenApi.Readers/V3/OpenApiV3VersionService.cs @@ -109,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/")) { @@ -127,13 +129,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; 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 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; }