Skip to content

Commit cf2df41

Browse files
authored
Merge pull request #2165 from microsoft/fix/static-factories
fix/static factories
2 parents 1be8edc + ea6e99b commit cf2df41

File tree

51 files changed

+427
-355
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

51 files changed

+427
-355
lines changed

src/Microsoft.OpenApi.Hidi/OpenApiService.cs

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -40,12 +40,6 @@ namespace Microsoft.OpenApi.Hidi
4040
{
4141
internal static class OpenApiService
4242
{
43-
static OpenApiService()
44-
{
45-
OpenApiReaderRegistry.RegisterReader(OpenApiConstants.Yaml, new OpenApiYamlReader());
46-
OpenApiReaderRegistry.RegisterReader(OpenApiConstants.Yml, new OpenApiYamlReader());
47-
}
48-
4943
/// <summary>
5044
/// Implementation of the transform command
5145
/// </summary>
@@ -392,8 +386,10 @@ private static async Task<ReadResult> ParseOpenApiAsync(string openApiFile, bool
392386
LoadExternalRefs = inlineExternal,
393387
BaseUrl = openApiFile.StartsWith("http", StringComparison.OrdinalIgnoreCase) ?
394388
new(openApiFile) :
395-
new Uri("file://" + new FileInfo(openApiFile).DirectoryName + Path.DirectorySeparatorChar)
389+
new Uri("file://" + new FileInfo(openApiFile).DirectoryName + Path.DirectorySeparatorChar),
390+
HttpClient = httpClient.Value
396391
};
392+
settings.AddYamlReader();
397393

398394
result = await OpenApiDocument.LoadAsync(stream, settings: settings, cancellationToken: cancellationToken).ConfigureAwait(false);
399395

@@ -497,6 +493,11 @@ private static Dictionary<string, List<string>> EnumerateJsonDocument(JsonElemen
497493
return paths;
498494
}
499495

496+
private static readonly Lazy<HttpClient> httpClient = new(() => new HttpClient()
497+
{
498+
DefaultRequestVersion = HttpVersion.Version20
499+
});
500+
500501
/// <summary>
501502
/// Reads stream from file system or makes HTTP request depending on the input string
502503
/// </summary>
@@ -512,11 +513,7 @@ private static async Task<Stream> GetStreamAsync(string input, ILogger logger, C
512513
{
513514
try
514515
{
515-
using var httpClient = new HttpClient
516-
{
517-
DefaultRequestVersion = HttpVersion.Version20
518-
};
519-
stream = await httpClient.GetStreamAsync(new Uri(input), cancellationToken).ConfigureAwait(false);
516+
stream = await httpClient.Value.GetStreamAsync(new Uri(input), cancellationToken).ConfigureAwait(false);
520517
}
521518
catch (HttpRequestException ex)
522519
{
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
using Microsoft.OpenApi.Interfaces;
2+
using Microsoft.OpenApi.Models;
3+
using Microsoft.OpenApi.Readers;
4+
5+
namespace Microsoft.OpenApi.Reader;
6+
7+
/// <summary>
8+
/// Extensions for <see cref="OpenApiReaderSettings"/>
9+
/// </summary>
10+
public static class OpenApiReaderSettingsExtensions
11+
{
12+
/// <summary>
13+
/// Adds a reader for the specified format
14+
/// </summary>
15+
/// <param name="settings">The settings to add the reader to.</param>
16+
public static void AddYamlReader(this OpenApiReaderSettings settings)
17+
{
18+
var yamlReader = new OpenApiYamlReader();
19+
settings.TryAddReader(OpenApiConstants.Yaml, yamlReader);
20+
settings.TryAddReader(OpenApiConstants.Yml, yamlReader);
21+
}
22+
}

src/Microsoft.OpenApi.Workbench/MainModel.cs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -211,9 +211,6 @@ protected void OnPropertyChanged(string propertyName)
211211
/// </summary>
212212
internal async Task ParseDocumentAsync()
213213
{
214-
OpenApiReaderRegistry.RegisterReader(OpenApiConstants.Yaml, new OpenApiYamlReader());
215-
OpenApiReaderRegistry.RegisterReader(OpenApiConstants.Yml, new OpenApiYamlReader());
216-
217214
Stream stream = null;
218215
try
219216
{
@@ -238,6 +235,7 @@ internal async Task ParseDocumentAsync()
238235
{
239236
RuleSet = ValidationRuleSet.GetDefaultRuleSet()
240237
};
238+
settings.AddYamlReader();
241239
if (ResolveExternal && !string.IsNullOrWhiteSpace(_inputFile))
242240
{
243241
settings.BaseUrl = _inputFile.StartsWith("http", StringComparison.OrdinalIgnoreCase) ? new(_inputFile)

src/Microsoft.OpenApi/Models/OpenApiDocument.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -562,10 +562,11 @@ public static ReadResult Load(MemoryStream stream,
562562
/// </summary>
563563
/// <param name="url"> The path to the OpenAPI file.</param>
564564
/// <param name="settings">The OpenApi reader settings.</param>
565+
/// <param name="token">The cancellation token</param>
565566
/// <returns></returns>
566-
public static async Task<ReadResult> LoadAsync(string url, OpenApiReaderSettings? settings = null)
567+
public static async Task<ReadResult> LoadAsync(string url, OpenApiReaderSettings? settings = null, CancellationToken token = default)
567568
{
568-
return await OpenApiModelFactory.LoadAsync(url, settings);
569+
return await OpenApiModelFactory.LoadAsync(url, settings, token).ConfigureAwait(false);
569570
}
570571

571572
/// <summary>

src/Microsoft.OpenApi/Reader/OpenApiModelFactory.cs

Lines changed: 17 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
using System;
55
using System.IO;
66
using System.Linq;
7-
using System.Net.Http;
87
using System.Security;
98
using System.Text;
109
using System.Threading;
@@ -21,13 +20,6 @@ namespace Microsoft.OpenApi.Reader
2120
/// </summary>
2221
public static class OpenApiModelFactory
2322
{
24-
private static readonly HttpClient _httpClient = new();
25-
26-
static OpenApiModelFactory()
27-
{
28-
OpenApiReaderRegistry.RegisterReader(OpenApiConstants.Json, new OpenApiJsonReader());
29-
}
30-
3123
/// <summary>
3224
/// Loads the input stream and parses it into an Open API document.
3325
/// </summary>
@@ -73,19 +65,21 @@ public static ReadResult Load(MemoryStream stream,
7365
public static T Load<T>(MemoryStream input, OpenApiSpecVersion version, string format, OpenApiDocument openApiDocument, out OpenApiDiagnostic diagnostic, OpenApiReaderSettings settings = null) where T : IOpenApiElement
7466
{
7567
format ??= InspectStreamFormat(input);
76-
return OpenApiReaderRegistry.GetReader(format).ReadFragment<T>(input, version, openApiDocument, out diagnostic, settings);
68+
settings ??= DefaultReaderSettings.Value;
69+
return settings.GetReader(format).ReadFragment<T>(input, version, openApiDocument, out diagnostic, settings);
7770
}
7871

7972
/// <summary>
8073
/// Loads the input URL and parses it into an Open API document.
8174
/// </summary>
8275
/// <param name="url">The path to the OpenAPI file</param>
8376
/// <param name="settings"> The OpenApi reader settings.</param>
84-
/// <param name="token"></param>
77+
/// <param name="token">The cancellation token</param>
8578
/// <returns></returns>
8679
public static async Task<ReadResult> LoadAsync(string url, OpenApiReaderSettings settings = null, CancellationToken token = default)
8780
{
88-
var (stream, format) = await RetrieveStreamAndFormatAsync(url, token).ConfigureAwait(false);
81+
settings ??= DefaultReaderSettings.Value;
82+
var (stream, format) = await RetrieveStreamAndFormatAsync(url, settings, token).ConfigureAwait(false);
8983
return await LoadAsync(stream, format, settings, token).ConfigureAwait(false);
9084
}
9185

@@ -102,7 +96,8 @@ public static async Task<ReadResult> LoadAsync(string url, OpenApiReaderSettings
10296
/// <returns>The OpenAPI element.</returns>
10397
public static async Task<T> LoadAsync<T>(string url, OpenApiSpecVersion version, OpenApiDocument openApiDocument, OpenApiReaderSettings settings = null, CancellationToken token = default) where T : IOpenApiElement
10498
{
105-
var (stream, format) = await RetrieveStreamAndFormatAsync(url, token).ConfigureAwait(false);
99+
settings ??= DefaultReaderSettings.Value;
100+
var (stream, format) = await RetrieveStreamAndFormatAsync(url, settings, token).ConfigureAwait(false);
106101
return await LoadAsync<T>(stream, version, openApiDocument, format, settings, token);
107102
}
108103

@@ -239,14 +234,15 @@ public static T Parse<T>(string input,
239234
return Load<T>(stream, version, format, openApiDocument, out diagnostic, settings);
240235
}
241236

242-
private static readonly OpenApiReaderSettings DefaultReaderSettings = new();
237+
private static readonly Lazy<OpenApiReaderSettings> DefaultReaderSettings = new(() => new OpenApiReaderSettings());
243238

244239
private static async Task<ReadResult> InternalLoadAsync(Stream input, string format, OpenApiReaderSettings settings, CancellationToken cancellationToken = default)
245240
{
246-
var reader = OpenApiReaderRegistry.GetReader(format);
241+
settings ??= DefaultReaderSettings.Value;
242+
var reader = settings.GetReader(format);
247243
var readResult = await reader.ReadAsync(input, settings, cancellationToken).ConfigureAwait(false);
248244

249-
if (settings?.LoadExternalRefs ?? DefaultReaderSettings.LoadExternalRefs)
245+
if (settings.LoadExternalRefs)
250246
{
251247
var diagnosticExternalRefs = await LoadExternalRefsAsync(readResult.Document, settings, format, cancellationToken).ConfigureAwait(false);
252248
// Merge diagnostics of external reference
@@ -267,14 +263,15 @@ private static async Task<OpenApiDiagnostic> LoadExternalRefsAsync(OpenApiDocume
267263
var openApiWorkSpace = new OpenApiWorkspace(baseUrl);
268264

269265
// Load this root document into the workspace
270-
var streamLoader = new DefaultStreamLoader(settings.BaseUrl);
266+
var streamLoader = new DefaultStreamLoader(settings.BaseUrl, settings.HttpClient);
271267
var workspaceLoader = new OpenApiWorkspaceLoader(openApiWorkSpace, settings.CustomExternalLoader ?? streamLoader, settings);
272268
return await workspaceLoader.LoadAsync(new OpenApiReference() { ExternalResource = "/" }, document, format ?? OpenApiConstants.Json, null, token).ConfigureAwait(false);
273269
}
274270

275271
private static ReadResult InternalLoad(MemoryStream input, string format, OpenApiReaderSettings settings)
276272
{
277-
if (settings?.LoadExternalRefs ?? DefaultReaderSettings.LoadExternalRefs)
273+
settings ??= DefaultReaderSettings.Value;
274+
if (settings.LoadExternalRefs)
278275
{
279276
throw new InvalidOperationException("Loading external references are not supported when using synchronous methods.");
280277
}
@@ -283,12 +280,12 @@ private static ReadResult InternalLoad(MemoryStream input, string format, OpenAp
283280
throw new ArgumentException($"Cannot parse the stream: {nameof(input)} is empty or contains no elements.");
284281
}
285282

286-
var reader = OpenApiReaderRegistry.GetReader(format);
283+
var reader = settings.GetReader(format);
287284
var readResult = reader.Read(input, settings);
288285
return readResult;
289286
}
290287

291-
private static async Task<(Stream, string)> RetrieveStreamAndFormatAsync(string url, CancellationToken token = default)
288+
private static async Task<(Stream, string)> RetrieveStreamAndFormatAsync(string url, OpenApiReaderSettings settings, CancellationToken token = default)
292289
{
293290
if (!string.IsNullOrEmpty(url))
294291
{
@@ -298,7 +295,7 @@ private static ReadResult InternalLoad(MemoryStream input, string format, OpenAp
298295
if (url.StartsWith("http", StringComparison.OrdinalIgnoreCase)
299296
|| url.StartsWith("https", StringComparison.OrdinalIgnoreCase))
300297
{
301-
var response = await _httpClient.GetAsync(url, token).ConfigureAwait(false);
298+
var response = await settings.HttpClient.GetAsync(url, token).ConfigureAwait(false);
302299
var mediaType = response.Content.Headers.ContentType.MediaType;
303300
var contentType = mediaType.Split(";".ToCharArray(), StringSplitOptions.RemoveEmptyEntries)[0];
304301
format = contentType.Split('/').Last().Split('+').Last().Split('-').Last();

src/Microsoft.OpenApi/Reader/OpenApiReaderRegistry.cs

Lines changed: 0 additions & 48 deletions
This file was deleted.

0 commit comments

Comments
 (0)