Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 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
115 changes: 77 additions & 38 deletions src/Microsoft.OpenApi.Hidi/OpenApiService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
using Microsoft.OpenApi.Services;
using Microsoft.OpenApi.Validations;
using Microsoft.OpenApi.Writers;
using System.Threading;

namespace Microsoft.OpenApi.Hidi
{
Expand All @@ -38,7 +39,8 @@ public static async Task ProcessOpenApiDocument(
bool resolveexternal,
string filterbyoperationids,
string filterbytags,
string filterbycollection
string filterbycollection,
CancellationToken cancellationToken
)
{
var logger = ConfigureLoggerInstance(loglevel);
Expand All @@ -52,7 +54,11 @@ string filterbycollection
}
catch (ArgumentNullException ex)
{
logger.LogError(ex.Message);
#if DEBUG
logger.LogCritical(ex, ex.Message);
#else
logger.LogCritical(ex.Message);
#endif
return;
}
try
Expand All @@ -64,19 +70,27 @@ string filterbycollection
}
catch (ArgumentException ex)
{
logger.LogError(ex.Message);
#if DEBUG
logger.LogCritical(ex, ex.Message);
#else
logger.LogCritical(ex.Message);
#endif
return;
}
try
{
if (output.Exists)
{
throw new IOException("The file you're writing to already exists. Please input a new file path.");
throw new IOException($"The file {output} already exists. Please input a new file path.");
}
}
catch (IOException ex)
{
logger.LogError(ex.Message);
#if DEBUG
logger.LogCritical(ex, ex.Message);
#else
logger.LogCritical(ex.Message);
#endif
return;
}

Expand All @@ -91,12 +105,12 @@ string filterbycollection
openApiFormat = format ?? GetOpenApiFormat(csdl, logger);
version ??= OpenApiSpecVersion.OpenApi3_0;

stream = await GetStream(csdl, logger);
stream = await GetStream(csdl, logger, cancellationToken);
document = await ConvertCsdlToOpenApi(stream);
}
else
{
stream = await GetStream(openapi, logger);
stream = await GetStream(openapi, logger, cancellationToken);

// Parsing OpenAPI file
stopwatch.Start();
Expand All @@ -114,10 +128,13 @@ string filterbycollection
var context = result.OpenApiDiagnostic;
if (context.Errors.Count > 0)
{
logger.LogTrace("{timestamp}ms: Parsed OpenAPI with errors. {count} paths found.", stopwatch.ElapsedMilliseconds, document.Paths.Count);

var errorReport = new StringBuilder();

foreach (var error in context.Errors)
{
logger.LogError("OpenApi Parsing error: {message}", error.ToString());
errorReport.AppendLine(error.ToString());
}
logger.LogError($"{stopwatch.ElapsedMilliseconds}ms: OpenApi Parsing errors {string.Join(Environment.NewLine, context.Errors.Select(e => e.Message).ToArray())}");
Expand Down Expand Up @@ -156,7 +173,7 @@ string filterbycollection
}
if (!string.IsNullOrEmpty(filterbycollection))
{
var fileStream = await GetStream(filterbycollection, logger);
var fileStream = await GetStream(filterbycollection, logger, cancellationToken);
var requestUrls = ParseJsonCollectionFile(fileStream, logger);

logger.LogTrace("Creating predicate based on the paths and Http methods defined in the Postman collection.");
Expand Down Expand Up @@ -245,7 +262,7 @@ public static OpenApiDocument FixReferences(OpenApiDocument document)
return doc;
}

private static async Task<Stream> GetStream(string input, ILogger logger)
private static async Task<Stream> GetStream(string input, ILogger logger, CancellationToken cancellationToken)
{
var stopwatch = new Stopwatch();
stopwatch.Start();
Expand All @@ -263,11 +280,15 @@ private static async Task<Stream> GetStream(string input, ILogger logger)
{
DefaultRequestVersion = HttpVersion.Version20
};
stream = await httpClient.GetStreamAsync(input);
stream = await httpClient.GetStreamAsync(input, cancellationToken);
}
catch (HttpRequestException ex)
{
logger.LogError($"Could not download the file at {input}, reason{ex}");
#if DEBUG
logger.LogCritical(ex, "Could not download the file at {inputPath}, reason: {exMessage}", input, ex.Message);
#else
logger.LogCritical( "Could not download the file at {inputPath}, reason: {exMessage}", input, ex.Message);
#endif
return null;
}
}
Expand All @@ -286,7 +307,11 @@ ex is UnauthorizedAccessException ||
ex is SecurityException ||
ex is NotSupportedException)
{
logger.LogError($"Could not open the file at {input}, reason: {ex.Message}");
#if DEBUG
logger.LogCritical(ex, "Could not open the file at {inputPath}, reason: {exMessage}", input, ex.Message);
#else
logger.LogCritical("Could not open the file at {inputPath}, reason: {exMessage}", input, ex.Message);
#endif
return null;
}
}
Expand Down Expand Up @@ -327,37 +352,51 @@ public static Dictionary<string, List<string>> ParseJsonCollectionFile(Stream st
return requestUrls;
}

internal static async Task ValidateOpenApiDocument(string openapi, LogLevel loglevel)
internal static async Task ValidateOpenApiDocument(string openapi, LogLevel loglevel, CancellationToken cancellationToken)
{
if (string.IsNullOrEmpty(openapi))
{
throw new ArgumentNullException(nameof(openapi));
}
var logger = ConfigureLoggerInstance(loglevel);
var stream = await GetStream(openapi, logger);

OpenApiDocument document;
logger.LogTrace("Parsing the OpenApi file");
document = new OpenApiStreamReader(new OpenApiReaderSettings
try
{
RuleSet = ValidationRuleSet.GetDefaultRuleSet()
}
).Read(stream, out var context);
if (string.IsNullOrEmpty(openapi))
{
throw new ArgumentNullException(nameof(openapi));
}
var stream = await GetStream(openapi, logger, cancellationToken);

if (context.Errors.Count != 0)
{
foreach (var error in context.Errors)
OpenApiDocument document;
logger.LogTrace("Parsing the OpenApi file");
document = new OpenApiStreamReader(new OpenApiReaderSettings
{
Console.WriteLine(error.ToString());
RuleSet = ValidationRuleSet.GetDefaultRuleSet()
}
}
).Read(stream, out var context);

var statsVisitor = new StatsVisitor();
var walker = new OpenApiWalker(statsVisitor);
walker.Walk(document);
if (context.Errors.Count != 0)
{
foreach (var error in context.Errors)
{
logger.LogError("OpenApi Parsing error: {message}", error.ToString());
Console.WriteLine(error.ToString());
}
}

var statsVisitor = new StatsVisitor();
var walker = new OpenApiWalker(statsVisitor);
walker.Walk(document);

logger.LogTrace("Finished walking through the OpenApi document. Generating a statistics report..");
Console.WriteLine(statsVisitor.GetStatisticsReport());
}
catch(Exception ex)
{
#if DEBUG
logger.LogCritical(ex, ex.Message);
#else
logger.LogCritical(ex.Message);
#endif
}

logger.LogTrace("Finished walking through the OpenApi document. Generating a statistics report..");
Console.WriteLine(statsVisitor.GetStatisticsReport());
}

private static OpenApiFormat GetOpenApiFormat(string input, ILogger logger)
Expand All @@ -369,16 +408,16 @@ private static OpenApiFormat GetOpenApiFormat(string input, ILogger logger)
private static ILogger ConfigureLoggerInstance(LogLevel loglevel)
{
// Configure logger options
#if DEBUG
#if DEBUG
loglevel = loglevel > LogLevel.Debug ? LogLevel.Debug : loglevel;
#endif
#endif

var logger = LoggerFactory.Create((builder) => {
builder
.AddConsole()
#if DEBUG
#if DEBUG
.AddDebug()
#endif
#endif
.SetMinimumLevel(loglevel);
}).CreateLogger<OpenApiService>();

Expand Down
5 changes: 3 additions & 2 deletions src/Microsoft.OpenApi.Hidi/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

using System.CommandLine;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;

Expand Down Expand Up @@ -55,7 +56,7 @@ static async Task<int> Main(string[] args)
logLevelOption
};

validateCommand.SetHandler<string, LogLevel>(OpenApiService.ValidateOpenApiDocument, descriptionOption, logLevelOption);
validateCommand.SetHandler<string, LogLevel, CancellationToken>(OpenApiService.ValidateOpenApiDocument, descriptionOption, logLevelOption);

var transformCommand = new Command("transform")
{
Expand All @@ -72,7 +73,7 @@ static async Task<int> Main(string[] args)
resolveExternalOption,
};

transformCommand.SetHandler<string, string, FileInfo, OpenApiSpecVersion?, OpenApiFormat?, LogLevel, bool, bool, string, string, string> (
transformCommand.SetHandler<string, string, FileInfo, OpenApiSpecVersion?, OpenApiFormat?, LogLevel, bool, bool, string, string, string, CancellationToken> (
OpenApiService.ProcessOpenApiDocument, descriptionOption, csdlOption, outputOption, versionOption, formatOption, logLevelOption, inlineOption, resolveExternalOption, filterByOperationIdsOption, filterByTagsOption, filterByCollectionOption);

rootCommand.Add(transformCommand);
Expand Down