diff --git a/docs/features/routing.rst b/docs/features/routing.rst index ed0d967e..0359d917 100644 --- a/docs/features/routing.rst +++ b/docs/features/routing.rst @@ -62,4 +62,33 @@ In order to change this you can specify on a per ReRoute basis the following set This means that when Ocelot tries to match the incoming upstream url with an upstream template the evaluation will be case sensitive. This setting defaults to false so only set it if you want -the ReRoute to be case sensitive is my advice! \ No newline at end of file +the ReRoute to be case sensitive is my advice! + +Catch All +^^^^^^^^^ + +Ocelot's routing also supports a catch all style routing where the user can specify that they want to match all traffic if you set up your config like below the request will be proxied straight through (it doesnt have to be url any placeholder name will work). + +.. code-block:: json + + { + "DownstreamPathTemplate": "/{url}", + "DownstreamScheme": "https", + "DownstreamPort": 80, + "DownstreamHost" "localhost", + "UpstreamPathTemplate": "/{url}", + "UpstreamHttpMethod": [ "Get" ] + } + +The catch all has a lower priority than any other ReRoute. If you also have the ReRoute below in your config then Ocelot would match it before the catch all. + +.. code-block:: json + + { + "DownstreamPathTemplate": "/", + "DownstreamScheme": "https", + "DownstreamPort": 80, + "DownstreamHost" "10.0.10.1", + "UpstreamPathTemplate": "/", + "UpstreamHttpMethod": [ "Get" ] + } \ No newline at end of file diff --git a/src/Ocelot/Configuration/Builder/ReRouteBuilder.cs b/src/Ocelot/Configuration/Builder/ReRouteBuilder.cs index 1a8877e7..cc5a61aa 100644 --- a/src/Ocelot/Configuration/Builder/ReRouteBuilder.cs +++ b/src/Ocelot/Configuration/Builder/ReRouteBuilder.cs @@ -2,6 +2,7 @@ using System.Net.Http; using Ocelot.Values; using System.Linq; +using Ocelot.Configuration.Creator; namespace Ocelot.Configuration.Builder { @@ -11,7 +12,7 @@ namespace Ocelot.Configuration.Builder private string _loadBalancerKey; private string _downstreamPathTemplate; private string _upstreamTemplate; - private string _upstreamTemplatePattern; + private UpstreamPathTemplate _upstreamTemplatePattern; private List _upstreamHttpMethod; private bool _isAuthenticated; private List _configHeaderExtractorProperties; @@ -65,7 +66,7 @@ namespace Ocelot.Configuration.Builder return this; } - public ReRouteBuilder WithUpstreamTemplatePattern(string input) + public ReRouteBuilder WithUpstreamTemplatePattern(UpstreamPathTemplate input) { _upstreamTemplatePattern = input; return this; diff --git a/src/Ocelot/Configuration/Creator/IUpstreamTemplatePatternCreator.cs b/src/Ocelot/Configuration/Creator/IUpstreamTemplatePatternCreator.cs index ae62c47a..14de619d 100644 --- a/src/Ocelot/Configuration/Creator/IUpstreamTemplatePatternCreator.cs +++ b/src/Ocelot/Configuration/Creator/IUpstreamTemplatePatternCreator.cs @@ -1,9 +1,10 @@ using Ocelot.Configuration.File; +using Ocelot.Values; namespace Ocelot.Configuration.Creator { public interface IUpstreamTemplatePatternCreator { - string Create(FileReRoute reRoute); + UpstreamPathTemplate Create(FileReRoute reRoute); } } \ No newline at end of file diff --git a/src/Ocelot/Configuration/Creator/UpstreamTemplatePatternCreator.cs b/src/Ocelot/Configuration/Creator/UpstreamTemplatePatternCreator.cs index a45d2864..7816d118 100644 --- a/src/Ocelot/Configuration/Creator/UpstreamTemplatePatternCreator.cs +++ b/src/Ocelot/Configuration/Creator/UpstreamTemplatePatternCreator.cs @@ -1,5 +1,6 @@ using System.Collections.Generic; using Ocelot.Configuration.File; +using Ocelot.Values; namespace Ocelot.Configuration.Creator { @@ -11,7 +12,7 @@ namespace Ocelot.Configuration.Creator private const string RegExForwardSlashOnly = "^/$"; private const string RegExForwardSlashAndOnePlaceHolder = "^/.*"; - public string Create(FileReRoute reRoute) + public UpstreamPathTemplate Create(FileReRoute reRoute) { var upstreamTemplate = reRoute.UpstreamPathTemplate; @@ -26,9 +27,10 @@ namespace Ocelot.Configuration.Creator var placeHolderName = upstreamTemplate.Substring(i, difference); placeholders.Add(placeHolderName); + //hack to handle /{url} case if(ForwardSlashAndOnePlaceHolder(upstreamTemplate, placeholders, postitionOfPlaceHolderClosingBracket)) { - return RegExForwardSlashAndOnePlaceHolder; + return new UpstreamPathTemplate(RegExForwardSlashAndOnePlaceHolder, 0); } } } @@ -40,7 +42,7 @@ namespace Ocelot.Configuration.Creator if (upstreamTemplate == "/") { - return RegExForwardSlashOnly; + return new UpstreamPathTemplate(RegExForwardSlashOnly, 1); } if(upstreamTemplate.EndsWith("/")) @@ -52,7 +54,7 @@ namespace Ocelot.Configuration.Creator ? $"^{upstreamTemplate}{RegExMatchEndString}" : $"^{RegExIgnoreCase}{upstreamTemplate}{RegExMatchEndString}"; - return route; + return new UpstreamPathTemplate(route, 1); } private bool ForwardSlashAndOnePlaceHolder(string upstreamTemplate, List placeholders, int postitionOfPlaceHolderClosingBracket) diff --git a/src/Ocelot/Configuration/ReRoute.cs b/src/Ocelot/Configuration/ReRoute.cs index 0d373425..18e068aa 100644 --- a/src/Ocelot/Configuration/ReRoute.cs +++ b/src/Ocelot/Configuration/ReRoute.cs @@ -1,5 +1,6 @@ using System.Collections.Generic; using System.Net.Http; +using Ocelot.Configuration.Creator; using Ocelot.Values; namespace Ocelot.Configuration @@ -9,7 +10,7 @@ namespace Ocelot.Configuration public ReRoute(PathTemplate downstreamPathTemplate, PathTemplate upstreamPathTemplate, List upstreamHttpMethod, - string upstreamTemplatePattern, + UpstreamPathTemplate upstreamTemplatePattern, bool isAuthenticated, AuthenticationOptions authenticationOptions, List claimsToHeaders, @@ -67,7 +68,7 @@ namespace Ocelot.Configuration public string ReRouteKey {get;private set;} public PathTemplate DownstreamPathTemplate { get; private set; } public PathTemplate UpstreamPathTemplate { get; private set; } - public string UpstreamTemplatePattern { get; private set; } + public UpstreamPathTemplate UpstreamTemplatePattern { get; private set; } public List UpstreamHttpMethod { get; private set; } public bool IsAuthenticated { get; private set; } public bool IsAuthorised { get; private set; } diff --git a/src/Ocelot/DependencyInjection/OcelotBuilder.cs b/src/Ocelot/DependencyInjection/OcelotBuilder.cs index b8ebc8a2..c5317a51 100644 --- a/src/Ocelot/DependencyInjection/OcelotBuilder.cs +++ b/src/Ocelot/DependencyInjection/OcelotBuilder.cs @@ -108,7 +108,7 @@ namespace Ocelot.DependencyInjection _services.TryAddSingleton(); _services.TryAddSingleton(); _services.TryAddSingleton(); - _services.TryAddSingleton(); + _services.TryAddSingleton(); _services.TryAddSingleton(); _services.TryAddSingleton(); _services.TryAddSingleton(); diff --git a/src/Ocelot/DownstreamRouteFinder/DownstreamRoute.cs b/src/Ocelot/DownstreamRouteFinder/DownstreamRoute.cs index d4a117c0..7a4a66ea 100644 --- a/src/Ocelot/DownstreamRouteFinder/DownstreamRoute.cs +++ b/src/Ocelot/DownstreamRouteFinder/DownstreamRoute.cs @@ -6,12 +6,12 @@ namespace Ocelot.DownstreamRouteFinder { public class DownstreamRoute { - public DownstreamRoute(List templatePlaceholderNameAndValues, ReRoute reRoute) + public DownstreamRoute(List templatePlaceholderNameAndValues, ReRoute reRoute) { TemplatePlaceholderNameAndValues = templatePlaceholderNameAndValues; ReRoute = reRoute; } - public List TemplatePlaceholderNameAndValues { get; private set; } + public List TemplatePlaceholderNameAndValues { get; private set; } public ReRoute ReRoute { get; private set; } } } \ No newline at end of file diff --git a/src/Ocelot/DownstreamRouteFinder/Finder/DownstreamRouteFinder.cs b/src/Ocelot/DownstreamRouteFinder/Finder/DownstreamRouteFinder.cs index 2c3077cc..643a4464 100644 --- a/src/Ocelot/DownstreamRouteFinder/Finder/DownstreamRouteFinder.cs +++ b/src/Ocelot/DownstreamRouteFinder/Finder/DownstreamRouteFinder.cs @@ -13,34 +13,30 @@ namespace Ocelot.DownstreamRouteFinder.Finder public class DownstreamRouteFinder : IDownstreamRouteFinder { private readonly IUrlPathToUrlTemplateMatcher _urlMatcher; - private readonly IUrlPathPlaceholderNameAndValueFinder _urlPathPlaceholderNameAndValueFinder; + private readonly IPlaceholderNameAndValueFinder __placeholderNameAndValueFinder; - public DownstreamRouteFinder(IUrlPathToUrlTemplateMatcher urlMatcher, IUrlPathPlaceholderNameAndValueFinder urlPathPlaceholderNameAndValueFinder) + public DownstreamRouteFinder(IUrlPathToUrlTemplateMatcher urlMatcher, IPlaceholderNameAndValueFinder urlPathPlaceholderNameAndValueFinder) { _urlMatcher = urlMatcher; - _urlPathPlaceholderNameAndValueFinder = urlPathPlaceholderNameAndValueFinder; + __placeholderNameAndValueFinder = urlPathPlaceholderNameAndValueFinder; } - public Response FindDownstreamRoute(string upstreamUrlPath, string upstreamHttpMethod, IOcelotConfiguration configuration) + public Response FindDownstreamRoute(string path, string httpMethod, IOcelotConfiguration configuration) { - var applicableReRoutes = configuration.ReRoutes.Where(r => r.UpstreamHttpMethod.Count == 0 || r.UpstreamHttpMethod.Select(x => x.Method.ToLower()).Contains(upstreamHttpMethod.ToLower())); + var applicableReRoutes = configuration.ReRoutes.Where(r => r.UpstreamHttpMethod.Count == 0 || r.UpstreamHttpMethod.Select(x => x.Method.ToLower()).Contains(httpMethod.ToLower())).OrderByDescending(x => x.UpstreamTemplatePattern.Priority); foreach (var reRoute in applicableReRoutes) { - if (upstreamUrlPath == reRoute.UpstreamTemplatePattern) + if (path == reRoute.UpstreamTemplatePattern.Template) { - var templateVariableNameAndValues = _urlPathPlaceholderNameAndValueFinder.Find(upstreamUrlPath, reRoute.UpstreamPathTemplate.Value); - - return new OkResponse(new DownstreamRoute(templateVariableNameAndValues.Data, reRoute)); + return GetPlaceholderNamesAndValues(path, reRoute); } - var urlMatch = _urlMatcher.Match(upstreamUrlPath, reRoute.UpstreamTemplatePattern); + var urlMatch = _urlMatcher.Match(path, reRoute.UpstreamTemplatePattern.Template); if (urlMatch.Data.Match) { - var templateVariableNameAndValues = _urlPathPlaceholderNameAndValueFinder.Find(upstreamUrlPath, reRoute.UpstreamPathTemplate.Value); - - return new OkResponse(new DownstreamRoute(templateVariableNameAndValues.Data, reRoute)); + return GetPlaceholderNamesAndValues(path, reRoute); } } @@ -49,5 +45,12 @@ namespace Ocelot.DownstreamRouteFinder.Finder new UnableToFindDownstreamRouteError() }); } + + private OkResponse GetPlaceholderNamesAndValues(string path, ReRoute reRoute) + { + var templatePlaceholderNameAndValues = __placeholderNameAndValueFinder.Find(path, reRoute.UpstreamPathTemplate.Value); + + return new OkResponse(new DownstreamRoute(templatePlaceholderNameAndValues.Data, reRoute)); + } } } \ No newline at end of file diff --git a/src/Ocelot/DownstreamRouteFinder/UrlMatcher/IUrlPathPlaceholderNameAndValueFinder.cs b/src/Ocelot/DownstreamRouteFinder/UrlMatcher/IUrlPathPlaceholderNameAndValueFinder.cs index 788299cb..678b1081 100644 --- a/src/Ocelot/DownstreamRouteFinder/UrlMatcher/IUrlPathPlaceholderNameAndValueFinder.cs +++ b/src/Ocelot/DownstreamRouteFinder/UrlMatcher/IUrlPathPlaceholderNameAndValueFinder.cs @@ -3,8 +3,8 @@ using Ocelot.Responses; namespace Ocelot.DownstreamRouteFinder.UrlMatcher { - public interface IUrlPathPlaceholderNameAndValueFinder + public interface IPlaceholderNameAndValueFinder { - Response> Find(string upstreamUrlPath, string upstreamUrlPathTemplate); + Response> Find(string path, string pathTemplate); } } diff --git a/src/Ocelot/DownstreamRouteFinder/UrlMatcher/UrlPathPlaceholderNameAndValue.cs b/src/Ocelot/DownstreamRouteFinder/UrlMatcher/UrlPathPlaceholderNameAndValue.cs index cb690666..825f1bab 100644 --- a/src/Ocelot/DownstreamRouteFinder/UrlMatcher/UrlPathPlaceholderNameAndValue.cs +++ b/src/Ocelot/DownstreamRouteFinder/UrlMatcher/UrlPathPlaceholderNameAndValue.cs @@ -1,13 +1,13 @@ namespace Ocelot.DownstreamRouteFinder.UrlMatcher { - public class UrlPathPlaceholderNameAndValue + public class PlaceholderNameAndValue { - public UrlPathPlaceholderNameAndValue(string templateVariableName, string templateVariableValue) + public PlaceholderNameAndValue(string name, string value) { - TemplateVariableName = templateVariableName; - TemplateVariableValue = templateVariableValue; + Name = name; + Value = value; } - public string TemplateVariableName {get;private set;} - public string TemplateVariableValue {get;private set;} + public string Name {get;private set;} + public string Value {get;private set;} } } \ No newline at end of file diff --git a/src/Ocelot/DownstreamRouteFinder/UrlMatcher/UrlPathPlaceholderNameAndValueFinder.cs b/src/Ocelot/DownstreamRouteFinder/UrlMatcher/UrlPathPlaceholderNameAndValueFinder.cs index 946a365c..8b1c6acf 100644 --- a/src/Ocelot/DownstreamRouteFinder/UrlMatcher/UrlPathPlaceholderNameAndValueFinder.cs +++ b/src/Ocelot/DownstreamRouteFinder/UrlMatcher/UrlPathPlaceholderNameAndValueFinder.cs @@ -3,44 +3,72 @@ using Ocelot.Responses; namespace Ocelot.DownstreamRouteFinder.UrlMatcher { - public class UrlPathPlaceholderNameAndValueFinder : IUrlPathPlaceholderNameAndValueFinder + public class UrlPathPlaceholderNameAndValueFinder : IPlaceholderNameAndValueFinder { - public Response> Find(string upstreamUrlPath, string upstreamUrlPathTemplate) + public Response> Find(string path, string pathTemplate) { - var templateKeysAndValues = new List(); + var placeHolderNameAndValues = new List(); - int counterForUrl = 0; + int counterForPath = 0; - for (int counterForTemplate = 0; counterForTemplate < upstreamUrlPathTemplate.Length; counterForTemplate++) + for (int counterForTemplate = 0; counterForTemplate < pathTemplate.Length; counterForTemplate++) { - if ((upstreamUrlPath.Length > counterForUrl) && CharactersDontMatch(upstreamUrlPathTemplate[counterForTemplate], upstreamUrlPath[counterForUrl]) && ContinueScanningUrl(counterForUrl,upstreamUrlPath.Length)) + if ((path.Length > counterForPath) && CharactersDontMatch(pathTemplate[counterForTemplate], path[counterForPath]) && ContinueScanningUrl(counterForPath,path.Length)) { - if (IsPlaceholder(upstreamUrlPathTemplate[counterForTemplate])) + if (IsPlaceholder(pathTemplate[counterForTemplate])) { - var variableName = GetPlaceholderVariableName(upstreamUrlPathTemplate, counterForTemplate); + var placeholderName = GetPlaceholderName(pathTemplate, counterForTemplate); - var variableValue = GetPlaceholderVariableValue(upstreamUrlPathTemplate, variableName, upstreamUrlPath, counterForUrl); + var placeholderValue = GetPlaceholderValue(pathTemplate, placeholderName, path, counterForPath); - var templateVariableNameAndValue = new UrlPathPlaceholderNameAndValue(variableName, variableValue); + placeHolderNameAndValues.Add(new PlaceholderNameAndValue(placeholderName, placeholderValue)); - templateKeysAndValues.Add(templateVariableNameAndValue); + counterForTemplate = GetNextCounterPosition(pathTemplate, counterForTemplate, '}'); - counterForTemplate = GetNextCounterPosition(upstreamUrlPathTemplate, counterForTemplate, '}'); - - counterForUrl = GetNextCounterPosition(upstreamUrlPath, counterForUrl, '/'); + counterForPath = GetNextCounterPosition(path, counterForPath, '/'); continue; } - return new OkResponse>(templateKeysAndValues); + return new OkResponse>(placeHolderNameAndValues); } - counterForUrl++; + else if(IsCatchAll(path, counterForPath, pathTemplate)) + { + var endOfPlaceholder = GetNextCounterPosition(pathTemplate, counterForTemplate, '}'); + + var placeholderName = GetPlaceholderName(pathTemplate, 1); + + if(NothingAfterFirstForwardSlash(path)) + { + placeHolderNameAndValues.Add(new PlaceholderNameAndValue(placeholderName, "")); + } + else + { + var placeholderValue = GetPlaceholderValue(pathTemplate, placeholderName, path, counterForPath + 1); + placeHolderNameAndValues.Add(new PlaceholderNameAndValue(placeholderName, placeholderValue)); + } + + counterForTemplate = endOfPlaceholder; + } + counterForPath++; } - return new OkResponse>(templateKeysAndValues); + return new OkResponse>(placeHolderNameAndValues); } - private string GetPlaceholderVariableValue(string urlPathTemplate, string variableName, string urlPath, int counterForUrl) + private bool IsCatchAll(string path, int counterForPath, string pathTemplate) + { + return string.IsNullOrEmpty(path) || (path.Length > counterForPath && path[counterForPath] == '/') && pathTemplate.Length > 1 + && pathTemplate.Substring(0, 2) == "/{" + && pathTemplate.IndexOf('}') == pathTemplate.Length - 1; + } + + private bool NothingAfterFirstForwardSlash(string path) + { + return path.Length == 1 || path.Length == 0; + } + + private string GetPlaceholderValue(string urlPathTemplate, string variableName, string urlPath, int counterForUrl) { var positionOfNextSlash = urlPath.IndexOf('/', counterForUrl); @@ -54,7 +82,7 @@ namespace Ocelot.DownstreamRouteFinder.UrlMatcher return variableValue; } - private string GetPlaceholderVariableName(string urlPathTemplate, int counterForTemplate) + private string GetPlaceholderName(string urlPathTemplate, int counterForTemplate) { var postitionOfPlaceHolderClosingBracket = urlPathTemplate.IndexOf('}', counterForTemplate) + 1; diff --git a/src/Ocelot/DownstreamUrlCreator/UrlTemplateReplacer/DownstreamUrlTemplateVariableReplacer.cs b/src/Ocelot/DownstreamUrlCreator/UrlTemplateReplacer/DownstreamUrlTemplateVariableReplacer.cs index 3c42b4f4..1b744819 100644 --- a/src/Ocelot/DownstreamUrlCreator/UrlTemplateReplacer/DownstreamUrlTemplateVariableReplacer.cs +++ b/src/Ocelot/DownstreamUrlCreator/UrlTemplateReplacer/DownstreamUrlTemplateVariableReplacer.cs @@ -8,7 +8,7 @@ namespace Ocelot.DownstreamUrlCreator.UrlTemplateReplacer { public class DownstreamTemplatePathPlaceholderReplacer : IDownstreamPathPlaceholderReplacer { - public Response Replace(PathTemplate downstreamPathTemplate, List urlPathPlaceholderNameAndValues) + public Response Replace(PathTemplate downstreamPathTemplate, List urlPathPlaceholderNameAndValues) { var downstreamPath = new StringBuilder(); @@ -16,7 +16,7 @@ namespace Ocelot.DownstreamUrlCreator.UrlTemplateReplacer foreach (var placeholderVariableAndValue in urlPathPlaceholderNameAndValues) { - downstreamPath.Replace(placeholderVariableAndValue.TemplateVariableName, placeholderVariableAndValue.TemplateVariableValue); + downstreamPath.Replace(placeholderVariableAndValue.Name, placeholderVariableAndValue.Value); } return new OkResponse(new DownstreamPath(downstreamPath.ToString())); diff --git a/src/Ocelot/DownstreamUrlCreator/UrlTemplateReplacer/IDownstreamUrlPathTemplateVariableReplacer.cs b/src/Ocelot/DownstreamUrlCreator/UrlTemplateReplacer/IDownstreamUrlPathTemplateVariableReplacer.cs index 647af63a..46e998d4 100644 --- a/src/Ocelot/DownstreamUrlCreator/UrlTemplateReplacer/IDownstreamUrlPathTemplateVariableReplacer.cs +++ b/src/Ocelot/DownstreamUrlCreator/UrlTemplateReplacer/IDownstreamUrlPathTemplateVariableReplacer.cs @@ -7,6 +7,6 @@ namespace Ocelot.DownstreamUrlCreator.UrlTemplateReplacer { public interface IDownstreamPathPlaceholderReplacer { - Response Replace(PathTemplate downstreamPathTemplate, List urlPathPlaceholderNameAndValues); + Response Replace(PathTemplate downstreamPathTemplate, List urlPathPlaceholderNameAndValues); } } \ No newline at end of file diff --git a/src/Ocelot/Values/DownstreamPathTemplate.cs b/src/Ocelot/Values/PathTemplate.cs similarity index 100% rename from src/Ocelot/Values/DownstreamPathTemplate.cs rename to src/Ocelot/Values/PathTemplate.cs diff --git a/src/Ocelot/Values/UpstreamPathTemplate.cs b/src/Ocelot/Values/UpstreamPathTemplate.cs new file mode 100644 index 00000000..00b70b2f --- /dev/null +++ b/src/Ocelot/Values/UpstreamPathTemplate.cs @@ -0,0 +1,14 @@ +namespace Ocelot.Values +{ + public class UpstreamPathTemplate + { + public UpstreamPathTemplate(string template, int priority) + { + Template = template; + Priority = priority; + } + + public string Template {get;} + public int Priority {get;} + } +} \ No newline at end of file diff --git a/test/Ocelot.AcceptanceTests/RoutingTests.cs b/test/Ocelot.AcceptanceTests/RoutingTests.cs index 587327d1..21c21c06 100644 --- a/test/Ocelot.AcceptanceTests/RoutingTests.cs +++ b/test/Ocelot.AcceptanceTests/RoutingTests.cs @@ -52,7 +52,7 @@ namespace Ocelot.AcceptanceTests } }; - this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:51879", "", 200, "Hello from Laura")) + this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:51879/", "/", 200, "Hello from Laura")) .And(x => _steps.GivenThereIsAConfiguration(configuration)) .And(x => _steps.GivenOcelotIsRunning()) .When(x => _steps.WhenIGetUrlOnTheApiGateway("/")) @@ -61,6 +61,145 @@ namespace Ocelot.AcceptanceTests .BDDfy(); } + [Fact] + public void should_return_response_200_favouring_forward_slash_with_path_route() + { + var configuration = new FileConfiguration + { + ReRoutes = new List + { + new FileReRoute + { + DownstreamPathTemplate = "/{url}", + DownstreamScheme = "http", + DownstreamHost = "localhost", + DownstreamPort = 51880, + UpstreamPathTemplate = "/{url}", + UpstreamHttpMethod = new List { "Get" }, + }, + new FileReRoute + { + DownstreamPathTemplate = "/", + DownstreamScheme = "http", + DownstreamHost = "localhost", + DownstreamPort = 51879, + UpstreamPathTemplate = "/", + UpstreamHttpMethod = new List { "Get" }, + } + } + }; + + this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:51880/", "/test", 200, "Hello from Laura")) + .And(x => _steps.GivenThereIsAConfiguration(configuration)) + .And(x => _steps.GivenOcelotIsRunning()) + .When(x => _steps.WhenIGetUrlOnTheApiGateway("/test")) + .Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.OK)) + .And(x => _steps.ThenTheResponseBodyShouldBe("Hello from Laura")) + .BDDfy(); + } + + [Fact] + public void should_return_response_200_favouring_forward_slash() + { + var configuration = new FileConfiguration + { + ReRoutes = new List + { + new FileReRoute + { + DownstreamPathTemplate = "/{url}", + DownstreamScheme = "http", + DownstreamHost = "localhost", + DownstreamPort = 51880, + UpstreamPathTemplate = "/{url}", + UpstreamHttpMethod = new List { "Get" }, + }, + new FileReRoute + { + DownstreamPathTemplate = "/", + DownstreamScheme = "http", + DownstreamHost = "localhost", + DownstreamPort = 51879, + UpstreamPathTemplate = "/", + UpstreamHttpMethod = new List { "Get" }, + } + } + }; + + this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:51879/", "/", 200, "Hello from Laura")) + .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")) + .BDDfy(); + } + + [Fact] + public void should_return_response_200_favouring_forward_slash_route_because_it_is_first() + { + var configuration = new FileConfiguration + { + ReRoutes = new List + { + new FileReRoute + { + DownstreamPathTemplate = "/", + DownstreamScheme = "http", + DownstreamHost = "localhost", + DownstreamPort = 51880, + UpstreamPathTemplate = "/", + UpstreamHttpMethod = new List { "Get" }, + }, + new FileReRoute + { + DownstreamPathTemplate = "/{url}", + DownstreamScheme = "http", + DownstreamHost = "localhost", + DownstreamPort = 51879, + UpstreamPathTemplate = "/{url}", + UpstreamHttpMethod = new List { "Get" }, + } + } + }; + + this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:51880/", "/", 200, "Hello from Laura")) + .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")) + .BDDfy(); + } + + [Fact] + public void should_return_response_200_with_nothing_and_placeholder_only() + { + var configuration = new FileConfiguration + { + ReRoutes = new List + { + new FileReRoute + { + DownstreamPathTemplate = "/{url}", + DownstreamScheme = "http", + DownstreamHost = "localhost", + DownstreamPort = 51879, + UpstreamPathTemplate = "/{url}", + UpstreamHttpMethod = new List { "Get" }, + } + } + }; + + this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:51879", "/", 200, "Hello from Laura")) + .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")) + .BDDfy(); + } + [Fact] public void should_return_response_200_with_simple_url() { @@ -80,7 +219,7 @@ namespace Ocelot.AcceptanceTests } }; - this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:51879", "", 200, "Hello from Laura")) + this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:51879", "/", 200, "Hello from Laura")) .And(x => _steps.GivenThereIsAConfiguration(configuration)) .And(x => _steps.GivenOcelotIsRunning()) .When(x => _steps.WhenIGetUrlOnTheApiGateway("/")) @@ -378,7 +517,7 @@ namespace Ocelot.AcceptanceTests } }; - this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:51879", "", 201, string.Empty)) + this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:51879", "/", 201, string.Empty)) .And(x => _steps.GivenThereIsAConfiguration(configuration)) .And(x => _steps.GivenOcelotIsRunning()) .And(x => _steps.GivenThePostHasContent("postContent")) @@ -406,7 +545,7 @@ namespace Ocelot.AcceptanceTests } }; - this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:51879", "", 200, "Hello from Laura")) + this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:51879", "/newThing", 200, "Hello from Laura")) .And(x => _steps.GivenThereIsAConfiguration(configuration)) .And(x => _steps.GivenOcelotIsRunning()) .When(x => _steps.WhenIGetUrlOnTheApiGateway("/newThing?DeviceType=IphoneApp&Browser=moonpigIphone&BrowserString=-&CountryCode=123&DeviceName=iPhone 5 (GSM+CDMA)&OperatingSystem=iPhone OS 7.1.2&BrowserVersion=3708AdHoc&ipAddress=-")) @@ -434,7 +573,7 @@ namespace Ocelot.AcceptanceTests } }; - this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:51879", "/myApp1Name/api/products/1", 200, "Some Product")) + this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:51879", "/api/products/1", 200, "Some Product")) .And(x => _steps.GivenThereIsAConfiguration(configuration)) .And(x => _steps.GivenOcelotIsRunning()) .When(x => _steps.WhenIGetUrlOnTheApiGateway("/myApp1Name/api/products/1")) @@ -490,7 +629,7 @@ namespace Ocelot.AcceptanceTests } }; - this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:51879", "", 200, "Hello from Laura")) + this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:51879", "/", 200, "Hello from Laura")) .And(x => _steps.GivenThereIsAConfiguration(configuration)) .And(x => _steps.GivenOcelotIsRunning()) .When(x => _steps.WhenIGetUrlOnTheApiGateway("/")) @@ -564,7 +703,7 @@ namespace Ocelot.AcceptanceTests } }; - this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:51899", "", 200, "Hello from Laura")) + this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:51899", "/api/swagger/lib/backbone-min.js", 200, "Hello from Laura")) .And(x => _steps.GivenThereIsAConfiguration(configuration)) .And(x => _steps.GivenOcelotIsRunning()) .When(x => _steps.WhenIGetUrlOnTheApiGateway("/platform/swagger/lib/backbone-min.js")) @@ -587,8 +726,17 @@ namespace Ocelot.AcceptanceTests app.Run(async context => { _downstreamPath = !string.IsNullOrEmpty(context.Request.PathBase.Value) ? context.Request.PathBase.Value : context.Request.Path.Value; - context.Response.StatusCode = statusCode; - await context.Response.WriteAsync(responseBody); + + if(_downstreamPath != basePath) + { + context.Response.StatusCode = statusCode; + await context.Response.WriteAsync("downstream path didnt match base path"); + } + else + { + context.Response.StatusCode = statusCode; + await context.Response.WriteAsync(responseBody); + } }); }) .Build(); diff --git a/test/Ocelot.UnitTests/Authentication/AuthenticationMiddlewareTests.cs b/test/Ocelot.UnitTests/Authentication/AuthenticationMiddlewareTests.cs index e6bcc500..dcb54388 100644 --- a/test/Ocelot.UnitTests/Authentication/AuthenticationMiddlewareTests.cs +++ b/test/Ocelot.UnitTests/Authentication/AuthenticationMiddlewareTests.cs @@ -29,7 +29,7 @@ { this.Given(x => x.GivenTheDownStreamRouteIs( new DownstreamRoute( - new List(), + new List(), new ReRouteBuilder().WithUpstreamHttpMethod(new List { "Get" }).Build()))) .When(x => x.WhenICallTheMiddleware()) .Then(x => x.ThenTheUserIsAuthenticated()) diff --git a/test/Ocelot.UnitTests/Authorization/AuthorisationMiddlewareTests.cs b/test/Ocelot.UnitTests/Authorization/AuthorisationMiddlewareTests.cs index ca346974..9ab81f94 100644 --- a/test/Ocelot.UnitTests/Authorization/AuthorisationMiddlewareTests.cs +++ b/test/Ocelot.UnitTests/Authorization/AuthorisationMiddlewareTests.cs @@ -32,7 +32,7 @@ [Fact] public void should_call_authorisation_service() { - this.Given(x => x.GivenTheDownStreamRouteIs(new DownstreamRoute(new List(), + this.Given(x => x.GivenTheDownStreamRouteIs(new DownstreamRoute(new List(), new ReRouteBuilder() .WithIsAuthorised(true) .WithUpstreamHttpMethod(new List { "Get" }) diff --git a/test/Ocelot.UnitTests/Cache/OutputCacheMiddlewareTests.cs b/test/Ocelot.UnitTests/Cache/OutputCacheMiddlewareTests.cs index 9b78b3cc..1499e19d 100644 --- a/test/Ocelot.UnitTests/Cache/OutputCacheMiddlewareTests.cs +++ b/test/Ocelot.UnitTests/Cache/OutputCacheMiddlewareTests.cs @@ -94,7 +94,7 @@ .WithUpstreamHttpMethod(new List { "Get" }) .Build(); - var downstreamRoute = new DownstreamRoute(new List(), reRoute); + var downstreamRoute = new DownstreamRoute(new List(), reRoute); ScopedRepository .Setup(x => x.Get(It.IsAny())) diff --git a/test/Ocelot.UnitTests/Claims/ClaimsBuilderMiddlewareTests.cs b/test/Ocelot.UnitTests/Claims/ClaimsBuilderMiddlewareTests.cs index 3eb86d1e..2470a6fb 100644 --- a/test/Ocelot.UnitTests/Claims/ClaimsBuilderMiddlewareTests.cs +++ b/test/Ocelot.UnitTests/Claims/ClaimsBuilderMiddlewareTests.cs @@ -31,7 +31,7 @@ [Fact] public void should_call_claims_to_request_correctly() { - var downstreamRoute = new DownstreamRoute(new List(), + var downstreamRoute = new DownstreamRoute(new List(), new ReRouteBuilder() .WithDownstreamPathTemplate("any old string") .WithClaimsToClaims(new List diff --git a/test/Ocelot.UnitTests/Configuration/FileConfigurationCreatorTests.cs b/test/Ocelot.UnitTests/Configuration/FileConfigurationCreatorTests.cs index 1182a56f..d39fa394 100644 --- a/test/Ocelot.UnitTests/Configuration/FileConfigurationCreatorTests.cs +++ b/test/Ocelot.UnitTests/Configuration/FileConfigurationCreatorTests.cs @@ -18,6 +18,7 @@ namespace Ocelot.UnitTests.Configuration using Ocelot.DependencyInjection; using Ocelot.Errors; using Ocelot.UnitTests.TestData; + using Ocelot.Values; public class FileConfigurationCreatorTests { @@ -367,7 +368,7 @@ namespace Ocelot.UnitTests.Configuration .WithDownstreamPathTemplate("/products/{productId}") .WithUpstreamPathTemplate("/api/products/{productId}") .WithUpstreamHttpMethod(new List { "Get" }) - .WithUpstreamTemplatePattern("(?i)/api/products/.*/$") + .WithUpstreamTemplatePattern(new UpstreamPathTemplate("(?i)/api/products/.*/$", 1)) .Build() })) .BDDfy(); @@ -580,7 +581,7 @@ namespace Ocelot.UnitTests.Configuration result.DownstreamPathTemplate.Value.ShouldBe(expected.DownstreamPathTemplate.Value); result.UpstreamHttpMethod.ShouldBe(expected.UpstreamHttpMethod); result.UpstreamPathTemplate.Value.ShouldBe(expected.UpstreamPathTemplate.Value); - result.UpstreamTemplatePattern.ShouldBe(expected.UpstreamTemplatePattern); + result.UpstreamTemplatePattern?.Template.ShouldBe(expected.UpstreamTemplatePattern?.Template); result.ClaimsToClaims.Count.ShouldBe(expected.ClaimsToClaims.Count); result.ClaimsToHeaders.Count.ShouldBe(expected.ClaimsToHeaders.Count); result.ClaimsToQueries.Count.ShouldBe(expected.ClaimsToQueries.Count); @@ -623,7 +624,7 @@ namespace Ocelot.UnitTests.Configuration { _upstreamTemplatePatternCreator .Setup(x => x.Create(It.IsAny())) - .Returns(pattern); + .Returns(new UpstreamPathTemplate(pattern, 1)); } private void ThenTheRequestIdKeyCreatorIsCalledCorrectly() diff --git a/test/Ocelot.UnitTests/Configuration/UpstreamTemplatePatternCreatorTests.cs b/test/Ocelot.UnitTests/Configuration/UpstreamTemplatePatternCreatorTests.cs index d5c9774b..87e2f2d6 100644 --- a/test/Ocelot.UnitTests/Configuration/UpstreamTemplatePatternCreatorTests.cs +++ b/test/Ocelot.UnitTests/Configuration/UpstreamTemplatePatternCreatorTests.cs @@ -1,5 +1,7 @@ +using System; using Ocelot.Configuration.Creator; using Ocelot.Configuration.File; +using Ocelot.Values; using Shouldly; using TestStack.BDDfy; using Xunit; @@ -10,7 +12,7 @@ namespace Ocelot.UnitTests.Configuration { private FileReRoute _fileReRoute; private UpstreamTemplatePatternCreator _creator; - private string _result; + private UpstreamPathTemplate _result; public UpstreamTemplatePatternCreatorTests() { @@ -29,6 +31,7 @@ namespace Ocelot.UnitTests.Configuration this.Given(x => x.GivenTheFollowingFileReRoute(fileReRoute)) .When(x => x.WhenICreateTheTemplatePattern()) .Then(x => x.ThenTheFollowingIsReturned("^(?i)/PRODUCTS/[0-9a-zA-Z].*$")) + .And(x => ThenThePriorityIs(1)) .BDDfy(); } @@ -45,6 +48,7 @@ namespace Ocelot.UnitTests.Configuration this.Given(x => x.GivenTheFollowingFileReRoute(fileReRoute)) .When(x => x.WhenICreateTheTemplatePattern()) .Then(x => x.ThenTheFollowingIsReturned("^(?i)/PRODUCTS(/|)$")) + .And(x => ThenThePriorityIs(1)) .BDDfy(); } @@ -59,6 +63,7 @@ namespace Ocelot.UnitTests.Configuration this.Given(x => x.GivenTheFollowingFileReRoute(fileReRoute)) .When(x => x.WhenICreateTheTemplatePattern()) .Then(x => x.ThenTheFollowingIsReturned("^/PRODUCTS/[0-9a-zA-Z].*$")) + .And(x => ThenThePriorityIs(1)) .BDDfy(); } @@ -74,6 +79,7 @@ namespace Ocelot.UnitTests.Configuration this.Given(x => x.GivenTheFollowingFileReRoute(fileReRoute)) .When(x => x.WhenICreateTheTemplatePattern()) .Then(x => x.ThenTheFollowingIsReturned("^/api/products/[0-9a-zA-Z].*$")) + .And(x => ThenThePriorityIs(1)) .BDDfy(); } @@ -89,6 +95,7 @@ namespace Ocelot.UnitTests.Configuration this.Given(x => x.GivenTheFollowingFileReRoute(fileReRoute)) .When(x => x.WhenICreateTheTemplatePattern()) .Then(x => x.ThenTheFollowingIsReturned("^/api/products/[0-9a-zA-Z].*/variants/[0-9a-zA-Z].*$")) + .And(x => ThenThePriorityIs(1)) .BDDfy(); } @@ -104,6 +111,7 @@ namespace Ocelot.UnitTests.Configuration this.Given(x => x.GivenTheFollowingFileReRoute(fileReRoute)) .When(x => x.WhenICreateTheTemplatePattern()) .Then(x => x.ThenTheFollowingIsReturned("^/api/products/[0-9a-zA-Z].*/variants/[0-9a-zA-Z].*(/|)$")) + .And(x => ThenThePriorityIs(1)) .BDDfy(); } @@ -118,6 +126,7 @@ namespace Ocelot.UnitTests.Configuration this.Given(x => x.GivenTheFollowingFileReRoute(fileReRoute)) .When(x => x.WhenICreateTheTemplatePattern()) .Then(x => x.ThenTheFollowingIsReturned("^/$")) + .And(x => ThenThePriorityIs(1)) .BDDfy(); } @@ -132,6 +141,7 @@ namespace Ocelot.UnitTests.Configuration this.Given(x => x.GivenTheFollowingFileReRoute(fileReRoute)) .When(x => x.WhenICreateTheTemplatePattern()) .Then(x => x.ThenTheFollowingIsReturned("^/.*")) + .And(x => ThenThePriorityIs(0)) .BDDfy(); } @@ -147,6 +157,7 @@ namespace Ocelot.UnitTests.Configuration this.Given(x => x.GivenTheFollowingFileReRoute(fileReRoute)) .When(x => x.WhenICreateTheTemplatePattern()) .Then(x => x.ThenTheFollowingIsReturned("^/[0-9a-zA-Z].*/products/variants/[0-9a-zA-Z].*(/|)$")) + .And(x => ThenThePriorityIs(1)) .BDDfy(); } @@ -162,7 +173,12 @@ namespace Ocelot.UnitTests.Configuration private void ThenTheFollowingIsReturned(string expected) { - _result.ShouldBe(expected); + _result.Template.ShouldBe(expected); + } + + private void ThenThePriorityIs(int v) + { + _result.Priority.ShouldBe(v); } } } \ No newline at end of file diff --git a/test/Ocelot.UnitTests/DownstreamRouteFinder/DownstreamRouteFinderMiddlewareTests.cs b/test/Ocelot.UnitTests/DownstreamRouteFinder/DownstreamRouteFinderMiddlewareTests.cs index 9b241fbe..5781996b 100644 --- a/test/Ocelot.UnitTests/DownstreamRouteFinder/DownstreamRouteFinderMiddlewareTests.cs +++ b/test/Ocelot.UnitTests/DownstreamRouteFinder/DownstreamRouteFinderMiddlewareTests.cs @@ -38,7 +38,7 @@ this.Given(x => x.GivenTheDownStreamRouteFinderReturns( new DownstreamRoute( - new List(), + new List(), new ReRouteBuilder() .WithDownstreamPathTemplate("any old string") .WithUpstreamHttpMethod(new List { "Get" }) diff --git a/test/Ocelot.UnitTests/DownstreamRouteFinder/DownstreamRouteFinderTests.cs b/test/Ocelot.UnitTests/DownstreamRouteFinder/DownstreamRouteFinderTests.cs index a1839bea..1593b3f3 100644 --- a/test/Ocelot.UnitTests/DownstreamRouteFinder/DownstreamRouteFinderTests.cs +++ b/test/Ocelot.UnitTests/DownstreamRouteFinder/DownstreamRouteFinderTests.cs @@ -2,11 +2,13 @@ using Moq; using Ocelot.Configuration; using Ocelot.Configuration.Builder; +using Ocelot.Configuration.Creator; using Ocelot.Configuration.Provider; using Ocelot.DownstreamRouteFinder; using Ocelot.DownstreamRouteFinder.Finder; using Ocelot.DownstreamRouteFinder.UrlMatcher; using Ocelot.Responses; +using Ocelot.Values; using Shouldly; using TestStack.BDDfy; using Xunit; @@ -17,7 +19,7 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder { private readonly IDownstreamRouteFinder _downstreamRouteFinder; private readonly Mock _mockMatcher; - private readonly Mock _finder; + private readonly Mock _finder; private string _upstreamUrlPath; private Response _result; private List _reRoutesConfig; @@ -28,10 +30,84 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder public DownstreamRouteFinderTests() { _mockMatcher = new Mock(); - _finder = new Mock(); + _finder = new Mock(); _downstreamRouteFinder = new Ocelot.DownstreamRouteFinder.Finder.DownstreamRouteFinder(_mockMatcher.Object, _finder.Object); } + + [Fact] + public void should_return_highest_priority_when_first() + { + var serviceProviderConfig = new ServiceProviderConfigurationBuilder().Build(); + + this.Given(x => x.GivenThereIsAnUpstreamUrlPath("someUpstreamPath")) + .And(x => x.GivenTheTemplateVariableAndNameFinderReturns( + new OkResponse>(new List()))) + .And(x => x.GivenTheConfigurationIs(new List + { + new ReRouteBuilder() + .WithDownstreamPathTemplate("someDownstreamPath") + .WithUpstreamPathTemplate("someUpstreamPath") + .WithUpstreamHttpMethod(new List { "Post" }) + .WithUpstreamTemplatePattern(new UpstreamPathTemplate("test", 1)) + .Build(), + new ReRouteBuilder() + .WithDownstreamPathTemplate("someDownstreamPath") + .WithUpstreamPathTemplate("someUpstreamPath") + .WithUpstreamHttpMethod(new List { "Post" }) + .WithUpstreamTemplatePattern(new UpstreamPathTemplate("test", 0)) + .Build() + }, string.Empty, serviceProviderConfig)) + .And(x => x.GivenTheUrlMatcherReturns(new OkResponse(new UrlMatch(true)))) + .And(x => x.GivenTheUpstreamHttpMethodIs("Post")) + .When(x => x.WhenICallTheFinder()) + .Then(x => x.ThenTheFollowingIsReturned(new DownstreamRoute(new List(), + new ReRouteBuilder() + .WithDownstreamPathTemplate("someDownstreamPath") + .WithUpstreamTemplatePattern(new UpstreamPathTemplate("test", 1)) + .WithUpstreamHttpMethod(new List { "Post" }) + .WithUpstreamTemplatePattern(new UpstreamPathTemplate("test", 1)) + .Build() + ))) + .BDDfy(); + } + + [Fact] + public void should_return_highest_priority_when_lowest() + { + var serviceProviderConfig = new ServiceProviderConfigurationBuilder().Build(); + + this.Given(x => x.GivenThereIsAnUpstreamUrlPath("someUpstreamPath")) + .And(x => x.GivenTheTemplateVariableAndNameFinderReturns( + new OkResponse>(new List()))) + .And(x => x.GivenTheConfigurationIs(new List + { + new ReRouteBuilder() + .WithDownstreamPathTemplate("someDownstreamPath") + .WithUpstreamPathTemplate("someUpstreamPath") + .WithUpstreamHttpMethod(new List { "Post" }) + .WithUpstreamTemplatePattern(new UpstreamPathTemplate("test", 0)) + .Build(), + new ReRouteBuilder() + .WithDownstreamPathTemplate("someDownstreamPath") + .WithUpstreamPathTemplate("someUpstreamPath") + .WithUpstreamHttpMethod(new List { "Post" }) + .WithUpstreamTemplatePattern(new UpstreamPathTemplate("test", 1)) + .Build() + }, string.Empty, serviceProviderConfig)) + .And(x => x.GivenTheUrlMatcherReturns(new OkResponse(new UrlMatch(true)))) + .And(x => x.GivenTheUpstreamHttpMethodIs("Post")) + .When(x => x.WhenICallTheFinder()) + .Then(x => x.ThenTheFollowingIsReturned(new DownstreamRoute(new List(), + new ReRouteBuilder() + .WithDownstreamPathTemplate("someDownstreamPath") + .WithUpstreamTemplatePattern(new UpstreamPathTemplate("test", 1)) + .WithUpstreamHttpMethod(new List { "Post" }) + .Build() + ))) + .BDDfy(); + } + [Fact] public void should_return_route() { @@ -39,15 +115,15 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder this.Given(x => x.GivenThereIsAnUpstreamUrlPath("matchInUrlMatcher/")) .And(x =>x.GivenTheTemplateVariableAndNameFinderReturns( - new OkResponse>( - new List()))) + new OkResponse>( + new List()))) .And(x => x.GivenTheConfigurationIs(new List { new ReRouteBuilder() .WithDownstreamPathTemplate("someDownstreamPath") .WithUpstreamPathTemplate("someUpstreamPath") .WithUpstreamHttpMethod(new List { "Get" }) - .WithUpstreamTemplatePattern("someUpstreamPath") + .WithUpstreamTemplatePattern(new UpstreamPathTemplate("someUpstreamPath", 1)) .Build() }, string.Empty, serviceProviderConfig )) @@ -56,10 +132,11 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder .When(x => x.WhenICallTheFinder()) .Then( x => x.ThenTheFollowingIsReturned(new DownstreamRoute( - new List(), + new List(), new ReRouteBuilder() .WithDownstreamPathTemplate("someDownstreamPath") .WithUpstreamHttpMethod(new List { "Get" }) + .WithUpstreamTemplatePattern(new UpstreamPathTemplate("someUpstreamPath", 1)) .Build() ))) .And(x => x.ThenTheUrlMatcherIsCalledCorrectly()) @@ -74,15 +151,15 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder this.Given(x => x.GivenThereIsAnUpstreamUrlPath("matchInUrlMatcher")) .And(x =>x.GivenTheTemplateVariableAndNameFinderReturns( - new OkResponse>( - new List()))) + new OkResponse>( + new List()))) .And(x => x.GivenTheConfigurationIs(new List { new ReRouteBuilder() .WithDownstreamPathTemplate("someDownstreamPath") .WithUpstreamPathTemplate("someUpstreamPath") .WithUpstreamHttpMethod(new List { "Get" }) - .WithUpstreamTemplatePattern("someUpstreamPath") + .WithUpstreamTemplatePattern(new UpstreamPathTemplate("someUpstreamPath", 1)) .Build() }, string.Empty, serviceProviderConfig )) @@ -91,10 +168,11 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder .When(x => x.WhenICallTheFinder()) .Then( x => x.ThenTheFollowingIsReturned(new DownstreamRoute( - new List(), + new List(), new ReRouteBuilder() .WithDownstreamPathTemplate("someDownstreamPath") .WithUpstreamHttpMethod(new List { "Get" }) + .WithUpstreamTemplatePattern(new UpstreamPathTemplate("someUpstreamPath", 1)) .Build() ))) .And(x => x.ThenTheUrlMatcherIsCalledCorrectly("matchInUrlMatcher")) @@ -110,14 +188,14 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder .And( x => x.GivenTheTemplateVariableAndNameFinderReturns( - new OkResponse>(new List()))) + new OkResponse>(new List()))) .And(x => x.GivenTheConfigurationIs(new List { new ReRouteBuilder() .WithDownstreamPathTemplate("someDownstreamPath") .WithUpstreamPathTemplate("someUpstreamPath") .WithUpstreamHttpMethod(new List { "Get" }) - .WithUpstreamTemplatePattern("someUpstreamPath") + .WithUpstreamTemplatePattern(new UpstreamPathTemplate("someUpstreamPath", 1)) .Build() }, string.Empty, serviceProviderConfig )) @@ -125,10 +203,11 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder .And(x => x.GivenTheUpstreamHttpMethodIs("Get")) .When(x => x.WhenICallTheFinder()) .Then( - x => x.ThenTheFollowingIsReturned(new DownstreamRoute(new List(), + x => x.ThenTheFollowingIsReturned(new DownstreamRoute(new List(), new ReRouteBuilder() .WithDownstreamPathTemplate("someDownstreamPath") .WithUpstreamHttpMethod(new List { "Get" }) + .WithUpstreamTemplatePattern(new UpstreamPathTemplate("someUpstreamPath", 1)) .Build() ))) .And(x => x.ThenTheUrlMatcherIsNotCalled()) @@ -144,20 +223,20 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder .And( x => x.GivenTheTemplateVariableAndNameFinderReturns( - new OkResponse>(new List()))) + new OkResponse>(new List()))) .And(x => x.GivenTheConfigurationIs(new List { new ReRouteBuilder() .WithDownstreamPathTemplate("someDownstreamPath") .WithUpstreamPathTemplate("someUpstreamPath") .WithUpstreamHttpMethod(new List { "Get" }) - .WithUpstreamTemplatePattern("") + .WithUpstreamTemplatePattern(new UpstreamPathTemplate("", 1)) .Build(), new ReRouteBuilder() .WithDownstreamPathTemplate("someDownstreamPathForAPost") .WithUpstreamPathTemplate("someUpstreamPath") .WithUpstreamHttpMethod(new List { "Post" }) - .WithUpstreamTemplatePattern("") + .WithUpstreamTemplatePattern(new UpstreamPathTemplate("", 1)) .Build() }, string.Empty, serviceProviderConfig )) @@ -165,10 +244,11 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder .And(x => x.GivenTheUpstreamHttpMethodIs("Post")) .When(x => x.WhenICallTheFinder()) .Then( - x => x.ThenTheFollowingIsReturned(new DownstreamRoute(new List(), + x => x.ThenTheFollowingIsReturned(new DownstreamRoute(new List(), new ReRouteBuilder() .WithDownstreamPathTemplate("someDownstreamPathForAPost") .WithUpstreamHttpMethod(new List { "Post" }) + .WithUpstreamTemplatePattern(new UpstreamPathTemplate("", 1)) .Build() ))) .BDDfy(); @@ -186,7 +266,7 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder .WithDownstreamPathTemplate("somPath") .WithUpstreamPathTemplate("somePath") .WithUpstreamHttpMethod(new List { "Get" }) - .WithUpstreamTemplatePattern("somePath") + .WithUpstreamTemplatePattern(new UpstreamPathTemplate("somePath", 1)) .Build(), }, string.Empty, serviceProviderConfig )) @@ -208,14 +288,14 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder .And( x => x.GivenTheTemplateVariableAndNameFinderReturns( - new OkResponse>(new List()))) + new OkResponse>(new List()))) .And(x => x.GivenTheConfigurationIs(new List { new ReRouteBuilder() .WithDownstreamPathTemplate("someDownstreamPath") .WithUpstreamPathTemplate("someUpstreamPath") .WithUpstreamHttpMethod(new List { "Get", "Post" }) - .WithUpstreamTemplatePattern("") + .WithUpstreamTemplatePattern(new UpstreamPathTemplate("", 1)) .Build() }, string.Empty, serviceProviderConfig )) @@ -223,10 +303,11 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder .And(x => x.GivenTheUpstreamHttpMethodIs("Post")) .When(x => x.WhenICallTheFinder()) .Then( - x => x.ThenTheFollowingIsReturned(new DownstreamRoute(new List(), + x => x.ThenTheFollowingIsReturned(new DownstreamRoute(new List(), new ReRouteBuilder() .WithDownstreamPathTemplate("someDownstreamPath") .WithUpstreamHttpMethod(new List { "Post" }) + .WithUpstreamTemplatePattern(new UpstreamPathTemplate("", 1)) .Build() ))) .BDDfy(); @@ -241,14 +322,14 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder .And( x => x.GivenTheTemplateVariableAndNameFinderReturns( - new OkResponse>(new List()))) + new OkResponse>(new List()))) .And(x => x.GivenTheConfigurationIs(new List { new ReRouteBuilder() .WithDownstreamPathTemplate("someDownstreamPath") .WithUpstreamPathTemplate("someUpstreamPath") .WithUpstreamHttpMethod(new List()) - .WithUpstreamTemplatePattern("") + .WithUpstreamTemplatePattern(new UpstreamPathTemplate("", 1)) .Build() }, string.Empty, serviceProviderConfig )) @@ -256,10 +337,11 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder .And(x => x.GivenTheUpstreamHttpMethodIs("Post")) .When(x => x.WhenICallTheFinder()) .Then( - x => x.ThenTheFollowingIsReturned(new DownstreamRoute(new List(), + x => x.ThenTheFollowingIsReturned(new DownstreamRoute(new List(), new ReRouteBuilder() .WithDownstreamPathTemplate("someDownstreamPath") .WithUpstreamHttpMethod(new List { "Post" }) + .WithUpstreamTemplatePattern(new UpstreamPathTemplate("", 1)) .Build() ))) .BDDfy(); @@ -274,14 +356,14 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder .And( x => x.GivenTheTemplateVariableAndNameFinderReturns( - new OkResponse>(new List()))) + new OkResponse>(new List()))) .And(x => x.GivenTheConfigurationIs(new List { new ReRouteBuilder() .WithDownstreamPathTemplate("someDownstreamPath") .WithUpstreamPathTemplate("someUpstreamPath") .WithUpstreamHttpMethod(new List { "Get", "Patch", "Delete" }) - .WithUpstreamTemplatePattern("") + .WithUpstreamTemplatePattern(new UpstreamPathTemplate("", 1)) .Build() }, string.Empty, serviceProviderConfig )) @@ -294,7 +376,7 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder .BDDfy(); } - private void GivenTheTemplateVariableAndNameFinderReturns(Response> response) + private void GivenTheTemplateVariableAndNameFinderReturns(Response> response) { _finder .Setup(x => x.Find(It.IsAny(), It.IsAny())) @@ -356,14 +438,12 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder private void ThenTheFollowingIsReturned(DownstreamRoute expected) { _result.Data.ReRoute.DownstreamPathTemplate.Value.ShouldBe(expected.ReRoute.DownstreamPathTemplate.Value); + _result.Data.ReRoute.UpstreamTemplatePattern.Priority.ShouldBe(expected.ReRoute.UpstreamTemplatePattern.Priority); for (int i = 0; i < _result.Data.TemplatePlaceholderNameAndValues.Count; i++) { - _result.Data.TemplatePlaceholderNameAndValues[i].TemplateVariableName.ShouldBe( - expected.TemplatePlaceholderNameAndValues[i].TemplateVariableName); - - _result.Data.TemplatePlaceholderNameAndValues[i].TemplateVariableValue.ShouldBe( - expected.TemplatePlaceholderNameAndValues[i].TemplateVariableValue); + _result.Data.TemplatePlaceholderNameAndValues[i].Name.ShouldBe(expected.TemplatePlaceholderNameAndValues[i].Name); + _result.Data.TemplatePlaceholderNameAndValues[i].Value.ShouldBe(expected.TemplatePlaceholderNameAndValues[i].Value); } _result.IsError.ShouldBeFalse(); diff --git a/test/Ocelot.UnitTests/DownstreamRouteFinder/UrlMatcher/RegExUrlMatcherTests.cs b/test/Ocelot.UnitTests/DownstreamRouteFinder/UrlMatcher/RegExUrlMatcherTests.cs index 9f76228b..f57ed842 100644 --- a/test/Ocelot.UnitTests/DownstreamRouteFinder/UrlMatcher/RegExUrlMatcherTests.cs +++ b/test/Ocelot.UnitTests/DownstreamRouteFinder/UrlMatcher/RegExUrlMatcherTests.cs @@ -18,6 +18,18 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder.UrlMatcher _urlMatcher = new RegExUrlMatcher(); } + [Fact] + public void should_not_match_slash_becaue_we_need_to_match_something_after_it() + { + const string RegExForwardSlashAndOnePlaceHolder = "^/[0-9a-zA-Z].*"; + + this.Given(x => x.GivenIHaveAUpstreamPath("/")) + .And(x => x.GivenIHaveAnUpstreamUrlTemplatePattern(RegExForwardSlashAndOnePlaceHolder)) + .When(x => x.WhenIMatchThePaths()) + .And(x => x.ThenTheResultIsFalse()) + .BDDfy(); + } + [Fact] public void should_not_match_forward_slash_only_regex() { diff --git a/test/Ocelot.UnitTests/DownstreamRouteFinder/UrlMatcher/TemplateVariableNameAndValueFinderTests.cs b/test/Ocelot.UnitTests/DownstreamRouteFinder/UrlMatcher/UrlPathPlaceholderNameAndValueFinderTests.cs similarity index 57% rename from test/Ocelot.UnitTests/DownstreamRouteFinder/UrlMatcher/TemplateVariableNameAndValueFinderTests.cs rename to test/Ocelot.UnitTests/DownstreamRouteFinder/UrlMatcher/UrlPathPlaceholderNameAndValueFinderTests.cs index fded9ecf..9fa9366b 100644 --- a/test/Ocelot.UnitTests/DownstreamRouteFinder/UrlMatcher/TemplateVariableNameAndValueFinderTests.cs +++ b/test/Ocelot.UnitTests/DownstreamRouteFinder/UrlMatcher/UrlPathPlaceholderNameAndValueFinderTests.cs @@ -8,14 +8,14 @@ using Xunit; namespace Ocelot.UnitTests.DownstreamRouteFinder.UrlMatcher { - public class UrlPathToUrlTemplateMatcherTests + public class UrlPathPlaceholderNameAndValueFinderTests { - private readonly IUrlPathPlaceholderNameAndValueFinder _finder; + private readonly IPlaceholderNameAndValueFinder _finder; private string _downstreamUrlPath; private string _downstreamPathTemplate; - private Response> _result; + private Response> _result; - public UrlPathToUrlTemplateMatcherTests() + public UrlPathPlaceholderNameAndValueFinderTests() { _finder = new UrlPathPlaceholderNameAndValueFinder(); } @@ -26,7 +26,82 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder.UrlMatcher this.Given(x => x.GivenIHaveAUpstreamPath("")) .And(x => x.GivenIHaveAnUpstreamUrlTemplate("")) .When(x => x.WhenIFindTheUrlVariableNamesAndValues()) - .And(x => x.ThenTheTemplatesVariablesAre(new List())) + .And(x => x.ThenTheTemplatesVariablesAre(new List())) + .BDDfy(); + } + + + [Fact] + public void can_match_down_stream_url_with_nothing_then_placeholder_no_value_is_blank() + { + var expectedTemplates = new List + { + new PlaceholderNameAndValue("{url}", "") + }; + + this.Given(x => x.GivenIHaveAUpstreamPath("")) + .And(x => x.GivenIHaveAnUpstreamUrlTemplate("/{url}")) + .When(x => x.WhenIFindTheUrlVariableNamesAndValues()) + .And(x => x.ThenTheTemplatesVariablesAre(expectedTemplates)) + .BDDfy(); + } + + [Fact] + public void can_match_down_stream_url_with_nothing_then_placeholder_value_is_test() + { + var expectedTemplates = new List + { + new PlaceholderNameAndValue("{url}", "test") + }; + + this.Given(x => x.GivenIHaveAUpstreamPath("/test")) + .And(x => x.GivenIHaveAnUpstreamUrlTemplate("/{url}")) + .When(x => x.WhenIFindTheUrlVariableNamesAndValues()) + .And(x => x.ThenTheTemplatesVariablesAre(expectedTemplates)) + .BDDfy(); + } + + [Fact] + public void can_match_down_stream_url_with_forward_slash_then_placeholder_no_value_is_blank() + { + var expectedTemplates = new List + { + new PlaceholderNameAndValue("{url}", "") + }; + + this.Given(x => x.GivenIHaveAUpstreamPath("/")) + .And(x => x.GivenIHaveAnUpstreamUrlTemplate("/{url}")) + .When(x => x.WhenIFindTheUrlVariableNamesAndValues()) + .And(x => x.ThenTheTemplatesVariablesAre(expectedTemplates)) + .BDDfy(); + } + + [Fact] + public void can_match_down_stream_url_with_forward_slash() + { + var expectedTemplates = new List + { + }; + + this.Given(x => x.GivenIHaveAUpstreamPath("/")) + .And(x => x.GivenIHaveAnUpstreamUrlTemplate("/")) + .When(x => x.WhenIFindTheUrlVariableNamesAndValues()) + .And(x => x.ThenTheTemplatesVariablesAre(expectedTemplates)) + .BDDfy(); + } + + [Fact] + public void can_match_down_stream_url_with_forward_slash_then_placeholder_then_another_value() + { + var expectedTemplates = new List + { + new PlaceholderNameAndValue("{url}", "1") + }; + + this.Given(x => x.GivenIHaveAUpstreamPath("/1/products")) + .And(x => x.GivenIHaveAnUpstreamUrlTemplate("/{url}/products")) + .When(x => x.WhenIFindTheUrlVariableNamesAndValues()) + .And(x => x.ThenTheTemplatesVariablesAre(expectedTemplates)) .BDDfy(); } @@ -36,7 +111,7 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder.UrlMatcher this.Given(x => x.GivenIHaveAUpstreamPath("/products")) .And(x => x.GivenIHaveAnUpstreamUrlTemplate("/products/")) .When(x => x.WhenIFindTheUrlVariableNamesAndValues()) - .And(x => x.ThenTheTemplatesVariablesAre(new List())) + .And(x => x.ThenTheTemplatesVariablesAre(new List())) .BDDfy(); } @@ -46,7 +121,7 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder.UrlMatcher this.Given(x => x.GivenIHaveAUpstreamPath("api")) .Given(x => x.GivenIHaveAnUpstreamUrlTemplate("api")) .When(x => x.WhenIFindTheUrlVariableNamesAndValues()) - .And(x => x.ThenTheTemplatesVariablesAre(new List())) + .And(x => x.ThenTheTemplatesVariablesAre(new List())) .BDDfy(); } @@ -56,7 +131,7 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder.UrlMatcher this.Given(x => x.GivenIHaveAUpstreamPath("api/")) .Given(x => x.GivenIHaveAnUpstreamUrlTemplate("api/")) .When(x => x.WhenIFindTheUrlVariableNamesAndValues()) - .And(x => x.ThenTheTemplatesVariablesAre(new List())) + .And(x => x.ThenTheTemplatesVariablesAre(new List())) .BDDfy(); } @@ -66,16 +141,16 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder.UrlMatcher this.Given(x => x.GivenIHaveAUpstreamPath("api/product/products/")) .Given(x => x.GivenIHaveAnUpstreamUrlTemplate("api/product/products/")) .When(x => x.WhenIFindTheUrlVariableNamesAndValues()) - .And(x => x.ThenTheTemplatesVariablesAre(new List())) + .And(x => x.ThenTheTemplatesVariablesAre(new List())) .BDDfy(); } [Fact] public void can_match_down_stream_url_with_downstream_template_with_one_place_holder() { - var expectedTemplates = new List + var expectedTemplates = new List { - new UrlPathPlaceholderNameAndValue("{productId}", "1") + new PlaceholderNameAndValue("{productId}", "1") }; this.Given(x => x.GivenIHaveAUpstreamPath("api/product/products/1")) @@ -88,10 +163,10 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder.UrlMatcher [Fact] public void can_match_down_stream_url_with_downstream_template_with_two_place_holders() { - var expectedTemplates = new List + var expectedTemplates = new List { - new UrlPathPlaceholderNameAndValue("{productId}", "1"), - new UrlPathPlaceholderNameAndValue("{categoryId}", "2") + new PlaceholderNameAndValue("{productId}", "1"), + new PlaceholderNameAndValue("{categoryId}", "2") }; this.Given(x => x.GivenIHaveAUpstreamPath("api/product/products/1/2")) @@ -104,10 +179,10 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder.UrlMatcher [Fact] public void can_match_down_stream_url_with_downstream_template_with_two_place_holders_seperated_by_something() { - var expectedTemplates = new List + var expectedTemplates = new List { - new UrlPathPlaceholderNameAndValue("{productId}", "1"), - new UrlPathPlaceholderNameAndValue("{categoryId}", "2") + new PlaceholderNameAndValue("{productId}", "1"), + new PlaceholderNameAndValue("{categoryId}", "2") }; this.Given(x => x.GivenIHaveAUpstreamPath("api/product/products/1/categories/2")) @@ -120,11 +195,11 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder.UrlMatcher [Fact] public void can_match_down_stream_url_with_downstream_template_with_three_place_holders_seperated_by_something() { - var expectedTemplates = new List + var expectedTemplates = new List { - new UrlPathPlaceholderNameAndValue("{productId}", "1"), - new UrlPathPlaceholderNameAndValue("{categoryId}", "2"), - new UrlPathPlaceholderNameAndValue("{variantId}", "123") + new PlaceholderNameAndValue("{productId}", "1"), + new PlaceholderNameAndValue("{categoryId}", "2"), + new PlaceholderNameAndValue("{variantId}", "123") }; this.Given(x => x.GivenIHaveAUpstreamPath("api/product/products/1/categories/2/variant/123")) @@ -137,10 +212,10 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder.UrlMatcher [Fact] public void can_match_down_stream_url_with_downstream_template_with_three_place_holders() { - var expectedTemplates = new List + var expectedTemplates = new List { - new UrlPathPlaceholderNameAndValue("{productId}", "1"), - new UrlPathPlaceholderNameAndValue("{categoryId}", "2") + new PlaceholderNameAndValue("{productId}", "1"), + new PlaceholderNameAndValue("{categoryId}", "2") }; this.Given(x => x.GivenIHaveAUpstreamPath("api/product/products/1/categories/2/variant/")) @@ -153,9 +228,9 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder.UrlMatcher [Fact] public void can_match_down_stream_url_with_downstream_template_with_place_holder_to_final_url_path() { - var expectedTemplates = new List + var expectedTemplates = new List { - new UrlPathPlaceholderNameAndValue("{finalUrlPath}", "product/products/categories/"), + new PlaceholderNameAndValue("{finalUrlPath}", "product/products/categories/"), }; this.Given(x => x.GivenIHaveAUpstreamPath("api/product/products/categories/")) @@ -165,13 +240,12 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder.UrlMatcher .BDDfy(); } - private void ThenTheTemplatesVariablesAre(List expectedResults) + private void ThenTheTemplatesVariablesAre(List expectedResults) { foreach (var expectedResult in expectedResults) { - var result = _result.Data - .First(t => t.TemplateVariableName == expectedResult.TemplateVariableName); - result.TemplateVariableValue.ShouldBe(expectedResult.TemplateVariableValue); + var result = _result.Data.First(t => t.Name == expectedResult.Name); + result.Value.ShouldBe(expectedResult.Value); } } diff --git a/test/Ocelot.UnitTests/DownstreamUrlCreator/DownstreamUrlCreatorMiddlewareTests.cs b/test/Ocelot.UnitTests/DownstreamUrlCreator/DownstreamUrlCreatorMiddlewareTests.cs index 1af70f71..04afdf3a 100644 --- a/test/Ocelot.UnitTests/DownstreamUrlCreator/DownstreamUrlCreatorMiddlewareTests.cs +++ b/test/Ocelot.UnitTests/DownstreamUrlCreator/DownstreamUrlCreatorMiddlewareTests.cs @@ -47,7 +47,7 @@ { this.Given(x => x.GivenTheDownStreamRouteIs( new DownstreamRoute( - new List(), + new List(), new ReRouteBuilder() .WithDownstreamPathTemplate("any old string") .WithUpstreamHttpMethod(new List { "Get" }) @@ -91,7 +91,7 @@ { _downstreamPath = new OkResponse(new DownstreamPath(path)); _downstreamUrlTemplateVariableReplacer - .Setup(x => x.Replace(It.IsAny(), It.IsAny>())) + .Setup(x => x.Replace(It.IsAny(), It.IsAny>())) .Returns(_downstreamPath); } diff --git a/test/Ocelot.UnitTests/DownstreamUrlCreator/UrlTemplateReplacer/UpstreamUrlPathTemplateVariableReplacerTests.cs b/test/Ocelot.UnitTests/DownstreamUrlCreator/UrlTemplateReplacer/UpstreamUrlPathTemplateVariableReplacerTests.cs index 4939c901..7aa8fc16 100644 --- a/test/Ocelot.UnitTests/DownstreamUrlCreator/UrlTemplateReplacer/UpstreamUrlPathTemplateVariableReplacerTests.cs +++ b/test/Ocelot.UnitTests/DownstreamUrlCreator/UrlTemplateReplacer/UpstreamUrlPathTemplateVariableReplacerTests.cs @@ -27,7 +27,7 @@ namespace Ocelot.UnitTests.DownstreamUrlCreator.UrlTemplateReplacer { this.Given(x => x.GivenThereIsAUrlMatch( new DownstreamRoute( - new List(), + new List(), new ReRouteBuilder() .WithUpstreamHttpMethod(new List { "Get" }) .Build()))) @@ -41,7 +41,7 @@ namespace Ocelot.UnitTests.DownstreamUrlCreator.UrlTemplateReplacer { this.Given(x => x.GivenThereIsAUrlMatch( new DownstreamRoute( - new List(), + new List(), new ReRouteBuilder() .WithDownstreamPathTemplate("/") .WithUpstreamHttpMethod(new List { "Get" }) @@ -54,7 +54,7 @@ namespace Ocelot.UnitTests.DownstreamUrlCreator.UrlTemplateReplacer [Fact] public void can_replace_url_no_slash() { - this.Given(x => x.GivenThereIsAUrlMatch(new DownstreamRoute(new List(), + this.Given(x => x.GivenThereIsAUrlMatch(new DownstreamRoute(new List(), new ReRouteBuilder() .WithDownstreamPathTemplate("api") .WithUpstreamHttpMethod(new List { "Get" }) @@ -67,7 +67,7 @@ namespace Ocelot.UnitTests.DownstreamUrlCreator.UrlTemplateReplacer [Fact] public void can_replace_url_one_slash() { - this.Given(x => x.GivenThereIsAUrlMatch(new DownstreamRoute(new List(), + this.Given(x => x.GivenThereIsAUrlMatch(new DownstreamRoute(new List(), new ReRouteBuilder() .WithDownstreamPathTemplate("api/") .WithUpstreamHttpMethod(new List { "Get" }) @@ -80,7 +80,7 @@ namespace Ocelot.UnitTests.DownstreamUrlCreator.UrlTemplateReplacer [Fact] public void can_replace_url_multiple_slash() { - this.Given(x => x.GivenThereIsAUrlMatch(new DownstreamRoute(new List(), + this.Given(x => x.GivenThereIsAUrlMatch(new DownstreamRoute(new List(), new ReRouteBuilder() .WithDownstreamPathTemplate("api/product/products/") .WithUpstreamHttpMethod(new List { "Get" }) @@ -93,9 +93,9 @@ namespace Ocelot.UnitTests.DownstreamUrlCreator.UrlTemplateReplacer [Fact] public void can_replace_url_one_template_variable() { - var templateVariables = new List() + var templateVariables = new List() { - new UrlPathPlaceholderNameAndValue("{productId}", "1") + new PlaceholderNameAndValue("{productId}", "1") }; this.Given(x => x.GivenThereIsAUrlMatch(new DownstreamRoute(templateVariables, @@ -111,9 +111,9 @@ namespace Ocelot.UnitTests.DownstreamUrlCreator.UrlTemplateReplacer [Fact] public void can_replace_url_one_template_variable_with_path_after() { - var templateVariables = new List() + var templateVariables = new List() { - new UrlPathPlaceholderNameAndValue("{productId}", "1") + new PlaceholderNameAndValue("{productId}", "1") }; this.Given(x => x.GivenThereIsAUrlMatch(new DownstreamRoute(templateVariables, @@ -129,10 +129,10 @@ namespace Ocelot.UnitTests.DownstreamUrlCreator.UrlTemplateReplacer [Fact] public void can_replace_url_two_template_variable() { - var templateVariables = new List() + var templateVariables = new List() { - new UrlPathPlaceholderNameAndValue("{productId}", "1"), - new UrlPathPlaceholderNameAndValue("{variantId}", "12") + new PlaceholderNameAndValue("{productId}", "1"), + new PlaceholderNameAndValue("{variantId}", "12") }; this.Given(x => x.GivenThereIsAUrlMatch(new DownstreamRoute(templateVariables, @@ -148,11 +148,11 @@ namespace Ocelot.UnitTests.DownstreamUrlCreator.UrlTemplateReplacer [Fact] public void can_replace_url_three_template_variable() { - var templateVariables = new List() + var templateVariables = new List() { - new UrlPathPlaceholderNameAndValue("{productId}", "1"), - new UrlPathPlaceholderNameAndValue("{variantId}", "12"), - new UrlPathPlaceholderNameAndValue("{categoryId}", "34") + new PlaceholderNameAndValue("{productId}", "1"), + new PlaceholderNameAndValue("{variantId}", "12"), + new PlaceholderNameAndValue("{categoryId}", "34") }; this.Given(x => x.GivenThereIsAUrlMatch(new DownstreamRoute(templateVariables, diff --git a/test/Ocelot.UnitTests/Headers/HttpRequestHeadersBuilderMiddlewareTests.cs b/test/Ocelot.UnitTests/Headers/HttpRequestHeadersBuilderMiddlewareTests.cs index 76a75d0a..20dbe84d 100644 --- a/test/Ocelot.UnitTests/Headers/HttpRequestHeadersBuilderMiddlewareTests.cs +++ b/test/Ocelot.UnitTests/Headers/HttpRequestHeadersBuilderMiddlewareTests.cs @@ -37,7 +37,7 @@ [Fact] public void should_call_add_headers_to_request_correctly() { - var downstreamRoute = new DownstreamRoute(new List(), + var downstreamRoute = new DownstreamRoute(new List(), new ReRouteBuilder() .WithDownstreamPathTemplate("any old string") .WithClaimsToHeaders(new List diff --git a/test/Ocelot.UnitTests/LoadBalancer/LoadBalancerMiddlewareTests.cs b/test/Ocelot.UnitTests/LoadBalancer/LoadBalancerMiddlewareTests.cs index 002e64a0..936e9249 100644 --- a/test/Ocelot.UnitTests/LoadBalancer/LoadBalancerMiddlewareTests.cs +++ b/test/Ocelot.UnitTests/LoadBalancer/LoadBalancerMiddlewareTests.cs @@ -47,7 +47,7 @@ namespace Ocelot.UnitTests.LoadBalancer [Fact] public void should_call_scoped_data_repository_correctly() { - var downstreamRoute = new DownstreamRoute(new List(), + var downstreamRoute = new DownstreamRoute(new List(), new ReRouteBuilder() .WithUpstreamHttpMethod(new List { "Get" }) .Build()); @@ -68,7 +68,7 @@ namespace Ocelot.UnitTests.LoadBalancer [Fact] public void should_set_pipeline_error_if_cannot_get_load_balancer() { - var downstreamRoute = new DownstreamRoute(new List(), + var downstreamRoute = new DownstreamRoute(new List(), new ReRouteBuilder() .WithUpstreamHttpMethod(new List { "Get" }) .Build()); @@ -88,7 +88,7 @@ namespace Ocelot.UnitTests.LoadBalancer [Fact] public void should_set_pipeline_error_if_cannot_get_least() { - var downstreamRoute = new DownstreamRoute(new List(), + var downstreamRoute = new DownstreamRoute(new List(), new ReRouteBuilder() .WithUpstreamHttpMethod(new List { "Get" }) .Build()); diff --git a/test/Ocelot.UnitTests/QueryStrings/QueryStringBuilderMiddlewareTests.cs b/test/Ocelot.UnitTests/QueryStrings/QueryStringBuilderMiddlewareTests.cs index 4bbcfd2c..a4a3b197 100644 --- a/test/Ocelot.UnitTests/QueryStrings/QueryStringBuilderMiddlewareTests.cs +++ b/test/Ocelot.UnitTests/QueryStrings/QueryStringBuilderMiddlewareTests.cs @@ -37,7 +37,7 @@ [Fact] public void should_call_add_queries_correctly() { - var downstreamRoute = new DownstreamRoute(new List(), + var downstreamRoute = new DownstreamRoute(new List(), new ReRouteBuilder() .WithDownstreamPathTemplate("any old string") .WithClaimsToQueries(new List diff --git a/test/Ocelot.UnitTests/RateLimit/ClientRateLimitMiddlewareTests.cs b/test/Ocelot.UnitTests/RateLimit/ClientRateLimitMiddlewareTests.cs index 1b73e233..e832760b 100644 --- a/test/Ocelot.UnitTests/RateLimit/ClientRateLimitMiddlewareTests.cs +++ b/test/Ocelot.UnitTests/RateLimit/ClientRateLimitMiddlewareTests.cs @@ -31,7 +31,7 @@ [Fact] public void should_call_middleware_and_ratelimiting() { - var downstreamRoute = new DownstreamRoute(new List(), + var downstreamRoute = new DownstreamRoute(new List(), new ReRouteBuilder().WithEnableRateLimiting(true).WithRateLimitOptions( new Ocelot.Configuration.RateLimitOptions(true, "ClientId", new List(), false, "", "", new Ocelot.Configuration.RateLimitRule("1s", 100, 3), 429)) .WithUpstreamHttpMethod(new List { "Get" }) @@ -48,7 +48,7 @@ [Fact] public void should_call_middleware_withWhitelistClient() { - var downstreamRoute = new DownstreamRoute(new List(), + var downstreamRoute = new DownstreamRoute(new List(), new ReRouteBuilder().WithEnableRateLimiting(true).WithRateLimitOptions( new Ocelot.Configuration.RateLimitOptions(true, "ClientId", new List() { "ocelotclient2" }, false, "", "", new RateLimitRule( "1s", 100,3),429)) .WithUpstreamHttpMethod(new List { "Get" }) diff --git a/test/Ocelot.UnitTests/Request/HttpRequestBuilderMiddlewareTests.cs b/test/Ocelot.UnitTests/Request/HttpRequestBuilderMiddlewareTests.cs index 4c72d137..10cbc120 100644 --- a/test/Ocelot.UnitTests/Request/HttpRequestBuilderMiddlewareTests.cs +++ b/test/Ocelot.UnitTests/Request/HttpRequestBuilderMiddlewareTests.cs @@ -47,7 +47,7 @@ public void should_call_scoped_data_repository_correctly() { - var downstreamRoute = new DownstreamRoute(new List(), + var downstreamRoute = new DownstreamRoute(new List(), new ReRouteBuilder() .WithRequestIdKey("LSRequestId") .WithUpstreamHttpMethod(new List { "Get" }) diff --git a/test/Ocelot.UnitTests/RequestId/RequestIdMiddlewareTests.cs b/test/Ocelot.UnitTests/RequestId/RequestIdMiddlewareTests.cs index a34290f1..4d684084 100644 --- a/test/Ocelot.UnitTests/RequestId/RequestIdMiddlewareTests.cs +++ b/test/Ocelot.UnitTests/RequestId/RequestIdMiddlewareTests.cs @@ -40,7 +40,7 @@ [Fact] public void should_pass_down_request_id_from_upstream_request() { - var downstreamRoute = new DownstreamRoute(new List(), + var downstreamRoute = new DownstreamRoute(new List(), new ReRouteBuilder() .WithDownstreamPathTemplate("any old string") .WithRequestIdKey("LSRequestId") @@ -59,7 +59,7 @@ [Fact] public void should_add_request_id_when_not_on_upstream_request() { - var downstreamRoute = new DownstreamRoute(new List(), + var downstreamRoute = new DownstreamRoute(new List(), new ReRouteBuilder() .WithDownstreamPathTemplate("any old string") .WithRequestIdKey("LSRequestId")