Skip to content

Commit

Permalink
Merge pull request #2150 from microsoft/fix/load-external-references
Browse files Browse the repository at this point in the history
fix/load external references
  • Loading branch information
baywet authored Feb 17, 2025
2 parents 20aacc1 + 3afb8db commit f61cbe1
Show file tree
Hide file tree
Showing 6 changed files with 35 additions and 28 deletions.
4 changes: 3 additions & 1 deletion src/Microsoft.OpenApi/Interfaces/IStreamLoader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

using System;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.OpenApi.Models;

Expand All @@ -17,7 +18,8 @@ public interface IStreamLoader
/// Use Uri to locate data and convert into an input object.
/// </summary>
/// <param name="uri">Identifier of some source of an OpenAPI Description</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>A data object that can be processed by a reader to generate an <see cref="OpenApiDocument"/></returns>
Task<Stream> LoadAsync(Uri uri);
Task<Stream> LoadAsync(Uri uri, CancellationToken cancellationToken = default);
}
}
41 changes: 22 additions & 19 deletions src/Microsoft.OpenApi/Reader/Services/DefaultStreamLoader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
using System;
using System.IO;
using System.Net.Http;
using System.Runtime.InteropServices;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.OpenApi.Interfaces;
using Microsoft.OpenApi.Models;
Expand All @@ -27,28 +29,29 @@ public DefaultStreamLoader(Uri baseUrl)
this.baseUrl = baseUrl;
}

/// <summary>
/// Use Uri to locate data and convert into an input object.
/// </summary>
/// <param name="uri">Identifier of some source of an OpenAPI Description</param>
/// <returns>A data object that can be processed by a reader to generate an <see cref="OpenApiDocument"/></returns>
/// <exception cref="ArgumentException"></exception>
public async Task<Stream> LoadAsync(Uri uri)
/// <inheritdoc/>
public async Task<Stream> LoadAsync(Uri uri, CancellationToken cancellationToken = default)
{
Uri absoluteUri;
absoluteUri = baseUrl.AbsoluteUri.Equals(OpenApiConstants.BaseRegistryUri) ? new Uri(Directory.GetCurrentDirectory() + uri)
: new Uri(baseUrl, uri);
var absoluteUri = (baseUrl.AbsoluteUri.Equals(OpenApiConstants.BaseRegistryUri), baseUrl.IsAbsoluteUri, uri.IsAbsoluteUri) switch
{
(true, _, _) => new Uri(Path.Combine(Directory.GetCurrentDirectory(), uri.ToString())),
// this overcomes a URI concatenation issue for local paths on linux OSes
(_, true, false) when baseUrl.Scheme.Equals("file", StringComparison.OrdinalIgnoreCase) && !RuntimeInformation.IsOSPlatform(OSPlatform.Windows) =>
new Uri(Path.Combine(baseUrl.AbsoluteUri, uri.ToString())),
(_, _, _) => new Uri(baseUrl, uri),
};

switch (absoluteUri.Scheme)
return absoluteUri.Scheme switch
{
case "file":
return File.OpenRead(absoluteUri.AbsolutePath);
case "http":
case "https":
return await _httpClient.GetStreamAsync(absoluteUri);
default:
throw new ArgumentException("Unsupported scheme");
}
"file" => File.OpenRead(absoluteUri.AbsolutePath),
"http" or "https" =>
#if NET5_0_OR_GREATER
await _httpClient.GetStreamAsync(absoluteUri, cancellationToken).ConfigureAwait(false),
#else
await _httpClient.GetStreamAsync(absoluteUri).ConfigureAwait(false),
#endif
_ => throw new ArgumentException("Unsupported scheme"),
};
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -45,16 +45,16 @@ internal async Task<OpenApiDiagnostic> LoadAsync(OpenApiReference reference,
// If not already in workspace, load it and process references
if (!_workspace.Contains(item.ExternalResource))
{
var input = await _loader.LoadAsync(new(item.ExternalResource, UriKind.RelativeOrAbsolute));
var result = await OpenApiDocument.LoadAsync(input, format, _readerSettings, cancellationToken);
var input = await _loader.LoadAsync(new(item.ExternalResource, UriKind.RelativeOrAbsolute), cancellationToken).ConfigureAwait(false);
var result = await OpenApiDocument.LoadAsync(input, format, _readerSettings, cancellationToken).ConfigureAwait(false);
// Merge diagnostics
if (result.Diagnostic != null)
{
diagnostic.AppendDiagnostic(result.Diagnostic, item.ExternalResource);
}
if (result.Document != null)
{
var loadDiagnostic = await LoadAsync(item, result.Document, format, diagnostic, cancellationToken);
var loadDiagnostic = await LoadAsync(item, result.Document, format, diagnostic, cancellationToken).ConfigureAwait(false);
diagnostic = loadDiagnostic;
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.

using System.Threading;
using System.Threading.Tasks;
using System;
using Microsoft.OpenApi.Models;
Expand Down Expand Up @@ -64,7 +65,7 @@ public Stream Load(Uri uri)
return null;
}

public Task<Stream> LoadAsync(Uri uri)
public Task<Stream> LoadAsync(Uri uri, CancellationToken cancellationToken = default)
{
var path = new Uri(new("http://example.org/OpenApiReaderTests/Samples/OpenApiDiagnosticReportMerged/"), uri).AbsolutePath;
path = path[1..]; // remove leading slash
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.OpenApi.Interfaces;
using Microsoft.OpenApi.Models;
Expand Down Expand Up @@ -80,7 +81,7 @@ public Stream Load(Uri uri)
return null;
}

public Task<Stream> LoadAsync(Uri uri)
public Task<Stream> LoadAsync(Uri uri, CancellationToken cancellationToken = default)
{
return Task.FromResult<Stream>(null);
}
Expand All @@ -93,7 +94,7 @@ public Stream Load(Uri uri)
return null;
}

public Task<Stream> LoadAsync(Uri uri)
public Task<Stream> LoadAsync(Uri uri, CancellationToken cancellationToken = default)
{
var path = new Uri(new("http://example.org/V3Tests/Samples/OpenApiWorkspace/"), uri).AbsolutePath;
path = path[1..]; // remove leading slash
Expand Down
4 changes: 2 additions & 2 deletions test/Microsoft.OpenApi.Tests/PublicApi/PublicApi.approved.txt
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,7 @@ namespace Microsoft.OpenApi.Interfaces
}
public interface IStreamLoader
{
System.Threading.Tasks.Task<System.IO.Stream> LoadAsync(System.Uri uri);
System.Threading.Tasks.Task<System.IO.Stream> LoadAsync(System.Uri uri, System.Threading.CancellationToken cancellationToken = default);
}
}
namespace Microsoft.OpenApi
Expand Down Expand Up @@ -1554,7 +1554,7 @@ namespace Microsoft.OpenApi.Reader.Services
public class DefaultStreamLoader : Microsoft.OpenApi.Interfaces.IStreamLoader
{
public DefaultStreamLoader(System.Uri baseUrl) { }
public System.Threading.Tasks.Task<System.IO.Stream> LoadAsync(System.Uri uri) { }
public System.Threading.Tasks.Task<System.IO.Stream> LoadAsync(System.Uri uri, System.Threading.CancellationToken cancellationToken = default) { }
}
}
namespace Microsoft.OpenApi.Services
Expand Down

0 comments on commit f61cbe1

Please sign in to comment.