Skip to content

Commit

Permalink
Merge pull request #139 from cibergarri/master
Browse files Browse the repository at this point in the history
Add built-in cache support. @cibergarri thank you!
  • Loading branch information
rbeauchamp committed Apr 28, 2017
2 parents 672d169 + 9b88369 commit e466c9b
Show file tree
Hide file tree
Showing 5 changed files with 74 additions and 3 deletions.
12 changes: 12 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,18 @@ c.CustomProvider(defaultProvider => new ODataSwaggerProvider(defaultProvider, c,
}));
```

### Enable caching of swagger requests ###

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 Cache 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:
Expand Down
3 changes: 3 additions & 0 deletions Swashbuckle.OData.Sample/App_Start/SwaggerConfig.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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 =>
Expand Down
31 changes: 29 additions & 2 deletions Swashbuckle.OData.Tests/Fixtures/ODataSwaggerProviderTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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> swaggerDocsConfig = null)
/// <summary>
/// Test to check if the cached swagger documents have the same value as the non-cached and to check if they are valid
/// </summary>
/// <returns></returns>
[Test]
public async Task It_supports_caching_swagger_document()
{
Action<ODataSwaggerDocsConfig> 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<SwaggerDocument>("swagger/docs/v1");

//Cached request
var swaggerDocument2 = await httpClient.GetJsonAsync<SwaggerDocument>("swagger/docs/v1");

swaggerDocument.ShouldBeEquivalentTo(swaggerDocument2);

await ValidationUtils.ValidateSwaggerJson();
}
}


private static void Configuration(IAppBuilder appBuilder, Type targetController = null, Action<SwaggerDocsConfig> swaggerDocsConfig = null, Action<ODataSwaggerDocsConfig> 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);
Expand Down
9 changes: 8 additions & 1 deletion Swashbuckle.OData/ODataSwaggerDocsConfig.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ public class ODataSwaggerDocsConfig
private readonly SwaggerDocsConfig _swaggerDocsConfig;
private readonly List<Func<IDocumentFilter>> _documentFilters;
private bool _includeNavigationProperties;
internal bool enableCache;

internal ODataSwaggerDocsConfig(SwaggerDocsConfig swaggerDocsConfig, HttpConfiguration httpConfiguration)
{
Expand All @@ -24,8 +25,9 @@ internal ODataSwaggerDocsConfig(SwaggerDocsConfig swaggerDocsConfig, HttpConfigu

Configuration = httpConfiguration;
_swaggerDocsConfig = swaggerDocsConfig;
_includeNavigationProperties = false;
_includeNavigationProperties = false;
_documentFilters = new List<Func<IDocumentFilter>>();
enableCache = false;
}

internal void DocumentFilter<TFilter>() where TFilter : IDocumentFilter, new()
Expand Down Expand Up @@ -172,5 +174,10 @@ public void IncludeNavigationProperties()
{
_includeNavigationProperties = true;
}

public void EnableSwaggerRequestCaching()
{
enableCache = true;
}
}
}
22 changes: 22 additions & 0 deletions Swashbuckle.OData/ODataSwaggerProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
using Swashbuckle.Application;
using Swashbuckle.OData.Descriptions;
using Swashbuckle.Swagger;
using System.Collections.Concurrent;

namespace Swashbuckle.OData
{
Expand All @@ -17,6 +18,9 @@ public class ODataSwaggerProvider : ISwaggerProvider
private readonly ISwaggerProvider _defaultProvider;
private readonly ODataSwaggerDocsConfig _config;

private static ConcurrentDictionary<string, Lazy<SwaggerDocument>> _cache =
new ConcurrentDictionary<string, Lazy<SwaggerDocument>>();

/// <summary>
/// Initializes a new instance of the <see cref="ODataSwaggerProvider" /> class.
/// Use this constructor for self-hosted scenarios.
Expand All @@ -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<SwaggerDocument>(() => {
//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();

Expand Down

0 comments on commit e466c9b

Please sign in to comment.