Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
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