mirror of
https://github.com/nsnail/Ocelot.git
synced 2025-04-22 06:22:50 +08:00
decided to stick a basic cache in for downstream route creator, can make fancy if required (#359)
This commit is contained in:
parent
061a90f1dd
commit
a55c75efdc
@ -1,5 +1,6 @@
|
|||||||
namespace Ocelot.DownstreamRouteFinder.Finder
|
namespace Ocelot.DownstreamRouteFinder.Finder
|
||||||
{
|
{
|
||||||
|
using System.Collections.Concurrent;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using Configuration;
|
using Configuration;
|
||||||
using Configuration.Builder;
|
using Configuration.Builder;
|
||||||
@ -12,10 +13,12 @@
|
|||||||
public class DownstreamRouteCreator : IDownstreamRouteProvider
|
public class DownstreamRouteCreator : IDownstreamRouteProvider
|
||||||
{
|
{
|
||||||
private readonly IQoSOptionsCreator _qoSOptionsCreator;
|
private readonly IQoSOptionsCreator _qoSOptionsCreator;
|
||||||
|
private readonly ConcurrentDictionary<string, OkResponse<DownstreamRoute>> _cache;
|
||||||
|
|
||||||
public DownstreamRouteCreator(IQoSOptionsCreator qoSOptionsCreator)
|
public DownstreamRouteCreator(IQoSOptionsCreator qoSOptionsCreator)
|
||||||
{
|
{
|
||||||
_qoSOptionsCreator = qoSOptionsCreator;
|
_qoSOptionsCreator = qoSOptionsCreator;
|
||||||
|
_cache = new ConcurrentDictionary<string, OkResponse<DownstreamRoute>>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Response<DownstreamRoute> Get(string upstreamUrlPath, string upstreamHttpMethod, IInternalConfiguration configuration, string upstreamHost)
|
public Response<DownstreamRoute> Get(string upstreamUrlPath, string upstreamHttpMethod, IInternalConfiguration configuration, string upstreamHost)
|
||||||
@ -33,6 +36,11 @@
|
|||||||
|
|
||||||
var loadBalancerKey = CreateLoadBalancerKey(downstreamPathForKeys, upstreamHttpMethod, configuration.LoadBalancerOptions);
|
var loadBalancerKey = CreateLoadBalancerKey(downstreamPathForKeys, upstreamHttpMethod, configuration.LoadBalancerOptions);
|
||||||
|
|
||||||
|
if(_cache.TryGetValue(loadBalancerKey, out var downstreamRoute))
|
||||||
|
{
|
||||||
|
return downstreamRoute;
|
||||||
|
}
|
||||||
|
|
||||||
var qosOptions = _qoSOptionsCreator.Create(configuration.QoSOptions, downstreamPathForKeys, new []{ upstreamHttpMethod });
|
var qosOptions = _qoSOptionsCreator.Create(configuration.QoSOptions, downstreamPathForKeys, new []{ upstreamHttpMethod });
|
||||||
|
|
||||||
var downstreamReRoute = new DownstreamReRouteBuilder()
|
var downstreamReRoute = new DownstreamReRouteBuilder()
|
||||||
@ -51,7 +59,11 @@
|
|||||||
.WithUpstreamHttpMethod(new List<string>(){ upstreamHttpMethod })
|
.WithUpstreamHttpMethod(new List<string>(){ upstreamHttpMethod })
|
||||||
.Build();
|
.Build();
|
||||||
|
|
||||||
return new OkResponse<DownstreamRoute>(new DownstreamRoute(new List<PlaceholderNameAndValue>(), reRoute));
|
downstreamRoute = new OkResponse<DownstreamRoute>(new DownstreamRoute(new List<PlaceholderNameAndValue>(), reRoute));
|
||||||
|
|
||||||
|
_cache.AddOrUpdate(loadBalancerKey, downstreamRoute, (x, y) => downstreamRoute);
|
||||||
|
|
||||||
|
return downstreamRoute;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static string RemoveQueryString(string downstreamPath)
|
private static string RemoveQueryString(string downstreamPath)
|
||||||
@ -67,12 +79,23 @@
|
|||||||
|
|
||||||
private static string GetDownstreamPath(string upstreamUrlPath)
|
private static string GetDownstreamPath(string upstreamUrlPath)
|
||||||
{
|
{
|
||||||
|
if(upstreamUrlPath.IndexOf('/', 1) == -1)
|
||||||
|
{
|
||||||
|
return "/";
|
||||||
|
}
|
||||||
|
|
||||||
return upstreamUrlPath
|
return upstreamUrlPath
|
||||||
.Substring(upstreamUrlPath.IndexOf('/', 1));
|
.Substring(upstreamUrlPath.IndexOf('/', 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static string GetServiceName(string upstreamUrlPath)
|
private static string GetServiceName(string upstreamUrlPath)
|
||||||
{
|
{
|
||||||
|
if(upstreamUrlPath.IndexOf('/', 1) == -1)
|
||||||
|
{
|
||||||
|
return upstreamUrlPath
|
||||||
|
.Substring(1);
|
||||||
|
}
|
||||||
|
|
||||||
return upstreamUrlPath
|
return upstreamUrlPath
|
||||||
.Substring(1, upstreamUrlPath.IndexOf('/', 1))
|
.Substring(1, upstreamUrlPath.IndexOf('/', 1))
|
||||||
.TrimEnd('/');
|
.TrimEnd('/');
|
||||||
|
@ -6,6 +6,7 @@ using System.Net.Http;
|
|||||||
|
|
||||||
namespace Ocelot.UnitTests.DownstreamRouteFinder
|
namespace Ocelot.UnitTests.DownstreamRouteFinder
|
||||||
{
|
{
|
||||||
|
using System;
|
||||||
using Moq;
|
using Moq;
|
||||||
using Ocelot.Configuration.Builder;
|
using Ocelot.Configuration.Builder;
|
||||||
using Ocelot.Configuration.Creator;
|
using Ocelot.Configuration.Creator;
|
||||||
@ -26,6 +27,7 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
|
|||||||
private string _upstreamHttpMethod;
|
private string _upstreamHttpMethod;
|
||||||
private IInternalConfiguration _configuration;
|
private IInternalConfiguration _configuration;
|
||||||
private Mock<IQoSOptionsCreator> _qosOptionsCreator;
|
private Mock<IQoSOptionsCreator> _qosOptionsCreator;
|
||||||
|
private Response<DownstreamRoute> _resultTwo;
|
||||||
|
|
||||||
public DownstreamRouteCreatorTests()
|
public DownstreamRouteCreatorTests()
|
||||||
{
|
{
|
||||||
@ -50,6 +52,32 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
|
|||||||
.BDDfy();
|
.BDDfy();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void should_cache_downstream_route()
|
||||||
|
{
|
||||||
|
var configuration = new InternalConfiguration(null, "doesnt matter", null, "doesnt matter", _loadBalancerOptions, "http", _qoSOptions, _handlerOptions);
|
||||||
|
|
||||||
|
this.Given(_ => GivenTheConfiguration(configuration, "/geoffisthebest/"))
|
||||||
|
.When(_ => WhenICreate())
|
||||||
|
.And(_ => GivenTheConfiguration(configuration, "/geoffisthebest/"))
|
||||||
|
.When(_ => WhenICreateAgain())
|
||||||
|
.Then(_ => ThenTheDownstreamRoutesAreTheSameReference())
|
||||||
|
.BDDfy();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void should_not_cache_downstream_route()
|
||||||
|
{
|
||||||
|
var configuration = new InternalConfiguration(null, "doesnt matter", null, "doesnt matter", _loadBalancerOptions, "http", _qoSOptions, _handlerOptions);
|
||||||
|
|
||||||
|
this.Given(_ => GivenTheConfiguration(configuration, "/geoffistheworst/"))
|
||||||
|
.When(_ => WhenICreate())
|
||||||
|
.And(_ => GivenTheConfiguration(configuration, "/geoffisthebest/"))
|
||||||
|
.When(_ => WhenICreateAgain())
|
||||||
|
.Then(_ => ThenTheDownstreamRoutesAreTheNotSameReference())
|
||||||
|
.BDDfy();
|
||||||
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void should_create_downstream_route_with_no_path()
|
public void should_create_downstream_route_with_no_path()
|
||||||
{
|
{
|
||||||
@ -62,6 +90,30 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
|
|||||||
.BDDfy();
|
.BDDfy();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void should_create_downstream_route_with_only_first_segment_no_traling_slash()
|
||||||
|
{
|
||||||
|
var upstreamUrlPath = "/auth";
|
||||||
|
var configuration = new InternalConfiguration(null, "doesnt matter", null, "doesnt matter", _loadBalancerOptions, "http", _qoSOptions, _handlerOptions);
|
||||||
|
|
||||||
|
this.Given(_ => GivenTheConfiguration(configuration, upstreamUrlPath))
|
||||||
|
.When(_ => WhenICreate())
|
||||||
|
.Then(_ => ThenTheDownstreamPathIsForwardSlash())
|
||||||
|
.BDDfy();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void should_create_downstream_route_with_segments_no_traling_slash()
|
||||||
|
{
|
||||||
|
var upstreamUrlPath = "/auth/test";
|
||||||
|
var configuration = new InternalConfiguration(null, "doesnt matter", null, "doesnt matter", _loadBalancerOptions, "http", _qoSOptions, _handlerOptions);
|
||||||
|
|
||||||
|
this.Given(_ => GivenTheConfiguration(configuration, upstreamUrlPath))
|
||||||
|
.When(_ => WhenICreate())
|
||||||
|
.Then(_ => ThenThePathDoesNotHaveTrailingSlash())
|
||||||
|
.BDDfy();
|
||||||
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void should_create_downstream_route_and_remove_query_string()
|
public void should_create_downstream_route_and_remove_query_string()
|
||||||
{
|
{
|
||||||
@ -143,6 +195,13 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
|
|||||||
_result.Data.ReRoute.DownstreamReRoute[0].LoadBalancerKey.ShouldBe("/auth/|GET");
|
_result.Data.ReRoute.DownstreamReRoute[0].LoadBalancerKey.ShouldBe("/auth/|GET");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void ThenThePathDoesNotHaveTrailingSlash()
|
||||||
|
{
|
||||||
|
_result.Data.ReRoute.DownstreamReRoute[0].DownstreamPathTemplate.Value.ShouldBe("/test");
|
||||||
|
_result.Data.ReRoute.DownstreamReRoute[0].ServiceName.ShouldBe("auth");
|
||||||
|
_result.Data.ReRoute.DownstreamReRoute[0].LoadBalancerKey.ShouldBe("/auth/test|GET");
|
||||||
|
}
|
||||||
|
|
||||||
private void ThenTheQueryStringIsRemoved()
|
private void ThenTheQueryStringIsRemoved()
|
||||||
{
|
{
|
||||||
_result.Data.ReRoute.DownstreamReRoute[0].DownstreamPathTemplate.Value.ShouldBe("/test");
|
_result.Data.ReRoute.DownstreamReRoute[0].DownstreamPathTemplate.Value.ShouldBe("/test");
|
||||||
@ -190,5 +249,20 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
|
|||||||
{
|
{
|
||||||
_result = _creator.Get(_upstreamUrlPath, _upstreamHttpMethod, _configuration, _upstreamHost);
|
_result = _creator.Get(_upstreamUrlPath, _upstreamHttpMethod, _configuration, _upstreamHost);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void WhenICreateAgain()
|
||||||
|
{
|
||||||
|
_resultTwo = _creator.Get(_upstreamUrlPath, _upstreamHttpMethod, _configuration, _upstreamHost);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ThenTheDownstreamRoutesAreTheSameReference()
|
||||||
|
{
|
||||||
|
_result.ShouldBe(_resultTwo);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ThenTheDownstreamRoutesAreTheNotSameReference()
|
||||||
|
{
|
||||||
|
_result.ShouldNotBe(_resultTwo);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user