Skip to content

Commit 482175d

Browse files
Merge pull request #1082 from microsoft/mk/reader-changes-external-reference
Fixes reader changing external reference bug
2 parents ed00216 + 4428e67 commit 482175d

File tree

6 files changed

+62
-7
lines changed

6 files changed

+62
-7
lines changed

src/Microsoft.OpenApi.Readers/V3/OpenApiV3VersionService.cs

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,8 @@ public OpenApiReference ConvertToOpenApiReference(
109109
}
110110
// Where fragments point into a non-OpenAPI document, the id will be the complete fragment identifier
111111
string id = segments[1];
112+
var openApiReference = new OpenApiReference();
113+
112114
// $ref: externalSource.yaml#/Pet
113115
if (id.StartsWith("/components/"))
114116
{
@@ -127,13 +129,16 @@ public OpenApiReference ConvertToOpenApiReference(
127129
}
128130
id = localSegments[3];
129131
}
130-
131-
return new OpenApiReference
132+
else
132133
{
133-
ExternalResource = segments[0],
134-
Type = type,
135-
Id = id
136-
};
134+
openApiReference.IsFragrament = true;
135+
}
136+
137+
openApiReference.ExternalResource = segments[0];
138+
openApiReference.Type = type;
139+
openApiReference.Id = id;
140+
141+
return openApiReference;
137142
}
138143
}
139144

src/Microsoft.OpenApi/Models/OpenApiReference.cs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,11 @@ public class OpenApiReference : IOpenApiSerializable
4545
/// </summary>
4646
public bool IsLocal => ExternalResource == null;
4747

48+
/// <summary>
49+
/// Gets a flag indicating whether a file is a valid OpenAPI document or a fragment
50+
/// </summary>
51+
public bool IsFragrament = false;
52+
4853
/// <summary>
4954
/// The OpenApiDocument that is hosting the OpenApiReference instance. This is used to enable dereferencing the reference.
5055
/// </summary>
@@ -196,7 +201,12 @@ private string GetExternalReferenceV3()
196201
{
197202
if (Id != null)
198203
{
199-
return ExternalResource + "#/components/" + Type.GetDisplayName() + "/"+ Id;
204+
if (IsFragrament)
205+
{
206+
return ExternalResource + "#" + Id;
207+
}
208+
209+
return ExternalResource + "#/components/" + Type.GetDisplayName() + "/"+ Id;
200210
}
201211

202212
return ExternalResource;

test/Microsoft.OpenApi.Readers.Tests/Microsoft.OpenApi.Readers.Tests.csproj

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,9 @@
149149
<EmbeddedResource Include="V3Tests\Samples\OpenApiDocument\petStoreWithTagAndSecurity.yaml">
150150
<CopyToOutputDirectory>Never</CopyToOutputDirectory>
151151
</EmbeddedResource>
152+
<EmbeddedResource Include="V3Tests\Samples\OpenApiDocument\documentWithExternalRefs.yaml">
153+
<CopyToOutputDirectory>Never</CopyToOutputDirectory>
154+
</EmbeddedResource>
152155
<EmbeddedResource Include="V3Tests\Samples\OpenApiDocument\securedApi.yaml" />
153156
<EmbeddedResource Include="V3Tests\Samples\OpenApiEncoding\advancedEncoding.yaml">
154157
<CopyToOutputDirectory>Never</CopyToOutputDirectory>

test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiDocumentTests.cs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
using System.Globalization;
77
using System.IO;
88
using System.Linq;
9+
using System.Text;
910
using System.Threading;
1011
using FluentAssertions;
1112
using Microsoft.OpenApi.Any;
@@ -1327,5 +1328,24 @@ public void HeaderParameterShouldAllowExample()
13271328
});
13281329
}
13291330
}
1331+
1332+
[Fact]
1333+
public void DoesNotChangeExternalReferences()
1334+
{
1335+
// Arrange
1336+
using var stream = Resources.GetStream(Path.Combine(SampleFolderPath, "documentWithExternalRefs.yaml"));
1337+
1338+
// Act
1339+
var doc = new OpenApiStreamReader(
1340+
new OpenApiReaderSettings { ReferenceResolution = ReferenceResolutionSetting.DoNotResolveReferences})
1341+
.Read(stream, out var diagnostic);
1342+
1343+
var externalRef = doc.Components.Schemas["Nested"].Properties["AnyOf"].AnyOf.First().Reference.ReferenceV3;
1344+
var externalRef2 = doc.Components.Schemas["Nested"].Properties["AnyOf"].AnyOf.Last().Reference.ReferenceV3;
1345+
1346+
// Assert
1347+
Assert.Equal("file:///C:/MySchemas.json#/definitions/ArrayObject", externalRef);
1348+
Assert.Equal("../foo/schemas.yaml#/components/schemas/Number", externalRef2);
1349+
}
13301350
}
13311351
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
openapi: 3.0.1
2+
info:
3+
title: anyOf-oneOf
4+
license:
5+
name: MIT
6+
version: 1.0.0
7+
paths: { }
8+
components:
9+
schemas:
10+
Nested:
11+
type: object
12+
properties:
13+
AnyOf:
14+
anyOf:
15+
- $ref: file:///C:/MySchemas.json#/definitions/ArrayObject
16+
- $ref: ../foo/schemas.yaml#/components/schemas/Number

test/Microsoft.OpenApi.Tests/PublicApi/PublicApi.approved.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -773,6 +773,7 @@ namespace Microsoft.OpenApi.Models
773773
}
774774
public class OpenApiReference : Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiSerializable
775775
{
776+
public bool IsFragrament;
776777
public OpenApiReference() { }
777778
public OpenApiReference(Microsoft.OpenApi.Models.OpenApiReference reference) { }
778779
public string ExternalResource { get; set; }

0 commit comments

Comments
 (0)