Skip to content

Commit b635242

Browse files
authored
Merge pull request #2873 from microsoft/fix/invalid-circular-ref
fix(library): avoid false circular refs for external schema re-exports
2 parents 9b1aed6 + 7a443c2 commit b635242

2 files changed

Lines changed: 75 additions & 1 deletion

File tree

src/Microsoft.OpenApi/Services/OpenApiWorkspace.cs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,8 +94,13 @@ public void RegisterComponents(OpenApiDocument document)
9494
foreach (var item in document.Components.Schemas)
9595
{
9696
if (item.Value == null) continue;
97-
location = item.Value.Id ?? baseUri + ReferenceType.Schema.GetDisplayName() + ComponentSegmentSeparator + item.Key;
97+
location = baseUri + ReferenceType.Schema.GetDisplayName() + ComponentSegmentSeparator + item.Key;
9898
RegisterComponent(location, item.Value);
99+
100+
if (item.Value is not OpenApiSchemaReference && item.Value.Id is string schemaId && schemaId.Length > 0)
101+
{
102+
RegisterComponent(schemaId, item.Value);
103+
}
99104
}
100105
}
101106

test/Microsoft.OpenApi.Readers.Tests/V31Tests/RelativeReferenceTests.cs

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,75 @@ public async Task ParseLocalReferenceToJsonSchemaResourceWorks()
203203
Assert.Equal(JsonSchemaType.Object | JsonSchemaType.Null, schema.Type);
204204
}
205205

206+
[Fact]
207+
public async Task ParseExternalSchemaReferencedDirectlyAndReExportedAtRootWorks()
208+
{
209+
var tempDirectory = Path.Join(Path.GetTempPath(), Guid.NewGuid().ToString("N"));
210+
Directory.CreateDirectory(tempDirectory);
211+
212+
var rootPath = Path.Join(tempDirectory, "root.yaml");
213+
var sharedPath = Path.Join(tempDirectory, "shared.yaml");
214+
215+
await File.WriteAllTextAsync(rootPath,
216+
@"openapi: 3.1.0
217+
info:
218+
title: T
219+
version: 1.0.0
220+
paths:
221+
/a:
222+
get:
223+
responses:
224+
'200':
225+
description: ok
226+
content:
227+
application/json:
228+
schema:
229+
type: object
230+
properties:
231+
meta:
232+
$ref: './shared.yaml#/Leaf'
233+
components:
234+
schemas:
235+
Leaf:
236+
$ref: './shared.yaml#/Leaf'
237+
");
238+
239+
await File.WriteAllTextAsync(sharedPath,
240+
@"Leaf:
241+
type: object
242+
properties:
243+
x:
244+
type: string
245+
y:
246+
type: integer
247+
");
248+
249+
try
250+
{
251+
var settings = new OpenApiReaderSettings
252+
{
253+
LoadExternalRefs = true,
254+
BaseUrl = new Uri(rootPath),
255+
};
256+
settings.AddYamlReader();
257+
258+
var result = await OpenApiDocument.LoadAsync(rootPath, settings);
259+
var responseSchema = result.Document.Paths["/a"].Operations[HttpMethod.Get].Responses["200"].Content["application/json"].Schema;
260+
var metaSchema = responseSchema.Properties["meta"];
261+
var leafSchema = result.Document.Components.Schemas["Leaf"];
262+
263+
Assert.NotNull(result.Document);
264+
Assert.DoesNotContain(result.Diagnostic.Errors, error => error.Message.Contains("Circular reference detected while resolving schema", StringComparison.Ordinal));
265+
Assert.DoesNotContain(result.Diagnostic.Warnings, warning => warning.Message.Contains("Circular reference detected while resolving schema", StringComparison.Ordinal));
266+
Assert.IsType<OpenApiSchemaReference>(metaSchema);
267+
Assert.IsType<OpenApiSchemaReference>(leafSchema);
268+
}
269+
finally
270+
{
271+
Directory.Delete(tempDirectory, true);
272+
}
273+
}
274+
206275
[Fact]
207276
public void ResolveSubSchema_ShouldTraverseKnownKeywords()
208277
{

0 commit comments

Comments
 (0)