diff --git a/src/Microsoft.OpenApi.Readers/OpenApiReaderSettings.cs b/src/Microsoft.OpenApi.Readers/OpenApiReaderSettings.cs
index 5d251802..e337fbb3 100644
--- a/src/Microsoft.OpenApi.Readers/OpenApiReaderSettings.cs
+++ b/src/Microsoft.OpenApi.Readers/OpenApiReaderSettings.cs
@@ -5,6 +5,7 @@
using Microsoft.OpenApi.Interfaces;
using Microsoft.OpenApi.MicrosoftExtensions;
using Microsoft.OpenApi.Readers.Interface;
+using Microsoft.OpenApi.Services;
using Microsoft.OpenApi.Validations;
using System;
using System.Collections.Generic;
@@ -81,6 +82,11 @@ public class OpenApiReaderSettings
///
public bool LeaveStreamOpen { get; set; }
+ ///
+ /// Yolo
+ ///
+ public OpenApiWorkspace Workspace { get; set; } = new();
+
///
/// Adds parsers for Microsoft OpenAPI extensions:
/// -
diff --git a/src/Microsoft.OpenApi.Readers/OpenApiStreamReader.cs b/src/Microsoft.OpenApi.Readers/OpenApiStreamReader.cs
index c6c8add2..e334e232 100644
--- a/src/Microsoft.OpenApi.Readers/OpenApiStreamReader.cs
+++ b/src/Microsoft.OpenApi.Readers/OpenApiStreamReader.cs
@@ -9,6 +9,7 @@
using Microsoft.OpenApi.Interfaces;
using Microsoft.OpenApi.Models;
using Microsoft.OpenApi.Readers.Interface;
+using Microsoft.OpenApi.Services;
namespace Microsoft.OpenApi.Readers
{
@@ -18,14 +19,23 @@ namespace Microsoft.OpenApi.Readers
public class OpenApiStreamReader : IOpenApiReader
{
private readonly OpenApiReaderSettings _settings;
+ private string _reference;
///
/// Create stream reader with custom settings if desired.
///
///
- public OpenApiStreamReader(OpenApiReaderSettings settings = null)
+ public OpenApiStreamReader(OpenApiReaderSettings settings = null) : this(settings, null) { }
+
+ ///
+ /// Create stream reader with custom settings if desired.
+ ///
+ ///
+ ///
+ public OpenApiStreamReader(OpenApiReaderSettings settings = null, string reference = null)
{
_settings = settings ?? new OpenApiReaderSettings();
+ _reference = reference;
if((_settings.ReferenceResolution == ReferenceResolutionSetting.ResolveAllReferences || _settings.LoadExternalRefs)
&& _settings.BaseUrl == null)
@@ -43,7 +53,7 @@ public OpenApiStreamReader(OpenApiReaderSettings settings = null)
public OpenApiDocument Read(Stream input, out OpenApiDiagnostic diagnostic)
{
using var reader = new StreamReader(input, Encoding.UTF8, true, 4096, _settings.LeaveStreamOpen);
- return new OpenApiTextReaderReader(_settings).Read(reader, out diagnostic);
+ return new OpenApiTextReaderReader(_settings, _reference).Read(reader, out diagnostic);
}
///
@@ -71,7 +81,7 @@ public async Task ReadAsync(Stream input, CancellationToken cancella
}
using var reader = new StreamReader(bufferedStream, Encoding.UTF8, true, bufferSize, _settings.LeaveStreamOpen);
- return await new OpenApiTextReaderReader(_settings).ReadAsync(reader, cancellationToken);
+ return await new OpenApiTextReaderReader(_settings, _reference).ReadAsync(reader, cancellationToken);
}
///
@@ -84,7 +94,7 @@ public async Task ReadAsync(Stream input, CancellationToken cancella
public T ReadFragment(Stream input, OpenApiSpecVersion version, out OpenApiDiagnostic diagnostic) where T : IOpenApiReferenceable
{
using var reader = new StreamReader(input, Encoding.UTF8, true, 4096, _settings.LeaveStreamOpen);
- return new OpenApiTextReaderReader(_settings).ReadFragment(reader, version, out diagnostic);
+ return new OpenApiTextReaderReader(_settings, _reference).ReadFragment(reader, version, out diagnostic);
}
}
}
diff --git a/src/Microsoft.OpenApi.Readers/OpenApiStringReader.cs b/src/Microsoft.OpenApi.Readers/OpenApiStringReader.cs
index 1a694f25..51eb7f75 100644
--- a/src/Microsoft.OpenApi.Readers/OpenApiStringReader.cs
+++ b/src/Microsoft.OpenApi.Readers/OpenApiStringReader.cs
@@ -14,14 +14,23 @@ namespace Microsoft.OpenApi.Readers
public class OpenApiStringReader : IOpenApiReader
{
private readonly OpenApiReaderSettings _settings;
+ private string _reference;
+
+ ///
+ /// Create stream reader with custom settings if desired.
+ ///
+ ///
+ public OpenApiStringReader(OpenApiReaderSettings settings = null) : this(settings, null) { }
///
/// Constructor tha allows reader to use non-default settings
///
///
- public OpenApiStringReader(OpenApiReaderSettings settings = null)
+ ///
+ public OpenApiStringReader(OpenApiReaderSettings settings = null, string reference = null)
{
_settings = settings ?? new OpenApiReaderSettings();
+ _reference = reference;
}
///
@@ -30,7 +39,7 @@ public OpenApiStringReader(OpenApiReaderSettings settings = null)
public OpenApiDocument Read(string input, out OpenApiDiagnostic diagnostic)
{
using var reader = new StringReader(input);
- return new OpenApiTextReaderReader(_settings).Read(reader, out diagnostic);
+ return new OpenApiTextReaderReader(_settings, _reference).Read(reader, out diagnostic);
}
///
@@ -39,7 +48,7 @@ public OpenApiDocument Read(string input, out OpenApiDiagnostic diagnostic)
public T ReadFragment(string input, OpenApiSpecVersion version, out OpenApiDiagnostic diagnostic) where T : IOpenApiElement
{
using var reader = new StringReader(input);
- return new OpenApiTextReaderReader(_settings).ReadFragment(reader, version, out diagnostic);
+ return new OpenApiTextReaderReader(_settings, _reference).ReadFragment(reader, version, out diagnostic);
}
}
}
diff --git a/src/Microsoft.OpenApi.Readers/OpenApiTextReaderReader.cs b/src/Microsoft.OpenApi.Readers/OpenApiTextReaderReader.cs
index dff20fc7..a491866b 100644
--- a/src/Microsoft.OpenApi.Readers/OpenApiTextReaderReader.cs
+++ b/src/Microsoft.OpenApi.Readers/OpenApiTextReaderReader.cs
@@ -19,14 +19,17 @@ namespace Microsoft.OpenApi.Readers
public class OpenApiTextReaderReader : IOpenApiReader
{
private readonly OpenApiReaderSettings _settings;
+ private string _reference;
///
/// Create stream reader with custom settings if desired.
///
///
- public OpenApiTextReaderReader(OpenApiReaderSettings settings = null)
+ ///
+ public OpenApiTextReaderReader(OpenApiReaderSettings settings = null, string reference = null)
{
_settings = settings ?? new OpenApiReaderSettings();
+ _reference = reference;
}
///
@@ -51,7 +54,7 @@ public OpenApiDocument Read(TextReader input, out OpenApiDiagnostic diagnostic)
return new();
}
- return new OpenApiYamlDocumentReader(this._settings).Read(yamlDocument, out diagnostic);
+ return new OpenApiYamlDocumentReader(this._settings, _reference).Read(yamlDocument, out diagnostic);
}
///
@@ -80,7 +83,7 @@ public async Task ReadAsync(TextReader input, CancellationToken canc
};
}
- return await new OpenApiYamlDocumentReader(this._settings).ReadAsync(yamlDocument, cancellationToken);
+ return await new OpenApiYamlDocumentReader(this._settings, _reference).ReadAsync(yamlDocument, cancellationToken);
}
///
@@ -106,7 +109,7 @@ public async Task ReadAsync(TextReader input, CancellationToken canc
return default;
}
- return new OpenApiYamlDocumentReader(this._settings).ReadFragment(yamlDocument, version, out diagnostic);
+ return new OpenApiYamlDocumentReader(this._settings, _reference).ReadFragment(yamlDocument, version, out diagnostic);
}
///
diff --git a/src/Microsoft.OpenApi.Readers/OpenApiYamlDocumentReader.cs b/src/Microsoft.OpenApi.Readers/OpenApiYamlDocumentReader.cs
index af9ebcad..2fccd9aa 100644
--- a/src/Microsoft.OpenApi.Readers/OpenApiYamlDocumentReader.cs
+++ b/src/Microsoft.OpenApi.Readers/OpenApiYamlDocumentReader.cs
@@ -24,14 +24,23 @@ namespace Microsoft.OpenApi.Readers
internal class OpenApiYamlDocumentReader : IOpenApiReader
{
private readonly OpenApiReaderSettings _settings;
+ private readonly string _reference;
///
/// Create stream reader with custom settings if desired.
///
///
- public OpenApiYamlDocumentReader(OpenApiReaderSettings settings = null)
+ public OpenApiYamlDocumentReader(OpenApiReaderSettings settings = null) : this(settings, null) { }
+
+ ///
+ /// Create stream reader with custom settings if desired.
+ ///
+ ///
+ ///
+ public OpenApiYamlDocumentReader(OpenApiReaderSettings settings = null, string reference = null)
{
_settings = settings ?? new OpenApiReaderSettings();
+ _reference = reference;
}
///
@@ -102,7 +111,7 @@ public async Task ReadAsync(YamlDocument input, CancellationToken ca
if (_settings.LoadExternalRefs)
{
- var diagnosticExternalRefs = await LoadExternalRefsAsync(document, cancellationToken);
+ var diagnosticExternalRefs = await LoadExternalRefsAsync(document, _reference, cancellationToken);
// Merge diagnostics of external reference
if (diagnosticExternalRefs != null)
{
@@ -139,15 +148,15 @@ public async Task ReadAsync(YamlDocument input, CancellationToken ca
};
}
- private Task LoadExternalRefsAsync(OpenApiDocument document, CancellationToken cancellationToken = default)
+ private Task LoadExternalRefsAsync(OpenApiDocument document, string reference = null, CancellationToken cancellationToken = default)
{
// Create workspace for all documents to live in.
- var openApiWorkSpace = new OpenApiWorkspace();
+ var openApiWorkSpace = _settings.Workspace;
// Load this root document into the workspace
var streamLoader = new DefaultStreamLoader(_settings.BaseUrl);
var workspaceLoader = new OpenApiWorkspaceLoader(openApiWorkSpace, _settings.CustomExternalLoader ?? streamLoader, _settings);
- return workspaceLoader.LoadAsync(new() { ExternalResource = "/" }, document, null, cancellationToken);
+ return workspaceLoader.LoadAsync(new() { ExternalResource = reference ?? "/" }, document, null, cancellationToken);
}
private void ResolveReferences(OpenApiDiagnostic diagnostic, OpenApiDocument document)
diff --git a/src/Microsoft.OpenApi.Readers/Services/OpenApiWorkspaceLoader.cs b/src/Microsoft.OpenApi.Readers/Services/OpenApiWorkspaceLoader.cs
index c2d1cfe3..8c925608 100644
--- a/src/Microsoft.OpenApi.Readers/Services/OpenApiWorkspaceLoader.cs
+++ b/src/Microsoft.OpenApi.Readers/Services/OpenApiWorkspaceLoader.cs
@@ -22,6 +22,11 @@ public OpenApiWorkspaceLoader(OpenApiWorkspace workspace, IStreamLoader loader,
internal async Task LoadAsync(OpenApiReference reference, OpenApiDocument document, OpenApiDiagnostic diagnostic = null, CancellationToken cancellationToken = default)
{
+ if (_workspace.Contains(reference.ExternalResource))
+ {
+ return diagnostic;
+ }
+
_workspace.AddDocument(reference.ExternalResource, document);
document.Workspace = _workspace;
@@ -30,8 +35,6 @@ internal async Task LoadAsync(OpenApiReference reference, Ope
var collectorWalker = new OpenApiWalker(referenceCollector);
collectorWalker.Walk(document);
- var reader = new OpenApiStreamReader(_readerSettings);
-
if (diagnostic is null)
{
diagnostic = new();
@@ -43,6 +46,7 @@ internal async Task LoadAsync(OpenApiReference reference, Ope
// If not already in workspace, load it and process references
if (!_workspace.Contains(item.ExternalResource))
{
+ var reader = new OpenApiStreamReader(_readerSettings, item.ExternalResource);
var input = await _loader.LoadAsync(new(item.ExternalResource, UriKind.RelativeOrAbsolute));
var result = await reader.ReadAsync(input, cancellationToken);
// Merge diagnostics