diff --git a/src/Microsoft.OpenApi.Readers/OpenApiReaderSettings.cs b/src/Microsoft.OpenApi.Readers/OpenApiReaderSettings.cs
index da178ae86..732708459 100644
--- a/src/Microsoft.OpenApi.Readers/OpenApiReaderSettings.cs
+++ b/src/Microsoft.OpenApi.Readers/OpenApiReaderSettings.cs
@@ -1,5 +1,5 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT license.
+// Licensed under the MIT license.
using Microsoft.OpenApi.Any;
using Microsoft.OpenApi.Interfaces;
@@ -61,11 +61,17 @@ public class OpenApiReaderSettings
public Uri BaseUrl { get; set; }
///
- /// Function used to provide an alternative loader for accessing external references.
+ /// Function used to provide an alternative loader for accessing external references.
///
///
/// Default loader will attempt to dereference http(s) urls and file urls.
///
public IStreamLoader CustomExternalLoader { get; set; }
+
+ ///
+ /// Whether to leave the object open after reading
+ /// from an object.
+ ///
+ public bool LeaveStreamOpen { get; set; }
}
}
diff --git a/src/Microsoft.OpenApi.Readers/OpenApiStreamReader.cs b/src/Microsoft.OpenApi.Readers/OpenApiStreamReader.cs
index cab5d1a83..cccf06a68 100644
--- a/src/Microsoft.OpenApi.Readers/OpenApiStreamReader.cs
+++ b/src/Microsoft.OpenApi.Readers/OpenApiStreamReader.cs
@@ -1,5 +1,5 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT license.
+// Licensed under the MIT license.
using System.IO;
using System.Threading.Tasks;
@@ -29,14 +29,18 @@ public OpenApiStreamReader(OpenApiReaderSettings settings = null)
/// Reads the stream input and parses it into an Open API document.
///
/// Stream containing OpenAPI description to parse.
- /// Returns diagnostic object containing errors detected during parsing
- /// Instance of newly created OpenApiDocument
+ /// Returns diagnostic object containing errors detected during parsing.
+ /// Instance of newly created OpenApiDocument.
public OpenApiDocument Read(Stream input, out OpenApiDiagnostic diagnostic)
{
- using (var reader = new StreamReader(input))
+ var reader = new StreamReader(input);
+ var result = new OpenApiTextReaderReader(_settings).Read(reader, out diagnostic);
+ if (!_settings.LeaveStreamOpen)
{
- return new OpenApiTextReaderReader(_settings).Read(reader, out diagnostic);
+ reader.Dispose();
}
+
+ return result;
}
///
@@ -50,8 +54,8 @@ public async Task ReadAsync(Stream input)
if (input is MemoryStream)
{
bufferedStream = (MemoryStream)input;
- }
- else
+ }
+ else
{
// Buffer stream so that OpenApiTextReaderReader can process it synchronously
// YamlDocument doesn't support async reading.
diff --git a/test/Microsoft.OpenApi.Readers.Tests/OpenApiReaderTests/OpenApiStreamReaderTests.cs b/test/Microsoft.OpenApi.Readers.Tests/OpenApiReaderTests/OpenApiStreamReaderTests.cs
new file mode 100644
index 000000000..7567e0b7d
--- /dev/null
+++ b/test/Microsoft.OpenApi.Readers.Tests/OpenApiReaderTests/OpenApiStreamReaderTests.cs
@@ -0,0 +1,35 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT license.
+
+using System.IO;
+using Xunit;
+
+namespace Microsoft.OpenApi.Readers.Tests.OpenApiReaderTests
+{
+ public class OpenApiStreamReaderTests
+ {
+ private const string SampleFolderPath = "V3Tests/Samples/OpenApiDocument/";
+
+ [Fact]
+ public void StreamShouldCloseIfLeaveStreamOpenSettingEqualsFalse()
+ {
+ using (var stream = Resources.GetStream(Path.Combine(SampleFolderPath, "petStore.yaml")))
+ {
+ var reader = new OpenApiStreamReader(new OpenApiReaderSettings { LeaveStreamOpen = false });
+ reader.Read(stream, out _);
+ Assert.False(stream.CanRead);
+ }
+ }
+
+ [Fact]
+ public void StreamShouldNotCloseIfLeaveStreamOpenSettingEqualsTrue()
+ {
+ using (var stream = Resources.GetStream(Path.Combine(SampleFolderPath, "petStore.yaml")))
+ {
+ var reader = new OpenApiStreamReader(new OpenApiReaderSettings { LeaveStreamOpen = true});
+ reader.Read(stream, out _);
+ Assert.True(stream.CanRead);
+ }
+ }
+ }
+}