Skip to content

Commit 1debbf2

Browse files
committed
Updated OpenApiWorkspaceLoader to support loading external references
1 parent 2ddc0a7 commit 1debbf2

File tree

4 files changed

+57
-9
lines changed

4 files changed

+57
-9
lines changed

src/Microsoft.OpenApi.Readers/OpenApiReaderSettings.cs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,13 @@
33

44
using Microsoft.OpenApi.Any;
55
using Microsoft.OpenApi.Interfaces;
6+
using Microsoft.OpenApi.Readers.Interface;
67
using Microsoft.OpenApi.Readers.ParseNodes;
8+
using Microsoft.OpenApi.Readers.Services;
79
using Microsoft.OpenApi.Validations;
810
using System;
911
using System.Collections.Generic;
12+
using System.IO;
1013
using System.Linq;
1114
using System.Text;
1215
using System.Threading.Tasks;
@@ -56,5 +59,13 @@ public class OpenApiReaderSettings
5659
/// URL where relative references should be resolved from if the description does not contain Server definitions
5760
/// </summary>
5861
public Uri BaseUrl { get; set; }
62+
63+
/// <summary>
64+
/// Function used to provide an alternative loader for accessing external references.
65+
/// </summary>
66+
/// <remarks>
67+
/// Default loader will attempt to dereference http(s) urls and file urls.
68+
/// </remarks>
69+
public Func<Uri, Task<Stream>> CustomExternalLoader { get; set; }
5970
}
6071
}

src/Microsoft.OpenApi.Readers/OpenApiYamlDocumentReader.cs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// Licensed under the MIT license.
33

44
using System;
5+
using System.IO;
56
using Microsoft.OpenApi.Exceptions;
67
using Microsoft.OpenApi.Extensions;
78
using Microsoft.OpenApi.Interfaces;
@@ -54,6 +55,14 @@ public OpenApiDocument Read(YamlDocument input, out OpenApiDiagnostic diagnostic
5455
switch (_settings.ReferenceResolution)
5556
{
5657
case ReferenceResolutionSetting.ResolveAllReferences:
58+
var openApiWorkSpace = new OpenApiWorkspace();
59+
document.Workspace = openApiWorkSpace;
60+
var streamLoader = new DefaultStreamLoader();
61+
62+
var workspaceLoader = new OpenApiWorkspaceLoader(openApiWorkSpace, _settings.CustomExternalLoader ?? streamLoader.LoadAsync, _settings);
63+
workspaceLoader.LoadAsync(new OpenApiReference() { ExternalResource="/" }, document);
64+
65+
// TODO: Need to add ReadAsync for resolving all references.
5766
throw new ArgumentException(Properties.SRResource.CannotResolveRemoteReferencesSynchronously);
5867
case ReferenceResolutionSetting.ResolveLocalReferences:
5968
var errors = document.ResolveReferences(false);

src/Microsoft.OpenApi.Readers/Services/OpenApiWorkspaceLoader.cs

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,21 +7,22 @@
77
using Microsoft.OpenApi.Models;
88
using Microsoft.OpenApi.Readers.Interface;
99
using Microsoft.OpenApi.Services;
10+
using SharpYaml.Model;
1011

1112
namespace Microsoft.OpenApi.Readers.Services
1213
{
13-
internal class OpenApiWorkspaceLoader<TInput,TDiagnostic> where TDiagnostic: IDiagnostic
14+
internal class OpenApiWorkspaceLoader
1415
{
1516
private OpenApiWorkspace _workspace;
16-
private IInputLoader<TInput> _loader;
17-
private TDiagnostic _diagnostics;
18-
private IOpenApiReader<TInput, TDiagnostic> _reader;
17+
private Func<Uri, Task<Stream>> _loader;
18+
private OpenApiDiagnostic _diagnostics;
19+
private OpenApiReaderSettings _readerSettings;
1920

20-
public OpenApiWorkspaceLoader(OpenApiWorkspace workspace, IInputLoader<TInput> loader, IOpenApiReader<TInput, TDiagnostic> reader)
21+
public OpenApiWorkspaceLoader(OpenApiWorkspace workspace, Func<Uri,Task<Stream>> loader, OpenApiReaderSettings readerSettings)
2122
{
2223
_workspace = workspace;
2324
_loader = loader;
24-
_reader = reader;
25+
_readerSettings = readerSettings;
2526
}
2627

2728
internal async Task LoadAsync(OpenApiReference reference, OpenApiDocument document)
@@ -34,14 +35,16 @@ internal async Task LoadAsync(OpenApiReference reference, OpenApiDocument docume
3435
var collectorWalker = new OpenApiWalker(referenceCollector);
3536
collectorWalker.Walk(document);
3637

38+
var reader = new OpenApiStreamReader(_readerSettings);
39+
3740
// Walk references
3841
foreach (var item in referenceCollector.References)
3942
{
4043
// If not already in workspace, load it and process references
4144
if (!_workspace.Contains(item.ExternalResource))
4245
{
43-
var input = await _loader.LoadAsync(new Uri(item.ExternalResource));
44-
var newDocument = _reader.Read(input, out _diagnostics);
46+
var input = await _loader(new Uri(item.ExternalResource));
47+
var newDocument = reader.Read(input, out _diagnostics); // TODO merge _diagnositics
4548
await LoadAsync(item, newDocument);
4649
}
4750
}
Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,37 @@
11
using System;
22
using System.Collections.Generic;
3+
using System.IO;
34
using System.Linq;
45
using System.Text;
56
using System.Threading.Tasks;
7+
using Microsoft.OpenApi.Models;
8+
using Microsoft.OpenApi.Readers.Interface;
9+
using Microsoft.OpenApi.Readers.Services;
10+
using Microsoft.OpenApi.Services;
11+
using Xunit;
612

713
namespace Microsoft.OpenApi.Readers.Tests.OpenApiWorkspaceTests
814
{
9-
class OpenApiWorkspaceStreamTests
15+
public class OpenApiWorkspaceStreamTests
1016
{
17+
18+
19+
// Use OpenApiWorkspace to load a document and a referenced document
20+
21+
//[Fact]
22+
public void LoadDocumentIntoWorkspace()
23+
{
24+
// Create a reader that will resolve all references
25+
var reader = new OpenApiStringReader(new OpenApiReaderSettings() {
26+
ReferenceResolution = ReferenceResolutionSetting.ResolveAllReferences,
27+
CustomExternalLoader = (url) => { return null; }
28+
});
29+
30+
// Todo: this should be ReadAsync
31+
var doc = reader.Read("", out OpenApiDiagnostic diagnostic);
32+
33+
Assert.NotNull(doc.Workspace);
34+
35+
}
1136
}
1237
}

0 commit comments

Comments
 (0)