diff --git a/Modules/OpenApi/Discovery/Extensions.cs b/Modules/OpenApi/Discovery/Extensions.cs deleted file mode 100644 index 8012511c..00000000 --- a/Modules/OpenApi/Discovery/Extensions.cs +++ /dev/null @@ -1,16 +0,0 @@ -namespace GenHTTP.Modules.OpenApi.Discovery; - -internal static class Extensions -{ - - internal static bool MightBeNull(this Type type) - { - if (type.IsClass) - { - return true; - } - - return Nullable.GetUnderlyingType(type) != null; - } - -} diff --git a/Modules/OpenApi/Discovery/MethodHandlerExplorer.cs b/Modules/OpenApi/Discovery/MethodHandlerExplorer.cs index f232e331..3952acfa 100644 --- a/Modules/OpenApi/Discovery/MethodHandlerExplorer.cs +++ b/Modules/OpenApi/Discovery/MethodHandlerExplorer.cs @@ -30,7 +30,7 @@ public void Explore(IHandler handler, List path, OpenApiDocument documen } } - var pathItem = GetPathItem(document, path, methodHandler.Operation); + var pathItem = OpenApiExtensions.GetPathItem(document, path, methodHandler.Operation); foreach (var method in methodHandler.Configuration.SupportedMethods) { @@ -112,44 +112,6 @@ public void Explore(IHandler handler, List path, OpenApiDocument documen } } - private static OpenApiPathItem GetPathItem(OpenApiDocument document, List path, Operation operation) - { - var stringPath = BuildPath(operation.Path.Name, path); - - if (document.Paths.TryGetValue(stringPath, out var existing)) - { - return existing; - } - - var newPath = new OpenApiPathItem(); - - document.Paths.Add(stringPath, newPath); - - return newPath; - } - - private static string BuildPath(string name, List pathParts) - { - var builder = new StringBuilder("/"); - - if (pathParts.Count > 0) - { - builder.Append(string.Join('/', pathParts)); - builder.Append('/'); - } - - if (name.Length > 0 && name[0] == '/') - { - builder.Append(name[1..]); - } - else - { - builder.Append(name); - } - - return builder.ToString(); - } - private static OpenApiParameterKind MapArgumentType(OperationArgumentSource source) => source switch { OperationArgumentSource.Path => OpenApiParameterKind.Path, diff --git a/Modules/OpenApi/Discovery/OpenApiExtensions.cs b/Modules/OpenApi/Discovery/OpenApiExtensions.cs new file mode 100644 index 00000000..2a4c7be7 --- /dev/null +++ b/Modules/OpenApi/Discovery/OpenApiExtensions.cs @@ -0,0 +1,58 @@ +using System.Text; +using GenHTTP.Modules.Reflection.Operations; +using NSwag; + +namespace GenHTTP.Modules.OpenApi.Discovery; + +public static class OpenApiExtensions +{ + + public static bool MightBeNull(this Type type) + { + if (type.IsClass) + { + return true; + } + + return Nullable.GetUnderlyingType(type) != null; + } + + public static OpenApiPathItem GetPathItem(OpenApiDocument document, List path, Operation operation) + { + var stringPath = BuildPath(operation.Path.Name, path); + + if (document.Paths.TryGetValue(stringPath, out var existing)) + { + return existing; + } + + var newPath = new OpenApiPathItem(); + + document.Paths.Add(stringPath, newPath); + + return newPath; + } + + public static string BuildPath(string name, List pathParts) + { + var builder = new StringBuilder("/"); + + if (pathParts.Count > 0) + { + builder.Append(string.Join('/', pathParts)); + builder.Append('/'); + } + + if (name.Length > 0 && name[0] == '/') + { + builder.Append(name[1..]); + } + else + { + builder.Append(name); + } + + return builder.ToString(); + } + +} diff --git a/Modules/OpenApi/Handler/OpenApiConcern.cs b/Modules/OpenApi/Handler/OpenApiConcern.cs index 345c0788..079f59cb 100644 --- a/Modules/OpenApi/Handler/OpenApiConcern.cs +++ b/Modules/OpenApi/Handler/OpenApiConcern.cs @@ -6,9 +6,11 @@ namespace GenHTTP.Modules.OpenApi.Handler; +internal record ReturnDocument(OpenApiDocument Document, ulong Checksum); + public sealed class OpenApiConcern : IConcern { - private OpenApiDocument? _Cached; + private ReturnDocument? _Cached; #region Initialization @@ -97,7 +99,7 @@ private IResponse GetDocument(IRequest request, OpenApiFormat format) .Build(); } - private OpenApiDocument Discover(IRequest request, ApiDiscoveryRegistry registry) + private ReturnDocument Discover(IRequest request, ApiDiscoveryRegistry registry) { if (EnableCaching && _Cached != null) { @@ -126,12 +128,15 @@ private OpenApiDocument Discover(IRequest request, ApiDiscoveryRegistry registry if (EnableCaching) { - _Cached = document; + _Cached = new (document, GetChecksum(document)); + return _Cached; } - return document; + return new (document, GetChecksum(document)); } + private static ulong GetChecksum(OpenApiDocument document) => (ulong)document.ToJson().GetHashCode(); + #endregion } diff --git a/Modules/OpenApi/Handler/OpenApiContent.cs b/Modules/OpenApi/Handler/OpenApiContent.cs index daab147d..af2d45f7 100644 --- a/Modules/OpenApi/Handler/OpenApiContent.cs +++ b/Modules/OpenApi/Handler/OpenApiContent.cs @@ -9,7 +9,7 @@ internal class OpenApiContent : IResponseContent #region Initialization - internal OpenApiContent(OpenApiDocument document, OpenApiFormat format) + internal OpenApiContent(ReturnDocument document, OpenApiFormat format) { Document = document; Format = format; @@ -21,7 +21,7 @@ internal OpenApiContent(OpenApiDocument document, OpenApiFormat format) public ulong? Length => null; - private OpenApiDocument Document { get; } + private ReturnDocument Document { get; } private OpenApiFormat Format { get; } @@ -29,17 +29,17 @@ internal OpenApiContent(OpenApiDocument document, OpenApiFormat format) #region Functionality - public ValueTask CalculateChecksumAsync() => new((ulong)Document.ToJson().GetHashCode()); + public ValueTask CalculateChecksumAsync() => new(Document.Checksum); public async ValueTask WriteAsync(Stream target, uint bufferSize) { if (Format == OpenApiFormat.Json) { - await target.WriteAsync(Encoding.UTF8.GetBytes(Document.ToJson())); + await target.WriteAsync(Encoding.UTF8.GetBytes(Document.Document.ToJson())); } else { - await target.WriteAsync(Encoding.UTF8.GetBytes(Document.ToYaml())); + await target.WriteAsync(Encoding.UTF8.GetBytes(Document.Document.ToYaml())); } } diff --git a/Testing/Acceptance/Modules/OpenApi/InfrastructureTests.cs b/Testing/Acceptance/Modules/OpenApi/InfrastructureTests.cs index 1020d958..bf406bee 100644 --- a/Testing/Acceptance/Modules/OpenApi/InfrastructureTests.cs +++ b/Testing/Acceptance/Modules/OpenApi/InfrastructureTests.cs @@ -14,7 +14,7 @@ public async Task TestContentIsPassed() { var api = Inline.Create() .Get("/some-path", () => "Hello World") - .Add(ApiDescription.Create()); + .AddOpenApi(); using var host = TestHost.Run(api); @@ -43,9 +43,10 @@ private async Task RunCachingTest(bool cacheEnabled) using var host = TestHost.Run(api); - await host.GetResponseAsync("/openapi.json"); - await host.GetResponseAsync("/openapi.json"); + AssertX.Contains("\"openapi\"", await (await host.GetResponseAsync("/openapi.json")).GetContentAsync()); + AssertX.Contains("openapi:", await (await host.GetResponseAsync("/openapi.yaml")).GetContentAsync()); return counter; } + } diff --git a/Testing/Acceptance/TestExtensions.cs b/Testing/Acceptance/TestOpenApiExtensions.cs similarity index 91% rename from Testing/Acceptance/TestExtensions.cs rename to Testing/Acceptance/TestOpenApiExtensions.cs index 1c664932..51f423d6 100644 --- a/Testing/Acceptance/TestExtensions.cs +++ b/Testing/Acceptance/TestOpenApiExtensions.cs @@ -3,7 +3,7 @@ namespace GenHTTP.Testing.Acceptance; -public static class TestExtensions +public static class TestOpenApiExtensions { public static IHandlerBuilder Wrap(this IHandler handler) => new HandlerBuilder(handler);