From 3e9e828874e2885d0f094c7b6b042885baec6cbc Mon Sep 17 00:00:00 2001 From: Javier Garrido Date: Sun, 23 Apr 2017 22:53:15 +0200 Subject: [PATCH 1/4] Add built-in cache support --- .../App_Start/SwaggerConfig.cs | 3 +++ Swashbuckle.OData/ODataSwaggerDocsConfig.cs | 9 +++++++- Swashbuckle.OData/ODataSwaggerProvider.cs | 22 +++++++++++++++++++ 3 files changed, 33 insertions(+), 1 deletion(-) diff --git a/Swashbuckle.OData.Sample/App_Start/SwaggerConfig.cs b/Swashbuckle.OData.Sample/App_Start/SwaggerConfig.cs index 6531b04..34b5298 100644 --- a/Swashbuckle.OData.Sample/App_Start/SwaggerConfig.cs +++ b/Swashbuckle.OData.Sample/App_Start/SwaggerConfig.cs @@ -177,6 +177,9 @@ public static void Register() // Set this flag to include navigation properties in your entity swagger models // odataConfig.IncludeNavigationProperties(); + + // Enable Caché for swagger doc requests + odataConfig.EnableSwaggerRequestCaching(); })); }) .EnableSwaggerUi(c => diff --git a/Swashbuckle.OData/ODataSwaggerDocsConfig.cs b/Swashbuckle.OData/ODataSwaggerDocsConfig.cs index ad64d57..99eb08f 100644 --- a/Swashbuckle.OData/ODataSwaggerDocsConfig.cs +++ b/Swashbuckle.OData/ODataSwaggerDocsConfig.cs @@ -16,6 +16,7 @@ public class ODataSwaggerDocsConfig private readonly SwaggerDocsConfig _swaggerDocsConfig; private readonly List> _documentFilters; private bool _includeNavigationProperties; + internal bool enableCache; internal ODataSwaggerDocsConfig(SwaggerDocsConfig swaggerDocsConfig, HttpConfiguration httpConfiguration) { @@ -24,8 +25,9 @@ internal ODataSwaggerDocsConfig(SwaggerDocsConfig swaggerDocsConfig, HttpConfigu Configuration = httpConfiguration; _swaggerDocsConfig = swaggerDocsConfig; - _includeNavigationProperties = false; + _includeNavigationProperties = false; _documentFilters = new List>(); + enableCache = false; } internal void DocumentFilter() where TFilter : IDocumentFilter, new() @@ -172,5 +174,10 @@ public void IncludeNavigationProperties() { _includeNavigationProperties = true; } + + public void EnableSwaggerRequestCaching() + { + enableCache = true; + } } } \ No newline at end of file diff --git a/Swashbuckle.OData/ODataSwaggerProvider.cs b/Swashbuckle.OData/ODataSwaggerProvider.cs index a7dccae..0d937d3 100644 --- a/Swashbuckle.OData/ODataSwaggerProvider.cs +++ b/Swashbuckle.OData/ODataSwaggerProvider.cs @@ -9,6 +9,7 @@ using Swashbuckle.Application; using Swashbuckle.OData.Descriptions; using Swashbuckle.Swagger; +using System.Collections.Concurrent; namespace Swashbuckle.OData { @@ -17,6 +18,9 @@ public class ODataSwaggerProvider : ISwaggerProvider private readonly ISwaggerProvider _defaultProvider; private readonly ODataSwaggerDocsConfig _config; + private static ConcurrentDictionary> _cache = + new ConcurrentDictionary>(); + /// /// Initializes a new instance of the class. /// Use this constructor for self-hosted scenarios. @@ -35,6 +39,24 @@ public ODataSwaggerProvider(ISwaggerProvider defaultProvider, SwaggerDocsConfig } public SwaggerDocument GetSwagger(string rootUrl, string apiVersion) + { + if(_config.enableCache) + { + var cacheKey = string.Format("{0}_{1}", rootUrl, apiVersion); + var SwaggerDoc = _cache.GetOrAdd(cacheKey, (key) => + //making GetOrAdd operation thread-safe + new Lazy(() => { + //Getting swagger + return GenerateSwagger(rootUrl, apiVersion); + }) + ); + return SwaggerDoc.Value; + } + else + return GenerateSwagger(rootUrl, apiVersion); + } + + private SwaggerDocument GenerateSwagger(string rootUrl, string apiVersion) { var swashbuckleOptions = _config.GetSwashbuckleOptions(); From b0086d7fca9fa42fee5484eea321078ea0ab9cb3 Mon Sep 17 00:00:00 2001 From: Javier Garrido Date: Mon, 24 Apr 2017 23:36:39 +0200 Subject: [PATCH 2/4] In-built swagger document cache test --- .../Fixtures/ODataSwaggerProviderTests.cs | 31 +++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/Swashbuckle.OData.Tests/Fixtures/ODataSwaggerProviderTests.cs b/Swashbuckle.OData.Tests/Fixtures/ODataSwaggerProviderTests.cs index cee71c3..fbc4f5a 100644 --- a/Swashbuckle.OData.Tests/Fixtures/ODataSwaggerProviderTests.cs +++ b/Swashbuckle.OData.Tests/Fixtures/ODataSwaggerProviderTests.cs @@ -145,9 +145,36 @@ public async Task It_supports_both_webapi_and_odata_controllers() } } - private static void Configuration(IAppBuilder appBuilder, Type targetController = null, Action swaggerDocsConfig = null) + /// + /// Test to check if the cached swagger documents have the same value as the non-cached and to check if they are valid + /// + /// + [Test] + public async Task It_supports_caching_swagger_document() + { + Action config = c => c.EnableSwaggerRequestCaching(); + using (WebApp.Start(HttpClientUtils.BaseAddress, appBuilder => Configuration(appBuilder, typeof(CustomersController), + odataSwaggerDocsConfig: config))) + { + // Arrange + var httpClient = HttpClientUtils.GetHttpClient(HttpClientUtils.BaseAddress); + + // First request (Non-cached) + var swaggerDocument = await httpClient.GetJsonAsync("swagger/docs/v1"); + + //Cached request + var swaggerDocument2 = await httpClient.GetJsonAsync("swagger/docs/v1"); + + swaggerDocument.ShouldBeEquivalentTo(swaggerDocument2); + + await ValidationUtils.ValidateSwaggerJson(); + } + } + + + private static void Configuration(IAppBuilder appBuilder, Type targetController = null, Action swaggerDocsConfig = null, Action odataSwaggerDocsConfig = null) { - var config = appBuilder.GetStandardHttpConfig(swaggerDocsConfig, null, targetController); + var config = appBuilder.GetStandardHttpConfig(swaggerDocsConfig, odataSwaggerDocsConfig, targetController); var controllerSelector = new UnitTestODataVersionControllerSelector(config, targetController); config.Services.Replace(typeof(IHttpControllerSelector), controllerSelector); From c726284a231dde5a460d2fc8afe95ae6da509070 Mon Sep 17 00:00:00 2001 From: Javier Garrido Date: Wed, 26 Apr 2017 10:21:33 +0200 Subject: [PATCH 3/4] Update README.md --- README.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/README.md b/README.md index 427a35b..e7a8456 100644 --- a/README.md +++ b/README.md @@ -33,6 +33,18 @@ c.CustomProvider(defaultProvider => new ODataSwaggerProvider(defaultProvider, c, })); ``` +### Enable caching of the swagger requests ### + +To enable the built-in caché funcionality you must set this configuration: + +```csharp +c.CustomProvider(defaultProvider => new ODataSwaggerProvider(defaultProvider, c, GlobalConfiguration.Configuration).Configure(odataConfig => + { + // Enable Caché for swagger doc requests + odataConfig.EnableSwaggerRequestCaching(); + })); +``` + ### Custom Swagger Routes ### The following snippet demonstrates how to configure a custom swagger route such that it will appear in the Swagger UI: From 9b883691acc467e1bb2d6850c860ea5c7a98c6a4 Mon Sep 17 00:00:00 2001 From: Richard Beauchamp Date: Thu, 27 Apr 2017 17:31:59 -0700 Subject: [PATCH 4/4] Fixed spelling --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index e7a8456..8ddcd0b 100644 --- a/README.md +++ b/README.md @@ -33,14 +33,14 @@ c.CustomProvider(defaultProvider => new ODataSwaggerProvider(defaultProvider, c, })); ``` -### Enable caching of the swagger requests ### +### Enable caching of swagger requests ### -To enable the built-in caché funcionality you must set this configuration: +To enable the built-in cache functionality you must set this configuration: ```csharp c.CustomProvider(defaultProvider => new ODataSwaggerProvider(defaultProvider, c, GlobalConfiguration.Configuration).Configure(odataConfig => { - // Enable Caché for swagger doc requests + // Enable Cache for swagger doc requests odataConfig.EnableSwaggerRequestCaching(); })); ```