10
10
using System . Net . Http ;
11
11
using System . Security ;
12
12
using System . Text ;
13
- using System . Text . Json ;
14
13
using System . Threading . Tasks ;
14
+ using System . Text . Json ;
15
15
using Microsoft . Extensions . Logging ;
16
16
using System . Xml . Linq ;
17
17
using Microsoft . OData . Edm . Csdl ;
@@ -45,8 +45,8 @@ public static async Task<int> TransformOpenApiDocument(
45
45
string ? version ,
46
46
OpenApiFormat ? format ,
47
47
LogLevel loglevel ,
48
- bool inline ,
49
- bool resolveexternal ,
48
+ bool inlineLocal ,
49
+ bool inlineExternal ,
50
50
string filterbyoperationids ,
51
51
string filterbytags ,
52
52
string filterbycollection ,
@@ -111,8 +111,9 @@ CancellationToken cancellationToken
111
111
stopwatch . Restart ( ) ;
112
112
var result = await new OpenApiStreamReader ( new OpenApiReaderSettings
113
113
{
114
- ReferenceResolution = resolveexternal ? ReferenceResolutionSetting . ResolveAllReferences : ReferenceResolutionSetting . ResolveLocalReferences ,
115
- RuleSet = ValidationRuleSet . GetDefaultRuleSet ( )
114
+ RuleSet = ValidationRuleSet . GetDefaultRuleSet ( ) ,
115
+ LoadExternalRefs = inlineExternal ,
116
+ BaseUrl = openapi . StartsWith ( "http" ) ? new Uri ( openapi ) : new Uri ( "file:" + new FileInfo ( openapi ) . DirectoryName + "\\ " )
116
117
}
117
118
) . ReadAsync ( stream ) ;
118
119
@@ -189,7 +190,8 @@ CancellationToken cancellationToken
189
190
190
191
var settings = new OpenApiWriterSettings ( )
191
192
{
192
- ReferenceInline = inline ? ReferenceInlineSetting . InlineLocalReferences : ReferenceInlineSetting . DoNotInlineReferences
193
+ InlineLocalReferences = inlineLocal ,
194
+ InlineExternalReferences = inlineExternal
193
195
} ;
194
196
195
197
IOpenApiWriter writer = openApiFormat switch
@@ -276,7 +278,7 @@ public static async Task<int> ValidateOpenApiDocument(
276
278
RuleSet = ValidationRuleSet . GetDefaultRuleSet ( )
277
279
}
278
280
) . ReadAsync ( stream ) ;
279
-
281
+
280
282
logger . LogTrace ( "{timestamp}ms: Completed parsing." , stopwatch . ElapsedMilliseconds ) ;
281
283
282
284
document = result . OpenApiDocument ;
@@ -353,6 +355,73 @@ public static async Task<OpenApiDocument> ConvertCsdlToOpenApi(Stream csdl)
353
355
return document ;
354
356
}
355
357
358
+ /// <summary>
359
+ /// Fixes the references in the resulting OpenApiDocument.
360
+ /// </summary>
361
+ /// <param name="document"> The converted OpenApiDocument.</param>
362
+ /// <returns> A valid OpenApiDocument instance.</returns>
363
+ public static OpenApiDocument FixReferences ( OpenApiDocument document )
364
+ {
365
+ // This method is only needed because the output of ConvertToOpenApi isn't quite a valid OpenApiDocument instance.
366
+ // So we write it out, and read it back in again to fix it up.
367
+
368
+ var sb = new StringBuilder ( ) ;
369
+ document . SerializeAsV3 ( new OpenApiYamlWriter ( new StringWriter ( sb ) ) ) ;
370
+ var doc = new OpenApiStringReader ( ) . Read ( sb . ToString ( ) , out _ ) ;
371
+
372
+ return doc ;
373
+ }
374
+
375
+ private static async Task < Stream > GetStream ( string input , ILogger logger )
376
+ {
377
+ var stopwatch = new Stopwatch ( ) ;
378
+ stopwatch . Start ( ) ;
379
+
380
+ Stream stream ;
381
+ if ( input . StartsWith ( "http" ) )
382
+ {
383
+ try
384
+ {
385
+ var httpClientHandler = new HttpClientHandler ( )
386
+ {
387
+ SslProtocols = System . Security . Authentication . SslProtocols . Tls12 ,
388
+ } ;
389
+ using var httpClient = new HttpClient ( httpClientHandler )
390
+ {
391
+ DefaultRequestVersion = HttpVersion . Version20
392
+ } ;
393
+ stream = await httpClient . GetStreamAsync ( input ) ;
394
+ }
395
+ catch ( HttpRequestException ex )
396
+ {
397
+ logger . LogError ( $ "Could not download the file at { input } , reason{ ex } ") ;
398
+ return null ;
399
+ }
400
+ }
401
+ else
402
+ {
403
+ try
404
+ {
405
+ var fileInput = new FileInfo ( input ) ;
406
+ stream = fileInput . OpenRead ( ) ;
407
+ }
408
+ catch ( Exception ex ) when ( ex is FileNotFoundException ||
409
+ ex is PathTooLongException ||
410
+ ex is DirectoryNotFoundException ||
411
+ ex is IOException ||
412
+ ex is UnauthorizedAccessException ||
413
+ ex is SecurityException ||
414
+ ex is NotSupportedException )
415
+ {
416
+ logger . LogError ( $ "Could not open the file at { input } , reason: { ex . Message } ") ;
417
+ return null ;
418
+ }
419
+ }
420
+ stopwatch . Stop ( ) ;
421
+ logger . LogTrace ( "{timestamp}ms: Read file {input}" , stopwatch . ElapsedMilliseconds , input ) ;
422
+ return stream ;
423
+ }
424
+
356
425
/// <summary>
357
426
/// Takes in a file stream, parses the stream into a JsonDocument and gets a list of paths and Http methods
358
427
/// </summary>
@@ -365,42 +434,76 @@ public static Dictionary<string, List<string>> ParseJsonCollectionFile(Stream st
365
434
logger . LogTrace ( "Parsing the json collection file into a JsonDocument" ) ;
366
435
using var document = JsonDocument . Parse ( stream ) ;
367
436
var root = document . RootElement ;
368
- var itemElement = root . GetProperty ( "item" ) ;
369
- foreach ( var requestObject in itemElement . EnumerateArray ( ) . Select ( item => item . GetProperty ( "request" ) ) )
370
- {
371
- // Fetch list of methods and urls from collection, store them in a dictionary
372
- var path = requestObject . GetProperty ( "url" ) . GetProperty ( "raw" ) . ToString ( ) ;
373
- var method = requestObject . GetProperty ( "method" ) . ToString ( ) ;
374
437
375
- if ( ! requestUrls . ContainsKey ( path ) )
438
+ requestUrls = EnumerateJsonDocument ( root , requestUrls ) ;
439
+ logger . LogTrace ( "Finished fetching the list of paths and Http methods defined in the Postman collection." ) ;
440
+
441
+ return requestUrls ;
442
+ }
443
+
444
+ private static Dictionary < string , List < string > > EnumerateJsonDocument ( JsonElement itemElement , Dictionary < string , List < string > > paths )
445
+ {
446
+ var itemsArray = itemElement . GetProperty ( "item" ) ;
447
+
448
+ foreach ( var item in itemsArray . EnumerateArray ( ) )
449
+ {
450
+ if ( item . ValueKind == JsonValueKind . Object )
376
451
{
377
- requestUrls . Add ( path , new List < string > { method } ) ;
452
+ if ( item . TryGetProperty ( "request" , out var request ) )
453
+ {
454
+ // Fetch list of methods and urls from collection, store them in a dictionary
455
+ var path = request . GetProperty ( "url" ) . GetProperty ( "raw" ) . ToString ( ) ;
456
+ var method = request . GetProperty ( "method" ) . ToString ( ) ;
457
+ if ( ! paths . ContainsKey ( path ) )
458
+ {
459
+ paths . Add ( path , new List < string > { method } ) ;
460
+ }
461
+ else
462
+ {
463
+ paths [ path ] . Add ( method ) ;
464
+ }
465
+ }
466
+ else
467
+ {
468
+ EnumerateJsonDocument ( item , paths ) ;
469
+ }
378
470
}
379
471
else
380
472
{
381
- requestUrls [ path ] . Add ( method ) ;
473
+ EnumerateJsonDocument ( item , paths ) ;
382
474
}
383
475
}
384
- logger . LogTrace ( "Finished fetching the list of paths and Http methods defined in the Postman collection." ) ;
385
- return requestUrls ;
476
+
477
+ return paths ;
386
478
}
387
479
388
480
/// <summary>
389
481
/// Fixes the references in the resulting OpenApiDocument.
390
482
/// </summary>
391
483
/// <param name="document"> The converted OpenApiDocument.</param>
392
484
/// <returns> A valid OpenApiDocument instance.</returns>
393
- private static OpenApiDocument FixReferences ( OpenApiDocument document )
394
- {
395
- // This method is only needed because the output of ConvertToOpenApi isn't quite a valid OpenApiDocument instance.
396
- // So we write it out, and read it back in again to fix it up.
397
-
398
- var sb = new StringBuilder ( ) ;
399
- document . SerializeAsV3 ( new OpenApiYamlWriter ( new StringWriter ( sb ) ) ) ;
400
- var doc = new OpenApiStringReader ( ) . Read ( sb . ToString ( ) , out _ ) ;
401
-
402
- return doc ;
403
- }
485
+ // private static OpenApiDocument FixReferences2(OpenApiDocument document)
486
+ // {
487
+ // // This method is only needed because the output of ConvertToOpenApi isn't quite a valid OpenApiDocument instance.
488
+ // // So we write it out, and read it back in again to fix it up.
489
+
490
+ // OpenApiDocument document;
491
+ // logger.LogTrace("Parsing the OpenApi file");
492
+ // var result = await new OpenApiStreamReader(new OpenApiReaderSettings
493
+ // {
494
+ // RuleSet = ValidationRuleSet.GetDefaultRuleSet(),
495
+ // BaseUrl = new Uri(openapi)
496
+ // }
497
+ // ).ReadAsync(stream);
498
+
499
+ // document = result.OpenApiDocument;
500
+ // var context = result.OpenApiDiagnostic;
501
+ // var sb = new StringBuilder();
502
+ // document.SerializeAsV3(new OpenApiYamlWriter(new StringWriter(sb)));
503
+ // var doc = new OpenApiStringReader().Read(sb.ToString(), out _);
504
+
505
+ // return doc;
506
+ // }
404
507
405
508
/// <summary>
406
509
/// Reads stream from file system or makes HTTP request depending on the input string
0 commit comments