#529 removed cache manager specific code (#535)

This commit is contained in:
Tom Pallister 2018-08-11 18:21:07 +05:30 committed by GitHub
parent 2673aebee2
commit d4b65198f3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
21 changed files with 210 additions and 1096 deletions

View File

@ -1,5 +1,4 @@
using System; using System;
using System.Collections.Generic;
namespace Ocelot.Cache namespace Ocelot.Cache
{ {
@ -10,4 +9,24 @@ namespace Ocelot.Cache
T Get(string key, string region); T Get(string key, string region);
void ClearRegion(string region); void ClearRegion(string region);
} }
public class NoCache<T> : IOcelotCache<T>
{
public void Add(string key, T value, TimeSpan ttl, string region)
{
}
public void AddAndDelete(string key, T value, TimeSpan ttl, string region)
{
}
public void ClearRegion(string region)
{
}
public T Get(string key, string region)
{
return default(T);
}
}
} }

View File

@ -1,29 +1,25 @@
using System; namespace Ocelot.Cache.Middleware
{
using System;
using System.Linq; using System.Linq;
using System.Net.Http; using System.Net.Http;
using System.Threading.Tasks; using System.Threading.Tasks;
using Ocelot.Logging; using Ocelot.Logging;
using Ocelot.Middleware; using Ocelot.Middleware;
using System.IO; using System.IO;
using Ocelot.Middleware.Multiplexer;
namespace Ocelot.Cache.Middleware
{
public class OutputCacheMiddleware : OcelotMiddleware public class OutputCacheMiddleware : OcelotMiddleware
{ {
private readonly OcelotRequestDelegate _next; private readonly OcelotRequestDelegate _next;
private readonly IOcelotCache<CachedResponse> _outputCache; private readonly IOcelotCache<CachedResponse> _outputCache;
private readonly IRegionCreator _regionCreator;
public OutputCacheMiddleware(OcelotRequestDelegate next, public OutputCacheMiddleware(OcelotRequestDelegate next,
IOcelotLoggerFactory loggerFactory, IOcelotLoggerFactory loggerFactory,
IOcelotCache<CachedResponse> outputCache, IOcelotCache<CachedResponse> outputCache)
IRegionCreator regionCreator)
:base(loggerFactory.CreateLogger<OutputCacheMiddleware>()) :base(loggerFactory.CreateLogger<OutputCacheMiddleware>())
{ {
_next = next; _next = next;
_outputCache = outputCache; _outputCache = outputCache;
_regionCreator = regionCreator;
} }
public async Task Invoke(DownstreamContext context) public async Task Invoke(DownstreamContext context)

View File

@ -1,44 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using CacheManager.Core;
namespace Ocelot.Cache
{
public class OcelotCacheManagerCache<T> : IOcelotCache<T>
{
private readonly ICacheManager<T> _cacheManager;
public OcelotCacheManagerCache(ICacheManager<T> cacheManager)
{
_cacheManager = cacheManager;
}
public void Add(string key, T value, TimeSpan ttl, string region)
{
_cacheManager.Add(new CacheItem<T>(key, region, value, ExpirationMode.Absolute, ttl));
}
public void AddAndDelete(string key, T value, TimeSpan ttl, string region)
{
var exists = _cacheManager.Get(key);
if (exists != null)
{
_cacheManager.Remove(key);
}
Add(key, value, ttl, region);
}
public T Get(string key, string region)
{
return _cacheManager.Get<T>(key, region);
}
public void ClearRegion(string region)
{
_cacheManager.ClearRegion(region);
}
}
}

View File

@ -1,7 +1,7 @@
using System.Collections.Generic;
namespace Ocelot.Cache namespace Ocelot.Cache
{ {
using System.Collections.Generic;
public class Regions public class Regions
{ {
public Regions(List<string> value) public Regions(List<string> value)
@ -9,6 +9,6 @@ namespace Ocelot.Cache
Value = value; Value = value;
} }
public List<string> Value {get;private set;} public List<string> Value { get; }
} }
} }

View File

@ -9,6 +9,7 @@
} }
public int TtlSeconds { get; private set; } public int TtlSeconds { get; private set; }
public string Region { get; private set; } public string Region { get; private set; }
} }
} }

View File

@ -1,4 +1,3 @@
using CacheManager.Core;
using System; using System;
using System.Net.Http; using System.Net.Http;
using IdentityServer4.AccessTokenValidation; using IdentityServer4.AccessTokenValidation;
@ -14,8 +13,6 @@ namespace Ocelot.DependencyInjection
IConfiguration Configuration { get; } IConfiguration Configuration { get; }
IOcelotBuilder AddStoreOcelotConfigurationInConsul(); IOcelotBuilder AddStoreOcelotConfigurationInConsul();
IOcelotBuilder AddCacheManager(Action<ConfigurationBuilderCachePart> settings);
IOcelotAdministrationBuilder AddAdministration(string path, string secret); IOcelotAdministrationBuilder AddAdministration(string path, string secret);
IOcelotAdministrationBuilder AddAdministration(string path, Action<IdentityServerAuthenticationOptions> configOptions); IOcelotAdministrationBuilder AddAdministration(string path, Action<IdentityServerAuthenticationOptions> configOptions);

View File

@ -1,6 +1,5 @@
namespace Ocelot.DependencyInjection namespace Ocelot.DependencyInjection
{ {
using CacheManager.Core;
using IdentityServer4.Models; using IdentityServer4.Models;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Configuration;
@ -50,118 +49,110 @@ namespace Ocelot.DependencyInjection
public class OcelotBuilder : IOcelotBuilder public class OcelotBuilder : IOcelotBuilder
{ {
private readonly IServiceCollection _services; public IServiceCollection Services { get; }
private readonly IConfiguration _configurationRoot; public IConfiguration Configuration { get; }
public IServiceCollection Services => _services;
public IConfiguration Configuration => _configurationRoot;
public OcelotBuilder(IServiceCollection services, IConfiguration configurationRoot) public OcelotBuilder(IServiceCollection services, IConfiguration configurationRoot)
{ {
_configurationRoot = configurationRoot; Configuration = configurationRoot;
_services = services; Services = services;
//add default cache settings... Services.Configure<FileConfiguration>(configurationRoot);
Action<ConfigurationBuilderCachePart> defaultCachingSettings = x =>
{
x.WithDictionaryHandle();
};
AddCacheManager(defaultCachingSettings); //default no caches...
Services.TryAddSingleton<IOcelotCache<FileConfiguration>, NoCache<FileConfiguration>>();
Services.TryAddSingleton<IOcelotCache<CachedResponse>, NoCache<CachedResponse>>();
//add ocelot services... Services.TryAddSingleton<IHttpResponseHeaderReplacer, HttpResponseHeaderReplacer>();
_services.Configure<FileConfiguration>(configurationRoot); Services.TryAddSingleton<IHttpContextRequestHeaderReplacer, HttpContextRequestHeaderReplacer>();
_services.TryAddSingleton<IHttpResponseHeaderReplacer, HttpResponseHeaderReplacer>(); Services.TryAddSingleton<IHeaderFindAndReplaceCreator, HeaderFindAndReplaceCreator>();
_services.TryAddSingleton<IHttpContextRequestHeaderReplacer, HttpContextRequestHeaderReplacer>(); Services.TryAddSingleton<IInternalConfigurationCreator, FileInternalConfigurationCreator>();
_services.TryAddSingleton<IHeaderFindAndReplaceCreator, HeaderFindAndReplaceCreator>(); Services.TryAddSingleton<IInternalConfigurationRepository, InMemoryInternalConfigurationRepository>();
_services.TryAddSingleton<IInternalConfigurationCreator, FileInternalConfigurationCreator>(); Services.TryAddSingleton<IConfigurationValidator, FileConfigurationFluentValidator>();
_services.TryAddSingleton<IInternalConfigurationRepository, InMemoryInternalConfigurationRepository>(); Services.TryAddSingleton<IClaimsToThingCreator, ClaimsToThingCreator>();
_services.TryAddSingleton<IConfigurationValidator, FileConfigurationFluentValidator>(); Services.TryAddSingleton<IAuthenticationOptionsCreator, AuthenticationOptionsCreator>();
_services.TryAddSingleton<IClaimsToThingCreator, ClaimsToThingCreator>(); Services.TryAddSingleton<IUpstreamTemplatePatternCreator, UpstreamTemplatePatternCreator>();
_services.TryAddSingleton<IAuthenticationOptionsCreator, AuthenticationOptionsCreator>(); Services.TryAddSingleton<IRequestIdKeyCreator, RequestIdKeyCreator>();
_services.TryAddSingleton<IUpstreamTemplatePatternCreator, UpstreamTemplatePatternCreator>(); Services.TryAddSingleton<IServiceProviderConfigurationCreator,ServiceProviderConfigurationCreator>();
_services.TryAddSingleton<IRequestIdKeyCreator, RequestIdKeyCreator>(); Services.TryAddSingleton<IQoSOptionsCreator, QoSOptionsCreator>();
_services.TryAddSingleton<IServiceProviderConfigurationCreator,ServiceProviderConfigurationCreator>(); Services.TryAddSingleton<IReRouteOptionsCreator, ReRouteOptionsCreator>();
_services.TryAddSingleton<IQoSOptionsCreator, QoSOptionsCreator>(); Services.TryAddSingleton<IRateLimitOptionsCreator, RateLimitOptionsCreator>();
_services.TryAddSingleton<IReRouteOptionsCreator, ReRouteOptionsCreator>(); Services.TryAddSingleton<IBaseUrlFinder, BaseUrlFinder>();
_services.TryAddSingleton<IRateLimitOptionsCreator, RateLimitOptionsCreator>(); Services.TryAddSingleton<IRegionCreator, RegionCreator>();
_services.TryAddSingleton<IBaseUrlFinder, BaseUrlFinder>(); Services.TryAddSingleton<IFileConfigurationRepository, DiskFileConfigurationRepository>();
_services.TryAddSingleton<IRegionCreator, RegionCreator>(); Services.TryAddSingleton<IFileConfigurationSetter, FileAndInternalConfigurationSetter>();
_services.TryAddSingleton<IFileConfigurationRepository, DiskFileConfigurationRepository>(); Services.TryAddSingleton<IQosProviderHouse, QosProviderHouse>();
_services.TryAddSingleton<IFileConfigurationSetter, FileAndInternalConfigurationSetter>(); Services.TryAddSingleton<IQoSProviderFactory, QoSProviderFactory>();
_services.TryAddSingleton<IQosProviderHouse, QosProviderHouse>(); Services.TryAddSingleton<IServiceDiscoveryProviderFactory, ServiceDiscoveryProviderFactory>();
_services.TryAddSingleton<IQoSProviderFactory, QoSProviderFactory>(); Services.TryAddSingleton<ILoadBalancerFactory, LoadBalancerFactory>();
_services.TryAddSingleton<IServiceDiscoveryProviderFactory, ServiceDiscoveryProviderFactory>(); Services.TryAddSingleton<ILoadBalancerHouse, LoadBalancerHouse>();
_services.TryAddSingleton<ILoadBalancerFactory, LoadBalancerFactory>(); Services.TryAddSingleton<IOcelotLoggerFactory, AspDotNetLoggerFactory>();
_services.TryAddSingleton<ILoadBalancerHouse, LoadBalancerHouse>(); Services.TryAddSingleton<IRemoveOutputHeaders, RemoveOutputHeaders>();
_services.TryAddSingleton<IOcelotLoggerFactory, AspDotNetLoggerFactory>(); Services.TryAddSingleton<IClaimToThingConfigurationParser, ClaimToThingConfigurationParser>();
_services.TryAddSingleton<IRemoveOutputHeaders, RemoveOutputHeaders>(); Services.TryAddSingleton<IClaimsAuthoriser, ClaimsAuthoriser>();
_services.TryAddSingleton<IClaimToThingConfigurationParser, ClaimToThingConfigurationParser>(); Services.TryAddSingleton<IScopesAuthoriser, ScopesAuthoriser>();
_services.TryAddSingleton<IClaimsAuthoriser, ClaimsAuthoriser>(); Services.TryAddSingleton<IAddClaimsToRequest, AddClaimsToRequest>();
_services.TryAddSingleton<IScopesAuthoriser, ScopesAuthoriser>(); Services.TryAddSingleton<IAddHeadersToRequest, AddHeadersToRequest>();
_services.TryAddSingleton<IAddClaimsToRequest, AddClaimsToRequest>(); Services.TryAddSingleton<IAddQueriesToRequest, AddQueriesToRequest>();
_services.TryAddSingleton<IAddHeadersToRequest, AddHeadersToRequest>(); Services.TryAddSingleton<IClaimsParser, ClaimsParser>();
_services.TryAddSingleton<IAddQueriesToRequest, AddQueriesToRequest>(); Services.TryAddSingleton<IUrlPathToUrlTemplateMatcher, RegExUrlMatcher>();
_services.TryAddSingleton<IClaimsParser, ClaimsParser>(); Services.TryAddSingleton<IPlaceholderNameAndValueFinder, UrlPathPlaceholderNameAndValueFinder>();
_services.TryAddSingleton<IUrlPathToUrlTemplateMatcher, RegExUrlMatcher>(); Services.TryAddSingleton<IDownstreamPathPlaceholderReplacer, DownstreamTemplatePathPlaceholderReplacer>();
_services.TryAddSingleton<IPlaceholderNameAndValueFinder, UrlPathPlaceholderNameAndValueFinder>(); Services.AddSingleton<IDownstreamRouteProvider, DownstreamRouteFinder>();
_services.TryAddSingleton<IDownstreamPathPlaceholderReplacer, DownstreamTemplatePathPlaceholderReplacer>(); Services.AddSingleton<IDownstreamRouteProvider, DownstreamRouteCreator>();
_services.AddSingleton<IDownstreamRouteProvider, DownstreamRouteFinder>(); Services.TryAddSingleton<IDownstreamRouteProviderFactory, DownstreamRouteProviderFactory>();
_services.AddSingleton<IDownstreamRouteProvider, Ocelot.DownstreamRouteFinder.Finder.DownstreamRouteCreator>(); Services.TryAddSingleton<IHttpRequester, HttpClientHttpRequester>();
_services.TryAddSingleton<IDownstreamRouteProviderFactory, Ocelot.DownstreamRouteFinder.Finder.DownstreamRouteProviderFactory>(); Services.TryAddSingleton<IHttpResponder, HttpContextResponder>();
_services.TryAddSingleton<IHttpRequester, HttpClientHttpRequester>(); Services.TryAddSingleton<IErrorsToHttpStatusCodeMapper, ErrorsToHttpStatusCodeMapper>();
_services.TryAddSingleton<IHttpResponder, HttpContextResponder>(); Services.TryAddSingleton<IRateLimitCounterHandler, MemoryCacheRateLimitCounterHandler>();
_services.TryAddSingleton<IErrorsToHttpStatusCodeMapper, ErrorsToHttpStatusCodeMapper>(); Services.TryAddSingleton<IHttpClientCache, MemoryHttpClientCache>();
_services.TryAddSingleton<IRateLimitCounterHandler, MemoryCacheRateLimitCounterHandler>(); Services.TryAddSingleton<IRequestMapper, RequestMapper>();
_services.TryAddSingleton<IHttpClientCache, MemoryHttpClientCache>(); Services.TryAddSingleton<IHttpHandlerOptionsCreator, HttpHandlerOptionsCreator>();
_services.TryAddSingleton<IRequestMapper, RequestMapper>(); Services.TryAddSingleton<IDownstreamAddressesCreator, DownstreamAddressesCreator>();
_services.TryAddSingleton<IHttpHandlerOptionsCreator, HttpHandlerOptionsCreator>(); Services.TryAddSingleton<IDelegatingHandlerHandlerFactory, DelegatingHandlerHandlerFactory>();
_services.TryAddSingleton<IDownstreamAddressesCreator, DownstreamAddressesCreator>();
_services.TryAddSingleton<IDelegatingHandlerHandlerFactory, DelegatingHandlerHandlerFactory>();
if (UsingEurekaServiceDiscoveryProvider(configurationRoot)) if (UsingEurekaServiceDiscoveryProvider(configurationRoot))
{ {
_services.AddDiscoveryClient(configurationRoot); Services.AddDiscoveryClient(configurationRoot);
} }
else else
{ {
_services.TryAddSingleton<IDiscoveryClient, FakeEurekaDiscoveryClient>(); Services.TryAddSingleton<IDiscoveryClient, FakeEurekaDiscoveryClient>();
} }
_services.TryAddSingleton<IHttpRequester, HttpClientHttpRequester>(); Services.TryAddSingleton<IHttpRequester, HttpClientHttpRequester>();
// see this for why we register this as singleton http://stackoverflow.com/questions/37371264/invalidoperationexception-unable-to-resolve-service-for-type-microsoft-aspnetc // see this for why we register this as singleton http://stackoverflow.com/questions/37371264/invalidoperationexception-unable-to-resolve-service-for-type-microsoft-aspnetc
// could maybe use a scoped data repository // could maybe use a scoped data repository
_services.TryAddSingleton<IHttpContextAccessor, HttpContextAccessor>(); Services.TryAddSingleton<IHttpContextAccessor, HttpContextAccessor>();
_services.TryAddSingleton<IRequestScopedDataRepository, HttpDataRepository>(); Services.TryAddSingleton<IRequestScopedDataRepository, HttpDataRepository>();
_services.AddMemoryCache(); Services.AddMemoryCache();
_services.TryAddSingleton<OcelotDiagnosticListener>(); Services.TryAddSingleton<OcelotDiagnosticListener>();
//add asp.net services.. //add asp.net services..
var assembly = typeof(FileConfigurationController).GetTypeInfo().Assembly; var assembly = typeof(FileConfigurationController).GetTypeInfo().Assembly;
_services.AddMvcCore() Services.AddMvcCore()
.AddApplicationPart(assembly) .AddApplicationPart(assembly)
.AddControllersAsServices() .AddControllersAsServices()
.AddAuthorization() .AddAuthorization()
.AddJsonFormatters(); .AddJsonFormatters();
_services.AddLogging(); Services.AddLogging();
_services.AddMiddlewareAnalysis(); Services.AddMiddlewareAnalysis();
_services.AddWebEncoders(); Services.AddWebEncoders();
_services.TryAddSingleton<IMultiplexer, Multiplexer>(); Services.TryAddSingleton<IMultiplexer, Multiplexer>();
_services.TryAddSingleton<IResponseAggregator, SimpleJsonResponseAggregator>(); Services.TryAddSingleton<IResponseAggregator, SimpleJsonResponseAggregator>();
_services.AddSingleton<ITracingHandlerFactory, TracingHandlerFactory>(); Services.AddSingleton<ITracingHandlerFactory, TracingHandlerFactory>();
_services.TryAddSingleton<IFileConfigurationPollerOptions, InMemoryFileConfigurationPollerOptions>(); Services.TryAddSingleton<IFileConfigurationPollerOptions, InMemoryFileConfigurationPollerOptions>();
_services.TryAddSingleton<IAddHeadersToResponse, AddHeadersToResponse>(); Services.TryAddSingleton<IAddHeadersToResponse, AddHeadersToResponse>();
_services.TryAddSingleton<IPlaceholders, Placeholders>(); Services.TryAddSingleton<IPlaceholders, Placeholders>();
_services.TryAddSingleton<IConsulClientFactory, ConsulClientFactory>(); Services.TryAddSingleton<IConsulClientFactory, ConsulClientFactory>();
_services.TryAddSingleton<IResponseAggregatorFactory, InMemoryResponseAggregatorFactory>(); Services.TryAddSingleton<IResponseAggregatorFactory, InMemoryResponseAggregatorFactory>();
_services.TryAddSingleton<IDefinedAggregatorProvider, ServiceLocatorDefinedAggregatorProvider>(); Services.TryAddSingleton<IDefinedAggregatorProvider, ServiceLocatorDefinedAggregatorProvider>();
_services.TryAddSingleton<IDownstreamRequestCreator, DownstreamRequestCreator>(); Services.TryAddSingleton<IDownstreamRequestCreator, DownstreamRequestCreator>();
_services.TryAddSingleton<IFrameworkDescription, FrameworkDescription>(); Services.TryAddSingleton<IFrameworkDescription, FrameworkDescription>();
} }
public IOcelotAdministrationBuilder AddAdministration(string path, string secret) public IOcelotAdministrationBuilder AddAdministration(string path, string secret)
@ -176,8 +167,8 @@ namespace Ocelot.DependencyInjection
AddIdentityServer(identityServerConfiguration, administrationPath); AddIdentityServer(identityServerConfiguration, administrationPath);
} }
_services.AddSingleton<IAdministrationPath>(administrationPath); Services.AddSingleton<IAdministrationPath>(administrationPath);
return new OcelotAdministrationBuilder(_services, _configurationRoot); return new OcelotAdministrationBuilder(Services, Configuration);
} }
public IOcelotAdministrationBuilder AddAdministration(string path, Action<IdentityServerAuthenticationOptions> configureOptions) public IOcelotAdministrationBuilder AddAdministration(string path, Action<IdentityServerAuthenticationOptions> configureOptions)
@ -189,21 +180,21 @@ namespace Ocelot.DependencyInjection
AddIdentityServer(configureOptions); AddIdentityServer(configureOptions);
} }
_services.AddSingleton<IAdministrationPath>(administrationPath); Services.AddSingleton<IAdministrationPath>(administrationPath);
return new OcelotAdministrationBuilder(_services, _configurationRoot); return new OcelotAdministrationBuilder(Services, Configuration);
} }
public IOcelotBuilder AddSingletonDefinedAggregator<T>() public IOcelotBuilder AddSingletonDefinedAggregator<T>()
where T : class, IDefinedAggregator where T : class, IDefinedAggregator
{ {
_services.AddSingleton<IDefinedAggregator, T>(); Services.AddSingleton<IDefinedAggregator, T>();
return this; return this;
} }
public IOcelotBuilder AddTransientDefinedAggregator<T>() public IOcelotBuilder AddTransientDefinedAggregator<T>()
where T : class, IDefinedAggregator where T : class, IDefinedAggregator
{ {
_services.AddTransient<IDefinedAggregator, T>(); Services.AddTransient<IDefinedAggregator, T>();
return this; return this;
} }
@ -212,15 +203,15 @@ namespace Ocelot.DependencyInjection
{ {
if(global) if(global)
{ {
_services.AddTransient<THandler>(); Services.AddTransient<THandler>();
_services.AddTransient<GlobalDelegatingHandler>(s => { Services.AddTransient<GlobalDelegatingHandler>(s => {
var service = s.GetService<THandler>(); var service = s.GetService<THandler>();
return new GlobalDelegatingHandler(service); return new GlobalDelegatingHandler(service);
}); });
} }
else else
{ {
_services.AddTransient<DelegatingHandler, THandler>(); Services.AddTransient<DelegatingHandler, THandler>();
} }
return this; return this;
@ -228,59 +219,33 @@ namespace Ocelot.DependencyInjection
public IOcelotBuilder AddStoreOcelotConfigurationInConsul() public IOcelotBuilder AddStoreOcelotConfigurationInConsul()
{ {
_services.AddHostedService<FileConfigurationPoller>(); Services.AddHostedService<FileConfigurationPoller>();
_services.AddSingleton<IFileConfigurationRepository, ConsulFileConfigurationRepository>(); Services.AddSingleton<IFileConfigurationRepository, ConsulFileConfigurationRepository>();
return this;
}
public IOcelotBuilder AddCacheManager(Action<ConfigurationBuilderCachePart> settings)
{
var cacheManagerOutputCache = CacheFactory.Build<CachedResponse>("OcelotOutputCache", settings);
var ocelotOutputCacheManager = new OcelotCacheManagerCache<CachedResponse>(cacheManagerOutputCache);
_services.RemoveAll(typeof(ICacheManager<CachedResponse>));
_services.RemoveAll(typeof(IOcelotCache<CachedResponse>));
_services.AddSingleton<ICacheManager<CachedResponse>>(cacheManagerOutputCache);
_services.AddSingleton<IOcelotCache<CachedResponse>>(ocelotOutputCacheManager);
var ocelotConfigCacheManagerOutputCache = CacheFactory.Build<IInternalConfiguration>("OcelotConfigurationCache", settings);
var ocelotConfigCacheManager = new OcelotCacheManagerCache<IInternalConfiguration>(ocelotConfigCacheManagerOutputCache);
_services.RemoveAll(typeof(ICacheManager<IInternalConfiguration>));
_services.RemoveAll(typeof(IOcelotCache<IInternalConfiguration>));
_services.AddSingleton<ICacheManager<IInternalConfiguration>>(ocelotConfigCacheManagerOutputCache);
_services.AddSingleton<IOcelotCache<IInternalConfiguration>>(ocelotConfigCacheManager);
var fileConfigCacheManagerOutputCache = CacheFactory.Build<FileConfiguration>("FileConfigurationCache", settings);
var fileConfigCacheManager = new OcelotCacheManagerCache<FileConfiguration>(fileConfigCacheManagerOutputCache);
_services.RemoveAll(typeof(ICacheManager<FileConfiguration>));
_services.RemoveAll(typeof(IOcelotCache<FileConfiguration>));
_services.AddSingleton<ICacheManager<FileConfiguration>>(fileConfigCacheManagerOutputCache);
_services.AddSingleton<IOcelotCache<FileConfiguration>>(fileConfigCacheManager);
return this; return this;
} }
private void AddIdentityServer(Action<IdentityServerAuthenticationOptions> configOptions) private void AddIdentityServer(Action<IdentityServerAuthenticationOptions> configOptions)
{ {
_services Services
.AddAuthentication(IdentityServerAuthenticationDefaults.AuthenticationScheme) .AddAuthentication(IdentityServerAuthenticationDefaults.AuthenticationScheme)
.AddIdentityServerAuthentication(configOptions); .AddIdentityServerAuthentication(configOptions);
} }
private void AddIdentityServer(IIdentityServerConfiguration identityServerConfiguration, IAdministrationPath adminPath) private void AddIdentityServer(IIdentityServerConfiguration identityServerConfiguration, IAdministrationPath adminPath)
{ {
_services.TryAddSingleton<IIdentityServerConfiguration>(identityServerConfiguration); Services.TryAddSingleton<IIdentityServerConfiguration>(identityServerConfiguration);
var identityServerBuilder = _services var identityServerBuilder = Services
.AddIdentityServer(o => { .AddIdentityServer(o => {
o.IssuerUri = "Ocelot"; o.IssuerUri = "Ocelot";
}) })
.AddInMemoryApiResources(Resources(identityServerConfiguration)) .AddInMemoryApiResources(Resources(identityServerConfiguration))
.AddInMemoryClients(Client(identityServerConfiguration)); .AddInMemoryClients(Client(identityServerConfiguration));
var urlFinder = new BaseUrlFinder(_configurationRoot); var urlFinder = new BaseUrlFinder(Configuration);
var baseSchemeUrlAndPort = urlFinder.Find(); var baseSchemeUrlAndPort = urlFinder.Find();
JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear(); JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();
_services.AddAuthentication(IdentityServerAuthenticationDefaults.AuthenticationScheme) Services.AddAuthentication(IdentityServerAuthenticationDefaults.AuthenticationScheme)
.AddIdentityServerAuthentication(o => .AddIdentityServerAuthentication(o =>
{ {
o.Authority = baseSchemeUrlAndPort + adminPath.Path; o.Authority = baseSchemeUrlAndPort + adminPath.Path;

View File

@ -45,9 +45,6 @@
<PrivateAssets>all</PrivateAssets> <PrivateAssets>all</PrivateAssets>
</PackageReference> </PackageReference>
<PackageReference Include="System.Text.RegularExpressions" Version="4.3.0" /> <PackageReference Include="System.Text.RegularExpressions" Version="4.3.0" />
<PackageReference Include="CacheManager.Core" Version="1.1.2" />
<PackageReference Include="CacheManager.Microsoft.Extensions.Configuration" Version="1.1.2" />
<PackageReference Include="CacheManager.Microsoft.Extensions.Logging" Version="1.1.2" />
<PackageReference Include="Consul" Version="0.7.2.5" /> <PackageReference Include="Consul" Version="0.7.2.5" />
<PackageReference Include="Polly" Version="6.0.1" /> <PackageReference Include="Polly" Version="6.0.1" />
<PackageReference Include="IdentityServer4" Version="2.2.0" /> <PackageReference Include="IdentityServer4" Version="2.2.0" />

View File

@ -1,137 +0,0 @@
using CacheManager.Core;
using CacheManager.Core.Internal;
using CacheManager.Core.Logging;
using System;
using System.Collections.Concurrent;
using System.Linq;
using static CacheManager.Core.Utility.Guard;
namespace Ocelot.AcceptanceTests.Caching
{
public class InMemoryJsonHandle<TCacheValue> : BaseCacheHandle<TCacheValue>
{
private readonly ICacheSerializer _serializer;
private readonly ConcurrentDictionary<string, Tuple<Type, byte[]>> _cache;
public InMemoryJsonHandle(
ICacheManagerConfiguration managerConfiguration,
CacheHandleConfiguration configuration,
ICacheSerializer serializer,
ILoggerFactory loggerFactory) : base(managerConfiguration, configuration)
{
_cache = new ConcurrentDictionary<string, Tuple<Type, byte[]>>();
_serializer = serializer;
Logger = loggerFactory.CreateLogger(this);
}
public override int Count => _cache.Count;
protected override ILogger Logger { get; }
public override void Clear() => _cache.Clear();
public override void ClearRegion(string region)
{
NotNullOrWhiteSpace(region, nameof(region));
var key = string.Concat(region, ":");
foreach (var item in _cache.Where(p => p.Key.StartsWith(key, StringComparison.OrdinalIgnoreCase)))
{
_cache.TryRemove(item.Key, out Tuple<Type, byte[]> val);
}
}
public override bool Exists(string key)
{
NotNullOrWhiteSpace(key, nameof(key));
return _cache.ContainsKey(key);
}
public override bool Exists(string key, string region)
{
NotNullOrWhiteSpace(region, nameof(region));
var fullKey = GetKey(key, region);
return _cache.ContainsKey(fullKey);
}
protected override bool AddInternalPrepared(CacheItem<TCacheValue> item)
{
NotNull(item, nameof(item));
var key = GetKey(item.Key, item.Region);
var serializedItem = _serializer.SerializeCacheItem(item);
return _cache.TryAdd(key, new Tuple<Type, byte[]>(item.Value.GetType(), serializedItem));
}
protected override CacheItem<TCacheValue> GetCacheItemInternal(string key) => GetCacheItemInternal(key, null);
protected override CacheItem<TCacheValue> GetCacheItemInternal(string key, string region)
{
var fullKey = GetKey(key, region);
CacheItem<TCacheValue> deserializedResult = null;
if (_cache.TryGetValue(fullKey, out Tuple<Type, byte[]> result))
{
deserializedResult = _serializer.DeserializeCacheItem<TCacheValue>(result.Item2, result.Item1);
if (deserializedResult.ExpirationMode != ExpirationMode.None && IsExpired(deserializedResult, DateTime.UtcNow))
{
_cache.TryRemove(fullKey, out Tuple<Type, byte[]> removeResult);
TriggerCacheSpecificRemove(key, region, CacheItemRemovedReason.Expired, deserializedResult.Value);
return null;
}
}
return deserializedResult;
}
protected override void PutInternalPrepared(CacheItem<TCacheValue> item)
{
NotNull(item, nameof(item));
var serializedItem = _serializer.SerializeCacheItem<TCacheValue>(item);
_cache[GetKey(item.Key, item.Region)] = new Tuple<Type, byte[]>(item.Value.GetType(), serializedItem);
}
protected override bool RemoveInternal(string key) => RemoveInternal(key, null);
protected override bool RemoveInternal(string key, string region)
{
var fullKey = GetKey(key, region);
return _cache.TryRemove(fullKey, out Tuple<Type, byte[]> val);
}
private static string GetKey(string key, string region)
{
NotNullOrWhiteSpace(key, nameof(key));
if (string.IsNullOrWhiteSpace(region))
{
return key;
}
return string.Concat(region, ":", key);
}
private static bool IsExpired(CacheItem<TCacheValue> item, DateTime now)
{
if (item.ExpirationMode == ExpirationMode.Absolute
&& item.CreatedUtc.Add(item.ExpirationTimeout) < now)
{
return true;
}
else if (item.ExpirationMode == ExpirationMode.Sliding
&& item.LastAccessedUtc.Add(item.ExpirationTimeout) < now)
{
return true;
}
return false;
}
}
}

View File

@ -1,225 +0,0 @@
namespace Ocelot.AcceptanceTests
{
using System;
using System.Collections.Generic;
using System.Net;
using System.Threading;
using Microsoft.AspNetCore.Http;
using Ocelot.Configuration.File;
using TestStack.BDDfy;
using Xunit;
public class CachingTests : IDisposable
{
private readonly Steps _steps;
private readonly ServiceHandler _serviceHandler;
public CachingTests()
{
_serviceHandler = new ServiceHandler();
_steps = new Steps();
}
[Fact]
public void should_return_cached_response()
{
var configuration = new FileConfiguration
{
ReRoutes = new List<FileReRoute>
{
new FileReRoute
{
DownstreamPathTemplate = "/",
DownstreamHostAndPorts = new List<FileHostAndPort>
{
new FileHostAndPort
{
Host = "localhost",
Port = 51899,
}
},
DownstreamScheme = "http",
UpstreamPathTemplate = "/",
UpstreamHttpMethod = new List<string> { "Get" },
FileCacheOptions = new FileCacheOptions
{
TtlSeconds = 100
}
}
}
};
this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:51899", 200, "Hello from Laura", null, null))
.And(x => _steps.GivenThereIsAConfiguration(configuration))
.And(x => _steps.GivenOcelotIsRunning())
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
.Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.OK))
.And(x => _steps.ThenTheResponseBodyShouldBe("Hello from Laura"))
.Given(x => x.GivenTheServiceNowReturns("http://localhost:51899", 200, "Hello from Tom"))
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
.Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.OK))
.And(x => _steps.ThenTheResponseBodyShouldBe("Hello from Laura"))
.And(x => _steps.ThenTheContentLengthIs(16))
.BDDfy();
}
[Fact]
public void should_return_cached_response_with_expires_header()
{
var configuration = new FileConfiguration
{
ReRoutes = new List<FileReRoute>
{
new FileReRoute
{
DownstreamPathTemplate = "/",
DownstreamHostAndPorts = new List<FileHostAndPort>
{
new FileHostAndPort
{
Host = "localhost",
Port = 52839,
}
},
DownstreamScheme = "http",
UpstreamPathTemplate = "/",
UpstreamHttpMethod = new List<string> { "Get" },
FileCacheOptions = new FileCacheOptions
{
TtlSeconds = 100
}
}
}
};
this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:52839", 200, "Hello from Laura", "Expires", "-1"))
.And(x => _steps.GivenThereIsAConfiguration(configuration))
.And(x => _steps.GivenOcelotIsRunning())
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
.Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.OK))
.And(x => _steps.ThenTheResponseBodyShouldBe("Hello from Laura"))
.Given(x => x.GivenTheServiceNowReturns("http://localhost:52839", 200, "Hello from Tom"))
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
.Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.OK))
.And(x => _steps.ThenTheResponseBodyShouldBe("Hello from Laura"))
.And(x => _steps.ThenTheContentLengthIs(16))
.And(x => _steps.ThenTheResponseBodyHeaderIs("Expires", "-1"))
.BDDfy();
}
[Fact]
public void should_return_cached_response_when_using_jsonserialized_cache()
{
var configuration = new FileConfiguration
{
ReRoutes = new List<FileReRoute>
{
new FileReRoute
{
DownstreamPathTemplate = "/",
DownstreamHostAndPorts = new List<FileHostAndPort>
{
new FileHostAndPort
{
Host = "localhost",
Port = 51899,
}
},
DownstreamScheme = "http",
UpstreamPathTemplate = "/",
UpstreamHttpMethod = new List<string> { "Get" },
FileCacheOptions = new FileCacheOptions
{
TtlSeconds = 100
}
}
}
};
this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:51899", 200, "Hello from Laura", null, null))
.And(x => _steps.GivenThereIsAConfiguration(configuration))
.And(x => _steps.GivenOcelotIsRunningUsingJsonSerializedCache())
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
.Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.OK))
.And(x => _steps.ThenTheResponseBodyShouldBe("Hello from Laura"))
.Given(x => x.GivenTheServiceNowReturns("http://localhost:51899", 200, "Hello from Tom"))
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
.Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.OK))
.And(x => _steps.ThenTheResponseBodyShouldBe("Hello from Laura"))
.BDDfy();
}
[Fact]
public void should_not_return_cached_response_as_ttl_expires()
{
var configuration = new FileConfiguration
{
ReRoutes = new List<FileReRoute>
{
new FileReRoute
{
DownstreamPathTemplate = "/",
DownstreamHostAndPorts = new List<FileHostAndPort>
{
new FileHostAndPort
{
Host = "localhost",
Port = 51899,
}
},
DownstreamScheme = "http",
UpstreamPathTemplate = "/",
UpstreamHttpMethod = new List<string> { "Get" },
FileCacheOptions = new FileCacheOptions
{
TtlSeconds = 1
}
}
}
};
this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:51899", 200, "Hello from Laura", null, null))
.And(x => _steps.GivenThereIsAConfiguration(configuration))
.And(x => _steps.GivenOcelotIsRunning())
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
.Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.OK))
.And(x => _steps.ThenTheResponseBodyShouldBe("Hello from Laura"))
.Given(x => x.GivenTheServiceNowReturns("http://localhost:51899", 200, "Hello from Tom"))
.And(x => x.GivenTheCacheExpires())
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
.Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.OK))
.And(x => _steps.ThenTheResponseBodyShouldBe("Hello from Tom"))
.BDDfy();
}
private void GivenTheCacheExpires()
{
Thread.Sleep(1000);
}
private void GivenTheServiceNowReturns(string url, int statusCode, string responseBody)
{
_serviceHandler.Dispose();
GivenThereIsAServiceRunningOn(url, statusCode, responseBody, null, null);
}
private void GivenThereIsAServiceRunningOn(string url, int statusCode, string responseBody, string key, string value)
{
_serviceHandler.GivenThereIsAServiceRunningOn(url, async context =>
{
if (!string.IsNullOrEmpty(key) && !string.IsNullOrEmpty(key))
{
context.Response.Headers.Add(key, value);
}
context.Response.StatusCode = statusCode;
await context.Response.WriteAsync(responseBody);
});
}
public void Dispose()
{
_serviceHandler?.Dispose();
_steps.Dispose();
}
}
}

View File

@ -17,6 +17,8 @@ using static Ocelot.Infrastructure.Wait;
namespace Ocelot.AcceptanceTests namespace Ocelot.AcceptanceTests
{ {
using Cache;
public class ConfigurationInConsulTests : IDisposable public class ConfigurationInConsulTests : IDisposable
{ {
private IWebHost _builder; private IWebHost _builder;
@ -76,51 +78,6 @@ namespace Ocelot.AcceptanceTests
.BDDfy(); .BDDfy();
} }
[Fact]
public void should_return_response_200_with_simple_url_when_using_jsonserialized_cache()
{
var configuration = new FileConfiguration
{
ReRoutes = new List<FileReRoute>
{
new FileReRoute
{
DownstreamPathTemplate = "/",
DownstreamScheme = "http",
DownstreamHostAndPorts = new List<FileHostAndPort>
{
new FileHostAndPort
{
Host = "localhost",
Port = 51779,
}
},
UpstreamPathTemplate = "/",
UpstreamHttpMethod = new List<string> { "Get" },
}
},
GlobalConfiguration = new FileGlobalConfiguration()
{
ServiceDiscoveryProvider = new FileServiceDiscoveryProvider()
{
Host = "localhost",
Port = 9502
}
}
};
var fakeConsulServiceDiscoveryUrl = "http://localhost:9502";
this.Given(x => GivenThereIsAFakeConsulServiceDiscoveryProvider(fakeConsulServiceDiscoveryUrl, ""))
.And(x => x.GivenThereIsAServiceRunningOn("http://localhost:51779", "", 200, "Hello from Laura"))
.And(x => _steps.GivenThereIsAConfiguration(configuration))
.And(x => _steps.GivenOcelotIsRunningUsingConsulToStoreConfigAndJsonSerializedCache())
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
.Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.OK))
.And(x => _steps.ThenTheResponseBodyShouldBe("Hello from Laura"))
.BDDfy();
}
[Fact] [Fact]
public void should_load_configuration_out_of_consul() public void should_load_configuration_out_of_consul()
{ {
@ -485,5 +442,28 @@ namespace Ocelot.AcceptanceTests
_builder?.Dispose(); _builder?.Dispose();
_steps.Dispose(); _steps.Dispose();
} }
class FakeCache : IOcelotCache<FileConfiguration>
{
public void Add(string key, FileConfiguration value, TimeSpan ttl, string region)
{
throw new NotImplementedException();
}
public void AddAndDelete(string key, FileConfiguration value, TimeSpan ttl, string region)
{
throw new NotImplementedException();
}
public FileConfiguration Get(string key, string region)
{
throw new NotImplementedException();
}
public void ClearRegion(string region)
{
throw new NotImplementedException();
}
}
} }
} }

View File

@ -32,7 +32,6 @@
<Service Include="{82a7f48d-3b50-4b1e-b82e-3ada8210c358}" /> <Service Include="{82a7f48d-3b50-4b1e-b82e-3ada8210c358}" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="CacheManager.Serialization.Json" Version="1.1.2" />
<PackageReference Include="Microsoft.AspNetCore.All" Version="2.1.1" /> <PackageReference Include="Microsoft.AspNetCore.All" Version="2.1.1" />
<PackageReference Include="Microsoft.AspNetCore.TestHost" Version="2.1.1" /> <PackageReference Include="Microsoft.AspNetCore.TestHost" Version="2.1.1" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.7.2" /> <PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.7.2" />

View File

@ -1,4 +1,6 @@
using System; namespace Ocelot.AcceptanceTests
{
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
@ -7,7 +9,6 @@ using System.Net.Http;
using System.Net.Http.Headers; using System.Net.Http.Headers;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using CacheManager.Core;
using IdentityServer4.AccessTokenValidation; using IdentityServer4.AccessTokenValidation;
using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Hosting;
@ -21,20 +22,14 @@ using Ocelot.DependencyInjection;
using Ocelot.Middleware; using Ocelot.Middleware;
using Shouldly; using Shouldly;
using ConfigurationBuilder = Microsoft.Extensions.Configuration.ConfigurationBuilder; using ConfigurationBuilder = Microsoft.Extensions.Configuration.ConfigurationBuilder;
using Ocelot.AcceptanceTests.Caching;
using System.IO.Compression; using System.IO.Compression;
using System.Text; using System.Text;
using static Ocelot.AcceptanceTests.HttpDelegatingHandlersTests; using static Ocelot.AcceptanceTests.HttpDelegatingHandlersTests;
using Ocelot.Requester;
using Ocelot.Middleware.Multiplexer; using Ocelot.Middleware.Multiplexer;
using static Ocelot.Infrastructure.Wait; using static Ocelot.Infrastructure.Wait;
namespace Ocelot.AcceptanceTests
{
using Butterfly;
using Configuration.Repository; using Configuration.Repository;
using Microsoft.Net.Http.Headers;
using Ocelot.Configuration.Creator; using Ocelot.Configuration.Creator;
using CookieHeaderValue = System.Net.Http.Headers.CookieHeaderValue;
using MediaTypeHeaderValue = System.Net.Http.Headers.MediaTypeHeaderValue; using MediaTypeHeaderValue = System.Net.Http.Headers.MediaTypeHeaderValue;
public class Steps : IDisposable public class Steps : IDisposable
@ -44,7 +39,6 @@ namespace Ocelot.AcceptanceTests
private HttpResponseMessage _response; private HttpResponseMessage _response;
private HttpContent _postContent; private HttpContent _postContent;
private BearerToken _token; private BearerToken _token;
public HttpClient OcelotClient => _ocelotClient;
public string RequestIdKey = "OcRequestId"; public string RequestIdKey = "OcRequestId";
private readonly Random _random; private readonly Random _random;
private IWebHostBuilder _webHostBuilder; private IWebHostBuilder _webHostBuilder;
@ -428,55 +422,6 @@ namespace Ocelot.AcceptanceTests
header.First().ShouldBe(value); header.First().ShouldBe(value);
} }
public void ThenTheResponseBodyHeaderIs(string key, string value)
{
var header = _response.Content.Headers.GetValues(key);
header.First().ShouldBe(value);
}
public void ThenTheTraceHeaderIsSet(string key)
{
var header = _response.Headers.GetValues(key);
header.First().ShouldNotBeNullOrEmpty();
}
public void GivenOcelotIsRunningUsingJsonSerializedCache()
{
_webHostBuilder = new WebHostBuilder();
_webHostBuilder
.ConfigureAppConfiguration((hostingContext, config) =>
{
config.SetBasePath(hostingContext.HostingEnvironment.ContentRootPath);
var env = hostingContext.HostingEnvironment;
config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: false)
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: false);
config.AddJsonFile("ocelot.json", false, false);
config.AddEnvironmentVariables();
})
.ConfigureServices(s =>
{
s.AddOcelot()
.AddCacheManager((x) =>
{
x.WithMicrosoftLogging(log =>
{
log.AddConsole(LogLevel.Debug);
})
.WithJsonSerializer()
.WithHandle(typeof(InMemoryJsonHandle<>));
});
})
.Configure(app =>
{
app.UseOcelot().Wait();
});
_ocelotServer = new TestServer(_webHostBuilder);
_ocelotClient = _ocelotServer.CreateClient();
}
public void GivenOcelotIsRunningUsingConsulToStoreConfig() public void GivenOcelotIsRunningUsingConsulToStoreConfig()
{ {
_webHostBuilder = new WebHostBuilder(); _webHostBuilder = new WebHostBuilder();
@ -505,69 +450,6 @@ namespace Ocelot.AcceptanceTests
_ocelotClient = _ocelotServer.CreateClient(); _ocelotClient = _ocelotServer.CreateClient();
} }
public void GivenOcelotIsRunningUsingConsulToStoreConfigAndJsonSerializedCache()
{
_webHostBuilder = new WebHostBuilder();
_webHostBuilder
.ConfigureAppConfiguration((hostingContext, config) =>
{
config.SetBasePath(hostingContext.HostingEnvironment.ContentRootPath);
var env = hostingContext.HostingEnvironment;
config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: false)
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: false);
config.AddJsonFile("ocelot.json", optional: true, reloadOnChange: false);
config.AddEnvironmentVariables();
})
.ConfigureServices(s =>
{
s.AddOcelot()
.AddCacheManager((x) =>
{
x.WithMicrosoftLogging(log =>
{
log.AddConsole(LogLevel.Debug);
})
.WithJsonSerializer()
.WithHandle(typeof(InMemoryJsonHandle<>));
})
.AddStoreOcelotConfigurationInConsul();
})
.Configure(app =>
{
app.UseOcelot().Wait();
});
_ocelotServer = new TestServer(_webHostBuilder);
_ocelotClient = _ocelotServer.CreateClient();
}
internal void ThenTheResponseShouldBe(FileConfiguration expecteds)
{
var response = JsonConvert.DeserializeObject<FileConfiguration>(_response.Content.ReadAsStringAsync().Result);
response.GlobalConfiguration.RequestIdKey.ShouldBe(expecteds.GlobalConfiguration.RequestIdKey);
response.GlobalConfiguration.ServiceDiscoveryProvider.Host.ShouldBe(expecteds.GlobalConfiguration.ServiceDiscoveryProvider.Host);
response.GlobalConfiguration.ServiceDiscoveryProvider.Port.ShouldBe(expecteds.GlobalConfiguration.ServiceDiscoveryProvider.Port);
for (var i = 0; i < response.ReRoutes.Count; i++)
{
for (var j = 0; j < response.ReRoutes[i].DownstreamHostAndPorts.Count; j++)
{
var result = response.ReRoutes[i].DownstreamHostAndPorts[j];
var expected = expecteds.ReRoutes[i].DownstreamHostAndPorts[j];
result.Host.ShouldBe(expected.Host);
result.Port.ShouldBe(expected.Port);
}
response.ReRoutes[i].DownstreamPathTemplate.ShouldBe(expecteds.ReRoutes[i].DownstreamPathTemplate);
response.ReRoutes[i].DownstreamScheme.ShouldBe(expecteds.ReRoutes[i].DownstreamScheme);
response.ReRoutes[i].UpstreamPathTemplate.ShouldBe(expecteds.ReRoutes[i].UpstreamPathTemplate);
response.ReRoutes[i].UpstreamHttpMethod.ShouldBe(expecteds.ReRoutes[i].UpstreamHttpMethod);
}
}
/// <summary> /// <summary>
/// This is annoying cos it should be in the constructor but we need to set up the file before calling startup so its a step. /// This is annoying cos it should be in the constructor but we need to set up the file before calling startup so its a step.
/// </summary> /// </summary>
@ -590,15 +472,6 @@ namespace Ocelot.AcceptanceTests
.UseConfiguration(configuration) .UseConfiguration(configuration)
.ConfigureServices(s => .ConfigureServices(s =>
{ {
Action<ConfigurationBuilderCachePart> settings = (x) =>
{
x.WithMicrosoftLogging(log =>
{
log.AddConsole(LogLevel.Debug);
})
.WithDictionaryHandle();
};
s.AddOcelot(configuration); s.AddOcelot(configuration);
}) })
.ConfigureLogging(l => .ConfigureLogging(l =>
@ -688,26 +561,6 @@ namespace Ocelot.AcceptanceTests
} }
} }
public void GivenIHaveAnOcelotToken(string adminPath)
{
var tokenUrl = $"{adminPath}/connect/token";
var formData = new List<KeyValuePair<string, string>>
{
new KeyValuePair<string, string>("client_id", "admin"),
new KeyValuePair<string, string>("client_secret", "secret"),
new KeyValuePair<string, string>("scope", "admin"),
new KeyValuePair<string, string>("username", "admin"),
new KeyValuePair<string, string>("password", "admin"),
new KeyValuePair<string, string>("grant_type", "password")
};
var content = new FormUrlEncodedContent(formData);
var response = _ocelotClient.PostAsync(tokenUrl, content).Result;
var responseContent = response.Content.ReadAsStringAsync().Result;
response.EnsureSuccessStatusCode();
_token = JsonConvert.DeserializeObject<BearerToken>(responseContent);
}
public void VerifyIdentiryServerStarted(string url) public void VerifyIdentiryServerStarted(string url)
{ {
using (var httpClient = new HttpClient()) using (var httpClient = new HttpClient())
@ -883,11 +736,6 @@ namespace Ocelot.AcceptanceTests
_response.Headers.GetValues(RequestIdKey).First().ShouldBe(expected); _response.Headers.GetValues(RequestIdKey).First().ShouldBe(expected);
} }
public void ThenTheContentLengthIs(int expected)
{
_response.Content.Headers.ContentLength.ShouldBe(expected);
}
public void WhenIMakeLotsOfDifferentRequestsToTheApiGateway() public void WhenIMakeLotsOfDifferentRequestsToTheApiGateway()
{ {
int numberOfRequests = 100; int numberOfRequests = 100;

View File

@ -5,7 +5,6 @@ using System.Net;
using System.Net.Http; using System.Net.Http;
using System.Net.Http.Headers; using System.Net.Http.Headers;
using System.Security.Claims; using System.Security.Claims;
using CacheManager.Core;
using IdentityServer4.AccessTokenValidation; using IdentityServer4.AccessTokenValidation;
using IdentityServer4.Models; using IdentityServer4.Models;
using IdentityServer4.Test; using IdentityServer4.Test;
@ -557,17 +556,7 @@ namespace Ocelot.IntegrationTests
}) })
.ConfigureServices(x => .ConfigureServices(x =>
{ {
Action<ConfigurationBuilderCachePart> settings = (s) =>
{
s.WithMicrosoftLogging(log =>
{
log.AddConsole(LogLevel.Debug);
})
.WithDictionaryHandle();
};
x.AddOcelot() x.AddOcelot()
.AddCacheManager(settings)
.AddAdministration("/administration", "secret"); .AddAdministration("/administration", "secret");
}) })
.Configure(app => .Configure(app =>
@ -682,10 +671,6 @@ namespace Ocelot.IntegrationTests
.ConfigureServices(x => { .ConfigureServices(x => {
x.AddSingleton(_webHostBuilder); x.AddSingleton(_webHostBuilder);
x.AddOcelot() x.AddOcelot()
.AddCacheManager(c =>
{
c.WithDictionaryHandle();
})
.AddAdministration("/administration", configOptions); .AddAdministration("/administration", configOptions);
}) })
.Configure(app => { .Configure(app => {
@ -714,17 +699,7 @@ namespace Ocelot.IntegrationTests
}) })
.ConfigureServices(x => .ConfigureServices(x =>
{ {
Action<ConfigurationBuilderCachePart> settings = (s) =>
{
s.WithMicrosoftLogging(log =>
{
log.AddConsole(LogLevel.Debug);
})
.WithDictionaryHandle();
};
x.AddOcelot() x.AddOcelot()
.AddCacheManager(settings)
.AddAdministration("/administration", "secret"); .AddAdministration("/administration", "secret");
}) })
.Configure(app => .Configure(app =>
@ -755,10 +730,6 @@ namespace Ocelot.IntegrationTests
.ConfigureServices(x => { .ConfigureServices(x => {
x.AddSingleton(_webHostBuilder); x.AddSingleton(_webHostBuilder);
x.AddOcelot() x.AddOcelot()
.AddCacheManager(c =>
{
c.WithDictionaryHandle();
})
.AddAdministration("/administration", "secret"); .AddAdministration("/administration", "secret");
}) })
.Configure(app => { .Configure(app => {

View File

@ -4,7 +4,6 @@ using System.IO;
using System.Net.Http; using System.Net.Http;
using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.DependencyInjection;
using Newtonsoft.Json; using Newtonsoft.Json;
using Ocelot.Configuration.File; using Ocelot.Configuration.File;
using Shouldly; using Shouldly;
@ -13,7 +12,6 @@ using Xunit;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using CacheManager.Core;
using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Ocelot.DependencyInjection; using Ocelot.DependencyInjection;
@ -113,17 +111,7 @@ namespace Ocelot.IntegrationTests
}) })
.ConfigureServices(x => .ConfigureServices(x =>
{ {
Action<ConfigurationBuilderCachePart> settings = (s) =>
{
s.WithMicrosoftLogging(log =>
{
log.AddConsole(LogLevel.Debug);
})
.WithDictionaryHandle();
};
x.AddOcelot() x.AddOcelot()
.AddCacheManager(settings)
.AddAdministration("/administration", "secret"); .AddAdministration("/administration", "secret");
}) })
.Configure(app => .Configure(app =>

View File

@ -1,5 +1,6 @@
using Ocelot.Configuration; using Xunit;
using Ocelot.Middleware;
[assembly: CollectionBehavior(DisableTestParallelization = true)]
namespace Ocelot.UnitTests.Authentication namespace Ocelot.UnitTests.Authentication
{ {
@ -15,14 +16,16 @@ namespace Ocelot.UnitTests.Authentication
using Shouldly; using Shouldly;
using TestStack.BDDfy; using TestStack.BDDfy;
using Xunit; using Xunit;
using Ocelot.Configuration;
using Ocelot.Middleware;
public class AuthenticationMiddlewareTests public class AuthenticationMiddlewareTests
{ {
private AuthenticationMiddleware _middleware; private AuthenticationMiddleware _middleware;
private Mock<IOcelotLoggerFactory> _factory; private readonly Mock<IOcelotLoggerFactory> _factory;
private Mock<IOcelotLogger> _logger; private Mock<IOcelotLogger> _logger;
private OcelotRequestDelegate _next; private OcelotRequestDelegate _next;
private DownstreamContext _downstreamContext; private readonly DownstreamContext _downstreamContext;
public AuthenticationMiddlewareTests() public AuthenticationMiddlewareTests()
{ {

View File

@ -1,103 +0,0 @@
using System;
using CacheManager.Core;
using Moq;
using Ocelot.Cache;
using Shouldly;
using TestStack.BDDfy;
using Xunit;
namespace Ocelot.UnitTests.Cache
{
public class CacheManagerCacheTests
{
private OcelotCacheManagerCache<string> _ocelotOcelotCacheManager;
private Mock<ICacheManager<string>> _mockCacheManager;
private string _key;
private string _value;
private string _resultGet;
private TimeSpan _ttlSeconds;
private string _region;
public CacheManagerCacheTests()
{
_mockCacheManager = new Mock<ICacheManager<string>>();
_ocelotOcelotCacheManager = new OcelotCacheManagerCache<string>(_mockCacheManager.Object);
}
[Fact]
public void should_get_from_cache()
{
this.Given(x => x.GivenTheFollowingIsCached("someKey", "someRegion", "someValue"))
.When(x => x.WhenIGetFromTheCache())
.Then(x => x.ThenTheResultIs("someValue"))
.BDDfy();
}
[Fact]
public void should_add_to_cache()
{
this.When(x => x.WhenIAddToTheCache("someKey", "someValue", TimeSpan.FromSeconds(1)))
.Then(x => x.ThenTheCacheIsCalledCorrectly())
.BDDfy();
}
[Fact]
public void should_delete_key_from_cache()
{
this.Given(_ => GivenTheFollowingRegion("fookey"))
.When(_ => WhenIDeleteTheRegion("fookey"))
.Then(_ => ThenTheRegionIsDeleted("fookey"))
.BDDfy();
}
private void WhenIDeleteTheRegion(string region)
{
_ocelotOcelotCacheManager.ClearRegion(region);
}
private void ThenTheRegionIsDeleted(string region)
{
_mockCacheManager
.Verify(x => x.ClearRegion(region), Times.Once);
}
private void GivenTheFollowingRegion(string key)
{
_ocelotOcelotCacheManager.Add(key, "doesnt matter", TimeSpan.FromSeconds(10), "region");
}
private void WhenIAddToTheCache(string key, string value, TimeSpan ttlSeconds)
{
_key = key;
_value = value;
_ttlSeconds = ttlSeconds;
_ocelotOcelotCacheManager.Add(_key, _value, _ttlSeconds, "region");
}
private void ThenTheCacheIsCalledCorrectly()
{
_mockCacheManager
.Verify(x => x.Add(It.IsAny<CacheItem<string>>()), Times.Once);
}
private void ThenTheResultIs(string expected)
{
_resultGet.ShouldBe(expected);
}
private void WhenIGetFromTheCache()
{
_resultGet = _ocelotOcelotCacheManager.Get(_key, _region);
}
private void GivenTheFollowingIsCached(string key, string region, string value)
{
_key = key;
_value = value;
_region = region;
_mockCacheManager
.Setup(x => x.Get<string>(It.IsAny<string>(), It.IsAny<string>()))
.Returns(value);
}
}
}

View File

@ -1,95 +0,0 @@
namespace Ocelot.UnitTests.Cache
{
using System.Linq;
using System.Net;
using System.Net.Http.Headers;
using CacheManager.Core;
using Shouldly;
using System.Collections.Generic;
using System.Net.Http;
using System.Threading.Tasks;
using Moq;
using Ocelot.Cache;
using Ocelot.Cache.Middleware;
using Ocelot.Configuration;
using Ocelot.Configuration.Builder;
using Ocelot.Logging;
using Ocelot.Middleware;
using TestStack.BDDfy;
using Xunit;
using Microsoft.AspNetCore.Http;
using Ocelot.Middleware.Multiplexer;
public class OutputCacheMiddlewareRealCacheTests
{
private readonly IOcelotCache<CachedResponse> _cacheManager;
private readonly OutputCacheMiddleware _middleware;
private readonly DownstreamContext _downstreamContext;
private OcelotRequestDelegate _next;
private Mock<IOcelotLoggerFactory> _loggerFactory;
private IRegionCreator _regionCreator;
private Mock<IOcelotLogger> _logger;
public OutputCacheMiddlewareRealCacheTests()
{
_loggerFactory = new Mock<IOcelotLoggerFactory>();
_logger = new Mock<IOcelotLogger>();
_loggerFactory.Setup(x => x.CreateLogger<OutputCacheMiddleware>()).Returns(_logger.Object);
_regionCreator = new RegionCreator();
var cacheManagerOutputCache = CacheFactory.Build<CachedResponse>("OcelotOutputCache", x =>
{
x.WithDictionaryHandle();
});
_cacheManager = new OcelotCacheManagerCache<CachedResponse>(cacheManagerOutputCache);
_downstreamContext = new DownstreamContext(new DefaultHttpContext());
_downstreamContext.DownstreamRequest = new Ocelot.Request.Middleware.DownstreamRequest(new HttpRequestMessage(HttpMethod.Get, "https://some.url/blah?abcd=123"));
_next = context => Task.CompletedTask;
_middleware = new OutputCacheMiddleware(_next, _loggerFactory.Object, _cacheManager, _regionCreator);
}
[Fact]
public void should_cache_content_headers()
{
var content = new StringContent("{\"Test\": 1}")
{
Headers = { ContentType = new MediaTypeHeaderValue("application/json")}
};
var response = new DownstreamResponse(content, HttpStatusCode.OK, new List<KeyValuePair<string, IEnumerable<string>>>());
this.Given(x => x.GivenResponseIsNotCached(response))
.And(x => x.GivenTheDownstreamRouteIs())
.When(x => x.WhenICallTheMiddleware())
.Then(x => x.ThenTheContentTypeHeaderIsCached())
.BDDfy();
}
private void WhenICallTheMiddleware()
{
_middleware.Invoke(_downstreamContext).GetAwaiter().GetResult();
}
private void ThenTheContentTypeHeaderIsCached()
{
var result = _cacheManager.Get("GET-https://some.url/blah?abcd=123", "kanken");
var header = result.ContentHeaders["Content-Type"];
header.First().ShouldBe("application/json");
}
private void GivenResponseIsNotCached(DownstreamResponse response)
{
_downstreamContext.DownstreamResponse = response;
}
private void GivenTheDownstreamRouteIs()
{
var reRoute = new DownstreamReRouteBuilder()
.WithIsCached(true)
.WithCacheOptions(new CacheOptions(100, "kanken"))
.WithUpstreamHttpMethod(new List<string> { "Get" })
.Build();
_downstreamContext.DownstreamReRoute = reRoute;
}
}
}

View File

@ -16,24 +16,22 @@
using TestStack.BDDfy; using TestStack.BDDfy;
using Xunit; using Xunit;
using System.Net; using System.Net;
using Microsoft.Extensions.DependencyInjection;
using Ocelot.Middleware; using Ocelot.Middleware;
using Ocelot.Middleware.Multiplexer;
public class OutputCacheMiddlewareTests public class OutputCacheMiddlewareTests
{ {
private readonly Mock<IOcelotCache<CachedResponse>> _cacheManager; private readonly Mock<IOcelotCache<CachedResponse>> _cache;
private readonly Mock<IOcelotLoggerFactory> _loggerFactory; private readonly Mock<IOcelotLoggerFactory> _loggerFactory;
private Mock<IOcelotLogger> _logger; private Mock<IOcelotLogger> _logger;
private OutputCacheMiddleware _middleware; private OutputCacheMiddleware _middleware;
private readonly DownstreamContext _downstreamContext; private readonly DownstreamContext _downstreamContext;
private readonly OcelotRequestDelegate _next; private readonly OcelotRequestDelegate _next;
private CachedResponse _response; private CachedResponse _response;
private readonly IRegionCreator _regionCreator;
public OutputCacheMiddlewareTests() public OutputCacheMiddlewareTests()
{ {
_cacheManager = new Mock<IOcelotCache<CachedResponse>>(); _cache = new Mock<IOcelotCache<CachedResponse>>();
_regionCreator = new RegionCreator();
_downstreamContext = new DownstreamContext(new DefaultHttpContext()); _downstreamContext = new DownstreamContext(new DefaultHttpContext());
_loggerFactory = new Mock<IOcelotLoggerFactory>(); _loggerFactory = new Mock<IOcelotLoggerFactory>();
_logger = new Mock<IOcelotLogger>(); _logger = new Mock<IOcelotLogger>();
@ -91,14 +89,14 @@
private void WhenICallTheMiddleware() private void WhenICallTheMiddleware()
{ {
_middleware = new OutputCacheMiddleware(_next, _loggerFactory.Object, _cacheManager.Object, _regionCreator); _middleware = new OutputCacheMiddleware(_next, _loggerFactory.Object, _cache.Object);
_middleware.Invoke(_downstreamContext).GetAwaiter().GetResult(); _middleware.Invoke(_downstreamContext).GetAwaiter().GetResult();
} }
private void GivenThereIsACachedResponse(CachedResponse response) private void GivenThereIsACachedResponse(CachedResponse response)
{ {
_response = response; _response = response;
_cacheManager _cache
.Setup(x => x.Get(It.IsAny<string>(), It.IsAny<string>())) .Setup(x => x.Get(It.IsAny<string>(), It.IsAny<string>()))
.Returns(_response); .Returns(_response);
} }
@ -127,13 +125,13 @@
private void ThenTheCacheGetIsCalledCorrectly() private void ThenTheCacheGetIsCalledCorrectly()
{ {
_cacheManager _cache
.Verify(x => x.Get(It.IsAny<string>(), It.IsAny<string>()), Times.Once); .Verify(x => x.Get(It.IsAny<string>(), It.IsAny<string>()), Times.Once);
} }
private void ThenTheCacheAddIsCalledCorrectly() private void ThenTheCacheAddIsCalledCorrectly()
{ {
_cacheManager _cache
.Verify(x => x.Add(It.IsAny<string>(), It.IsAny<CachedResponse>(), It.IsAny<TimeSpan>(), It.IsAny<string>()), Times.Once); .Verify(x => x.Add(It.IsAny<string>(), It.IsAny<CachedResponse>(), It.IsAny<TimeSpan>(), It.IsAny<string>()), Times.Once);
} }
} }

View File

@ -2,7 +2,6 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Net.Http; using System.Net.Http;
using CacheManager.Core;
using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Hosting.Internal; using Microsoft.AspNetCore.Hosting.Internal;
using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Configuration;
@ -81,16 +80,6 @@ namespace Ocelot.UnitTests.DependencyInjection
.BDDfy(); .BDDfy();
} }
[Fact]
public void should_set_up_cache_manager()
{
this.Given(x => WhenISetUpOcelotServices())
.When(x => WhenISetUpCacheManager())
.Then(x => ThenAnExceptionIsntThrown())
.And(x => OnlyOneVersionOfEachCacheIsRegistered())
.BDDfy();
}
[Fact] [Fact]
public void should_set_up_consul() public void should_set_up_consul()
{ {
@ -282,24 +271,6 @@ namespace Ocelot.UnitTests.DependencyInjection
first.ShouldBe(second); first.ShouldBe(second);
} }
private void OnlyOneVersionOfEachCacheIsRegistered()
{
var outputCache = _services.Single(x => x.ServiceType == typeof(IOcelotCache<CachedResponse>));
var outputCacheManager = _services.Single(x => x.ServiceType == typeof(ICacheManager<CachedResponse>));
var instance = (ICacheManager<CachedResponse>)outputCacheManager.ImplementationInstance;
var ocelotConfigCache = _services.Single(x => x.ServiceType == typeof(IOcelotCache<IInternalConfiguration>));
var ocelotConfigCacheManager = _services.Single(x => x.ServiceType == typeof(ICacheManager<IInternalConfiguration>));
var fileConfigCache = _services.Single(x => x.ServiceType == typeof(IOcelotCache<FileConfiguration>));
var fileConfigCacheManager = _services.Single(x => x.ServiceType == typeof(ICacheManager<FileConfiguration>));
instance.Configuration.MaxRetries.ShouldBe(_maxRetries);
outputCache.ShouldNotBeNull();
ocelotConfigCache.ShouldNotBeNull();
ocelotConfigCacheManager.ShouldNotBeNull();
fileConfigCache.ShouldNotBeNull();
fileConfigCacheManager.ShouldNotBeNull();
}
private void WhenISetUpConsul() private void WhenISetUpConsul()
{ {
try try
@ -365,21 +336,6 @@ namespace Ocelot.UnitTests.DependencyInjection
} }
} }
private void WhenISetUpCacheManager()
{
try
{
_ocelotBuilder.AddCacheManager(x => {
x.WithMaxRetries(_maxRetries);
x.WithDictionaryHandle();
});
}
catch (Exception e)
{
_ex = e;
}
}
private void WhenIAccessLoggerFactory() private void WhenIAccessLoggerFactory()
{ {
try try

View File

@ -1,7 +1,9 @@
namespace Ocelot.UnitTests.Middleware namespace Ocelot.UnitTests.Middleware
{ {
using System;
using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Ocelot.Cache;
using Ocelot.DependencyInjection; using Ocelot.DependencyInjection;
using Ocelot.DownstreamRouteFinder.Middleware; using Ocelot.DownstreamRouteFinder.Middleware;
using Ocelot.DownstreamUrlCreator.Middleware; using Ocelot.DownstreamUrlCreator.Middleware;
@ -40,7 +42,6 @@ namespace Ocelot.UnitTests.Middleware
.BDDfy(); .BDDfy();
} }
private void ThenThePipelineIsBuilt() private void ThenThePipelineIsBuilt()
{ {
_handlers.ShouldNotBeNull(); _handlers.ShouldNotBeNull();
@ -67,7 +68,6 @@ namespace Ocelot.UnitTests.Middleware
_handlers = _builder.BuildOcelotPipeline(new OcelotPipelineConfiguration()); _handlers = _builder.BuildOcelotPipeline(new OcelotPipelineConfiguration());
} }
private void GivenTheDepedenciesAreSetUp() private void GivenTheDepedenciesAreSetUp()
{ {
IConfigurationBuilder test = new ConfigurationBuilder(); IConfigurationBuilder test = new ConfigurationBuilder();