diff --git a/src/Ocelot.Library/Infrastructure/Configuration/Configuration.cs b/src/Ocelot.Library/Infrastructure/Configuration/Configuration.cs new file mode 100644 index 00000000..f1cc9b90 --- /dev/null +++ b/src/Ocelot.Library/Infrastructure/Configuration/Configuration.cs @@ -0,0 +1,14 @@ +using System.Collections.Generic; + +namespace Ocelot.Library.Infrastructure.Configuration +{ + public class Configuration + { + public Configuration() + { + ReRoutes = new List(); + } + + public List ReRoutes { get; set; } + } +} diff --git a/src/Ocelot.Library/Infrastructure/Configuration/ReRoute.cs b/src/Ocelot.Library/Infrastructure/Configuration/ReRoute.cs new file mode 100644 index 00000000..4c27ec37 --- /dev/null +++ b/src/Ocelot.Library/Infrastructure/Configuration/ReRoute.cs @@ -0,0 +1,8 @@ +namespace Ocelot.Library.Infrastructure.Configuration +{ + public class ReRoute + { + public string DownstreamTemplate { get; set; } + public string UpstreamTemplate { get; set; } + } +} diff --git a/src/Ocelot.Library/Infrastructure/DownstreamRouteFinder/DownstreamRoute.cs b/src/Ocelot.Library/Infrastructure/DownstreamRouteFinder/DownstreamRoute.cs new file mode 100644 index 00000000..b88f0063 --- /dev/null +++ b/src/Ocelot.Library/Infrastructure/DownstreamRouteFinder/DownstreamRoute.cs @@ -0,0 +1,16 @@ +using System.Collections.Generic; +using Ocelot.Library.Infrastructure.UrlMatcher; + +namespace Ocelot.Library.Infrastructure.DownstreamRouteFinder +{ + public class DownstreamRoute + { + public DownstreamRoute(List templateVariableNameAndValues, string downstreamUrlTemplate) + { + TemplateVariableNameAndValues = templateVariableNameAndValues; + DownstreamUrlTemplate = downstreamUrlTemplate; + } + public List TemplateVariableNameAndValues { get; private set; } + public string DownstreamUrlTemplate { get; private set; } + } +} \ No newline at end of file diff --git a/src/Ocelot.Library/Infrastructure/DownstreamRouteFinder/DownstreamRouteFinder.cs b/src/Ocelot.Library/Infrastructure/DownstreamRouteFinder/DownstreamRouteFinder.cs new file mode 100644 index 00000000..63ddfacd --- /dev/null +++ b/src/Ocelot.Library/Infrastructure/DownstreamRouteFinder/DownstreamRouteFinder.cs @@ -0,0 +1,38 @@ +using System.Collections.Generic; +using Microsoft.Extensions.Options; +using Ocelot.Library.Infrastructure.Responses; +using Ocelot.Library.Infrastructure.UrlMatcher; + +namespace Ocelot.Library.Infrastructure.DownstreamRouteFinder +{ + public class DownstreamRouteFinder : IDownstreamRouteFinder + { + private readonly IOptions _configuration; + private readonly IUrlPathToUrlTemplateMatcher _urlMatcher; + + public DownstreamRouteFinder(IOptions configuration, IUrlPathToUrlTemplateMatcher urlMatcher) + { + _configuration = configuration; + _urlMatcher = urlMatcher; + } + + public Response FindDownstreamRoute(string upstreamUrlPath) + { + + foreach (var template in _configuration.Value.ReRoutes) + { + var urlMatch = _urlMatcher.Match(upstreamUrlPath, template.UpstreamTemplate); + + if (urlMatch.Match) + { + return new OkResponse(new DownstreamRoute(urlMatch.TemplateVariableNameAndValues, template.DownstreamTemplate)); + } + } + + return new ErrorResponse(new List + { + new UnableToFindDownstreamRouteError() + }); + } + } +} \ No newline at end of file diff --git a/src/Ocelot.Library/Infrastructure/DownstreamRouteFinder/IDownstreamRouteFinder.cs b/src/Ocelot.Library/Infrastructure/DownstreamRouteFinder/IDownstreamRouteFinder.cs new file mode 100644 index 00000000..1394b3af --- /dev/null +++ b/src/Ocelot.Library/Infrastructure/DownstreamRouteFinder/IDownstreamRouteFinder.cs @@ -0,0 +1,9 @@ +using Ocelot.Library.Infrastructure.Responses; + +namespace Ocelot.Library.Infrastructure.DownstreamRouteFinder +{ + public interface IDownstreamRouteFinder + { + Response FindDownstreamRoute(string upstreamUrlPath); + } +} diff --git a/src/Ocelot.Library/Infrastructure/DownstreamRouteFinder/UnableToFindDownstreamRouteError.cs b/src/Ocelot.Library/Infrastructure/DownstreamRouteFinder/UnableToFindDownstreamRouteError.cs new file mode 100644 index 00000000..62618951 --- /dev/null +++ b/src/Ocelot.Library/Infrastructure/DownstreamRouteFinder/UnableToFindDownstreamRouteError.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Ocelot.Library.Infrastructure.Responses; + +namespace Ocelot.Library.Infrastructure.DownstreamRouteFinder +{ + public class UnableToFindDownstreamRouteError : Error + { + public UnableToFindDownstreamRouteError() : base("UnableToFindDownstreamRouteError") + { + } + } +} diff --git a/src/Ocelot.Library/Infrastructure/HostUrlRepository/HostUrlMap.cs b/src/Ocelot.Library/Infrastructure/HostUrlRepository/HostUrlMap.cs deleted file mode 100644 index a9b6ce61..00000000 --- a/src/Ocelot.Library/Infrastructure/HostUrlRepository/HostUrlMap.cs +++ /dev/null @@ -1,14 +0,0 @@ -namespace Ocelot.Library.Infrastructure.HostUrlRepository -{ - public class HostUrlMap - { - public HostUrlMap(string urlPathTemplate, string upstreamHostUrl) - { - UrlPathTemplate = urlPathTemplate; - UpstreamHostUrl = upstreamHostUrl; - } - - public string UrlPathTemplate {get;private set;} - public string UpstreamHostUrl {get;private set;} - } -} \ No newline at end of file diff --git a/src/Ocelot.Library/Infrastructure/HostUrlRepository/HostUrlMapKeyAlreadyExists.cs b/src/Ocelot.Library/Infrastructure/HostUrlRepository/HostUrlMapKeyAlreadyExists.cs deleted file mode 100644 index 236cac79..00000000 --- a/src/Ocelot.Library/Infrastructure/HostUrlRepository/HostUrlMapKeyAlreadyExists.cs +++ /dev/null @@ -1,12 +0,0 @@ -using Ocelot.Library.Infrastructure.Responses; - -namespace Ocelot.Library.Infrastructure.HostUrlRepository -{ - public class HostUrlMapKeyAlreadyExists : Error - { - public HostUrlMapKeyAlreadyExists() - : base("This key has already been used") - { - } - } -} \ No newline at end of file diff --git a/src/Ocelot.Library/Infrastructure/HostUrlRepository/HostUrlMapKeyDoesNotExist.cs b/src/Ocelot.Library/Infrastructure/HostUrlRepository/HostUrlMapKeyDoesNotExist.cs deleted file mode 100644 index 913f2b67..00000000 --- a/src/Ocelot.Library/Infrastructure/HostUrlRepository/HostUrlMapKeyDoesNotExist.cs +++ /dev/null @@ -1,12 +0,0 @@ -using Ocelot.Library.Infrastructure.Responses; - -namespace Ocelot.Library.Infrastructure.HostUrlRepository -{ - public class HostUrlMapKeyDoesNotExist : Error - { - public HostUrlMapKeyDoesNotExist() - : base("This key does not exist") - { - } - } -} \ No newline at end of file diff --git a/src/Ocelot.Library/Infrastructure/HostUrlRepository/IHostUrlMapRepository.cs b/src/Ocelot.Library/Infrastructure/HostUrlRepository/IHostUrlMapRepository.cs deleted file mode 100644 index da78044c..00000000 --- a/src/Ocelot.Library/Infrastructure/HostUrlRepository/IHostUrlMapRepository.cs +++ /dev/null @@ -1,10 +0,0 @@ -using Ocelot.Library.Infrastructure.Responses; - -namespace Ocelot.Library.Infrastructure.HostUrlRepository -{ - public interface IHostUrlMapRepository - { - Response AddBaseUrlMap(HostUrlMap baseUrlMap); - Response GetBaseUrlMap(string urlPathTemplate); - } -} \ No newline at end of file diff --git a/src/Ocelot.Library/Infrastructure/HostUrlRepository/InMemoryHostUrlMapRepository.cs b/src/Ocelot.Library/Infrastructure/HostUrlRepository/InMemoryHostUrlMapRepository.cs deleted file mode 100644 index 61b45ebf..00000000 --- a/src/Ocelot.Library/Infrastructure/HostUrlRepository/InMemoryHostUrlMapRepository.cs +++ /dev/null @@ -1,37 +0,0 @@ -using System.Collections.Generic; -using Ocelot.Library.Infrastructure.Responses; - -namespace Ocelot.Library.Infrastructure.HostUrlRepository -{ - public class InMemoryHostUrlMapRepository : IHostUrlMapRepository - { - private readonly Dictionary _routes; - public InMemoryHostUrlMapRepository() - { - _routes = new Dictionary(); - } - public Response AddBaseUrlMap(HostUrlMap baseUrlMap) - { - if(_routes.ContainsKey(baseUrlMap.UrlPathTemplate)) - { - return new ErrorResponse(new List(){new HostUrlMapKeyAlreadyExists()}); - } - - _routes.Add(baseUrlMap.UrlPathTemplate, baseUrlMap.UpstreamHostUrl); - - return new OkResponse(); - } - - public Response GetBaseUrlMap(string urlPathTemplate) - { - string upstreamUrl = null; - - if(_routes.TryGetValue(urlPathTemplate, out upstreamUrl)) - { - return new OkResponse(new HostUrlMap(urlPathTemplate, upstreamUrl)); - } - - return new ErrorResponse(new List(){new HostUrlMapKeyDoesNotExist()}); - } - } -} \ No newline at end of file diff --git a/src/Ocelot.Library/Infrastructure/UrlFinder/IUpstreamHostUrlFinder.cs b/src/Ocelot.Library/Infrastructure/UrlFinder/IUpstreamHostUrlFinder.cs deleted file mode 100644 index 84a78493..00000000 --- a/src/Ocelot.Library/Infrastructure/UrlFinder/IUpstreamHostUrlFinder.cs +++ /dev/null @@ -1,9 +0,0 @@ -using Ocelot.Library.Infrastructure.Responses; - -namespace Ocelot.Library.Infrastructure.UrlFinder -{ - public interface IUpstreamHostUrlFinder - { - Response FindUpstreamHostUrl(string downstreamHostUrl); - } -} diff --git a/src/Ocelot.Library/Infrastructure/UrlFinder/UnableToFindUpstreamHostUrl.cs b/src/Ocelot.Library/Infrastructure/UrlFinder/UnableToFindUpstreamHostUrl.cs deleted file mode 100644 index 10defcee..00000000 --- a/src/Ocelot.Library/Infrastructure/UrlFinder/UnableToFindUpstreamHostUrl.cs +++ /dev/null @@ -1,12 +0,0 @@ -using Ocelot.Library.Infrastructure.Responses; - -namespace Ocelot.Library.Infrastructure.UrlFinder -{ - public class UnableToFindUpstreamHostUrl : Error - { - public UnableToFindUpstreamHostUrl() - : base("Unable to find upstream base url") - { - } - } -} \ No newline at end of file diff --git a/src/Ocelot.Library/Infrastructure/UrlFinder/UpstreamHostUrlFinder.cs b/src/Ocelot.Library/Infrastructure/UrlFinder/UpstreamHostUrlFinder.cs deleted file mode 100644 index 555eb3d2..00000000 --- a/src/Ocelot.Library/Infrastructure/UrlFinder/UpstreamHostUrlFinder.cs +++ /dev/null @@ -1,28 +0,0 @@ -using System; -using System.Collections.Generic; -using Ocelot.Library.Infrastructure.HostUrlRepository; -using Ocelot.Library.Infrastructure.Responses; - -namespace Ocelot.Library.Infrastructure.UrlFinder -{ - public class UpstreamHostUrlFinder : IUpstreamHostUrlFinder - { - private readonly IHostUrlMapRepository _hostUrlMapRepository; - - public UpstreamHostUrlFinder(IHostUrlMapRepository hostUrlMapRepository) - { - _hostUrlMapRepository = hostUrlMapRepository; - } - public Response FindUpstreamHostUrl(string downstreamBaseUrl) - { - var baseUrl = _hostUrlMapRepository.GetBaseUrlMap(downstreamBaseUrl); - - if(baseUrl.IsError) - { - return new ErrorResponse(new List {new UnableToFindUpstreamHostUrl()}); - } - - return new OkResponse(baseUrl.Data.UpstreamHostUrl); - } - } -} \ No newline at end of file diff --git a/src/Ocelot.Library/Infrastructure/UrlMatcher/IUrlPathToUrlTemplateMatcher.cs b/src/Ocelot.Library/Infrastructure/UrlMatcher/IUrlPathToUrlTemplateMatcher.cs new file mode 100644 index 00000000..954e3fee --- /dev/null +++ b/src/Ocelot.Library/Infrastructure/UrlMatcher/IUrlPathToUrlTemplateMatcher.cs @@ -0,0 +1,7 @@ +namespace Ocelot.Library.Infrastructure.UrlMatcher +{ + public interface IUrlPathToUrlTemplateMatcher + { + UrlMatch Match(string upstreamUrlPath, string upstreamUrlTemplate); + } +} \ No newline at end of file diff --git a/src/Ocelot.Library/Infrastructure/UrlPathMatcher/TemplateVariableNameAndValue.cs b/src/Ocelot.Library/Infrastructure/UrlMatcher/TemplateVariableNameAndValue.cs similarity index 88% rename from src/Ocelot.Library/Infrastructure/UrlPathMatcher/TemplateVariableNameAndValue.cs rename to src/Ocelot.Library/Infrastructure/UrlMatcher/TemplateVariableNameAndValue.cs index f65ab514..07935d08 100644 --- a/src/Ocelot.Library/Infrastructure/UrlPathMatcher/TemplateVariableNameAndValue.cs +++ b/src/Ocelot.Library/Infrastructure/UrlMatcher/TemplateVariableNameAndValue.cs @@ -1,4 +1,4 @@ -namespace Ocelot.Library.Infrastructure.UrlPathMatcher +namespace Ocelot.Library.Infrastructure.UrlMatcher { public class TemplateVariableNameAndValue { diff --git a/src/Ocelot.Library/Infrastructure/UrlMatcher/UrlMatch.cs b/src/Ocelot.Library/Infrastructure/UrlMatcher/UrlMatch.cs new file mode 100644 index 00000000..0eb4cb47 --- /dev/null +++ b/src/Ocelot.Library/Infrastructure/UrlMatcher/UrlMatch.cs @@ -0,0 +1,17 @@ +using System.Collections.Generic; + +namespace Ocelot.Library.Infrastructure.UrlMatcher +{ + public class UrlMatch + { + public UrlMatch(bool match, List templateVariableNameAndValues, string downstreamUrlTemplate) + { + Match = match; + TemplateVariableNameAndValues = templateVariableNameAndValues; + DownstreamUrlTemplate = downstreamUrlTemplate; + } + public bool Match {get;private set;} + public List TemplateVariableNameAndValues {get;private set;} + public string DownstreamUrlTemplate {get;private set;} + } +} \ No newline at end of file diff --git a/src/Ocelot.Library/Infrastructure/UrlPathMatcher/UrlPathToUrlPathTemplateMatcher.cs b/src/Ocelot.Library/Infrastructure/UrlMatcher/UrlPathToUrlTemplateMatcher.cs similarity index 70% rename from src/Ocelot.Library/Infrastructure/UrlPathMatcher/UrlPathToUrlPathTemplateMatcher.cs rename to src/Ocelot.Library/Infrastructure/UrlMatcher/UrlPathToUrlTemplateMatcher.cs index 3b2152e8..0c396e32 100644 --- a/src/Ocelot.Library/Infrastructure/UrlPathMatcher/UrlPathToUrlPathTemplateMatcher.cs +++ b/src/Ocelot.Library/Infrastructure/UrlMatcher/UrlPathToUrlTemplateMatcher.cs @@ -1,46 +1,46 @@ using System; using System.Collections.Generic; -namespace Ocelot.Library.Infrastructure.UrlPathMatcher +namespace Ocelot.Library.Infrastructure.UrlMatcher { - public class UrlPathToUrlPathTemplateMatcher : IUrlPathToUrlPathTemplateMatcher + public class UrlPathToUrlTemplateMatcher : IUrlPathToUrlTemplateMatcher { - public UrlPathMatch Match(string downstreamUrlPath, string downstreamUrlPathTemplate) + public UrlMatch Match(string upstreamUrlPath, string upstreamUrlTemplate) { - var urlPathTemplateCopy = downstreamUrlPathTemplate; + var urlPathTemplateCopy = upstreamUrlTemplate; var templateKeysAndValues = new List(); int counterForUrl = 0; - for (int counterForTemplate = 0; counterForTemplate < downstreamUrlPathTemplate.Length; counterForTemplate++) + for (int counterForTemplate = 0; counterForTemplate < upstreamUrlTemplate.Length; counterForTemplate++) { - if (CharactersDontMatch(downstreamUrlPathTemplate[counterForTemplate], downstreamUrlPath[counterForUrl]) && ContinueScanningUrl(counterForUrl,downstreamUrlPath.Length)) + if (CharactersDontMatch(upstreamUrlTemplate[counterForTemplate], upstreamUrlPath[counterForUrl]) && ContinueScanningUrl(counterForUrl,upstreamUrlPath.Length)) { - if (IsPlaceholder(downstreamUrlPathTemplate[counterForTemplate])) + if (IsPlaceholder(upstreamUrlTemplate[counterForTemplate])) { - var variableName = GetPlaceholderVariableName(downstreamUrlPathTemplate, counterForTemplate); + var variableName = GetPlaceholderVariableName(upstreamUrlTemplate, counterForTemplate); - var variableValue = GetPlaceholderVariableValue(downstreamUrlPath, counterForUrl); + var variableValue = GetPlaceholderVariableValue(upstreamUrlPath, counterForUrl); var templateVariableNameAndValue = new TemplateVariableNameAndValue(variableName, variableValue); templateKeysAndValues.Add(templateVariableNameAndValue); - counterForTemplate = GetNextCounterPosition(downstreamUrlPathTemplate, counterForTemplate, '}'); + counterForTemplate = GetNextCounterPosition(upstreamUrlTemplate, counterForTemplate, '}'); - counterForUrl = GetNextCounterPosition(downstreamUrlPath, counterForUrl, '/'); + counterForUrl = GetNextCounterPosition(upstreamUrlPath, counterForUrl, '/'); continue; } else { - return new UrlPathMatch(false, templateKeysAndValues, string.Empty); + return new UrlMatch(false, templateKeysAndValues, string.Empty); } } counterForUrl++; } - return new UrlPathMatch(true, templateKeysAndValues, urlPathTemplateCopy); + return new UrlMatch(true, templateKeysAndValues, urlPathTemplateCopy); } private string GetPlaceholderVariableValue(string urlPath, int counterForUrl) diff --git a/src/Ocelot.Library/Infrastructure/UrlPathMatcher/IUrlPathToUrlPathTemplateMatcher.cs b/src/Ocelot.Library/Infrastructure/UrlPathMatcher/IUrlPathToUrlPathTemplateMatcher.cs deleted file mode 100644 index 5ed4d637..00000000 --- a/src/Ocelot.Library/Infrastructure/UrlPathMatcher/IUrlPathToUrlPathTemplateMatcher.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace Ocelot.Library.Infrastructure.UrlPathMatcher -{ - public interface IUrlPathToUrlPathTemplateMatcher - { - UrlPathMatch Match(string downstreamUrlPath, string downStreamUrlPathTemplate); - } -} \ No newline at end of file diff --git a/src/Ocelot.Library/Infrastructure/UrlPathMatcher/UrlPathMatch.cs b/src/Ocelot.Library/Infrastructure/UrlPathMatcher/UrlPathMatch.cs deleted file mode 100644 index 7f474e62..00000000 --- a/src/Ocelot.Library/Infrastructure/UrlPathMatcher/UrlPathMatch.cs +++ /dev/null @@ -1,17 +0,0 @@ -using System.Collections.Generic; - -namespace Ocelot.Library.Infrastructure.UrlPathMatcher -{ - public class UrlPathMatch - { - public UrlPathMatch(bool match, List templateVariableNameAndValues, string downstreamUrlPathTemplate) - { - Match = match; - TemplateVariableNameAndValues = templateVariableNameAndValues; - DownstreamUrlPathTemplate = downstreamUrlPathTemplate; - } - public bool Match {get;private set;} - public List TemplateVariableNameAndValues {get;private set;} - public string DownstreamUrlPathTemplate {get;private set;} - } -} \ No newline at end of file diff --git a/src/Ocelot.Library/Infrastructure/UrlPathReplacer/IUpstreamUrlPathTemplateVariableReplacer.cs b/src/Ocelot.Library/Infrastructure/UrlPathReplacer/IUpstreamUrlPathTemplateVariableReplacer.cs deleted file mode 100644 index cb455185..00000000 --- a/src/Ocelot.Library/Infrastructure/UrlPathReplacer/IUpstreamUrlPathTemplateVariableReplacer.cs +++ /dev/null @@ -1,10 +0,0 @@ -using Ocelot.Library.Infrastructure.UrlPathMatcher; - -namespace Ocelot.Library.Infrastructure.UrlPathReplacer -{ - public interface IUpstreamUrlPathTemplateVariableReplacer - { - string ReplaceTemplateVariable(string upstreamPathTemplate, UrlPathMatch urlPathMatch); - - } -} \ No newline at end of file diff --git a/src/Ocelot.Library/Infrastructure/UrlPathReplacer/UpstreamUrlPathTemplateVariableReplacer.cs b/src/Ocelot.Library/Infrastructure/UrlPathReplacer/UpstreamUrlPathTemplateVariableReplacer.cs deleted file mode 100644 index b52ea69e..00000000 --- a/src/Ocelot.Library/Infrastructure/UrlPathReplacer/UpstreamUrlPathTemplateVariableReplacer.cs +++ /dev/null @@ -1,22 +0,0 @@ -using System; -using System.Text; -using Ocelot.Library.Infrastructure.UrlPathMatcher; - -namespace Ocelot.Library.Infrastructure.UrlPathReplacer -{ - public class UpstreamUrlPathTemplateVariableReplacer : IUpstreamUrlPathTemplateVariableReplacer - { - public string ReplaceTemplateVariable(string upstreamPathTemplate, UrlPathMatch urlPathMatch) - { - var upstreamUrl = new StringBuilder(); - upstreamUrl.Append(upstreamPathTemplate); - - foreach (var templateVarAndValue in urlPathMatch.TemplateVariableNameAndValues) - { - upstreamUrl.Replace(templateVarAndValue.TemplateVariableName, templateVarAndValue.TemplateVariableValue); - } - - return upstreamUrl.ToString(); - } - } -} \ No newline at end of file diff --git a/src/Ocelot.Library/Infrastructure/UrlPathTemplateRepository/DownstreamUrlPathAlreadyExists.cs b/src/Ocelot.Library/Infrastructure/UrlPathTemplateRepository/DownstreamUrlPathAlreadyExists.cs deleted file mode 100644 index 05a552ac..00000000 --- a/src/Ocelot.Library/Infrastructure/UrlPathTemplateRepository/DownstreamUrlPathAlreadyExists.cs +++ /dev/null @@ -1,12 +0,0 @@ -using Ocelot.Library.Infrastructure.Responses; - -namespace Ocelot.Library.Infrastructure.UrlPathTemplateRepository -{ - public class DownstreamUrlPathTemplateAlreadyExists : Error - { - public DownstreamUrlPathTemplateAlreadyExists() - : base("This key has already been used") - { - } - } -} \ No newline at end of file diff --git a/src/Ocelot.Library/Infrastructure/UrlPathTemplateRepository/DownstreamUrlPathDoesNotExist.cs b/src/Ocelot.Library/Infrastructure/UrlPathTemplateRepository/DownstreamUrlPathDoesNotExist.cs deleted file mode 100644 index 7d89beeb..00000000 --- a/src/Ocelot.Library/Infrastructure/UrlPathTemplateRepository/DownstreamUrlPathDoesNotExist.cs +++ /dev/null @@ -1,12 +0,0 @@ -using Ocelot.Library.Infrastructure.Responses; - -namespace Ocelot.Library.Infrastructure.UrlPathTemplateRepository -{ - public class DownstreamUrlPathTemplateDoesNotExist : Error - { - public DownstreamUrlPathTemplateDoesNotExist() - : base("This key does not exist") - { - } - } -} \ No newline at end of file diff --git a/src/Ocelot.Library/Infrastructure/UrlPathTemplateRepository/IUrlPathTemplateMapRepository.cs b/src/Ocelot.Library/Infrastructure/UrlPathTemplateRepository/IUrlPathTemplateMapRepository.cs deleted file mode 100644 index b63ecfc6..00000000 --- a/src/Ocelot.Library/Infrastructure/UrlPathTemplateRepository/IUrlPathTemplateMapRepository.cs +++ /dev/null @@ -1,12 +0,0 @@ -using System.Collections.Generic; -using Ocelot.Library.Infrastructure.Responses; - -namespace Ocelot.Library.Infrastructure.UrlPathTemplateRepository -{ - public interface IUrlPathTemplateMapRepository - { - Response AddUrlPathTemplateMap(UrlPathTemplateMap urlPathMap); - Response GetUrlPathTemplateMap(string downstreamUrlPathTemplate); - Response> All { get; } - } -} \ No newline at end of file diff --git a/src/Ocelot.Library/Infrastructure/UrlPathTemplateRepository/InMemoryUrlPathTemplateMapRepository.cs b/src/Ocelot.Library/Infrastructure/UrlPathTemplateRepository/InMemoryUrlPathTemplateMapRepository.cs deleted file mode 100644 index b56c6b95..00000000 --- a/src/Ocelot.Library/Infrastructure/UrlPathTemplateRepository/InMemoryUrlPathTemplateMapRepository.cs +++ /dev/null @@ -1,51 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using Ocelot.Library.Infrastructure.Responses; - -namespace Ocelot.Library.Infrastructure.UrlPathTemplateRepository -{ - public class InMemoryUrlPathTemplateMapRepository : IUrlPathTemplateMapRepository - { - private readonly Dictionary _routes; - public InMemoryUrlPathTemplateMapRepository() - { - _routes = new Dictionary(); - } - - public Response> All - { - get - { - var routes = _routes - .Select(r => new UrlPathTemplateMap(r.Key, r.Value)) - .ToList(); - return new OkResponse>(routes); - } - } - - public Response AddUrlPathTemplateMap(UrlPathTemplateMap urlPathMap) - { - if(_routes.ContainsKey(urlPathMap.DownstreamUrlPathTemplate)) - { - return new ErrorResponse(new List(){new DownstreamUrlPathTemplateAlreadyExists()}); - } - - _routes.Add(urlPathMap.DownstreamUrlPathTemplate, urlPathMap.UpstreamUrlPathTemplate); - - return new OkResponse(); - } - - public Response GetUrlPathTemplateMap(string downstreamUrlPathTemplate) - { - string upstreamUrlPathTemplate = null; - - if(_routes.TryGetValue(downstreamUrlPathTemplate, out upstreamUrlPathTemplate)) - { - return new OkResponse(new UrlPathTemplateMap(downstreamUrlPathTemplate, upstreamUrlPathTemplate)); - } - - return new ErrorResponse(new List(){new DownstreamUrlPathTemplateDoesNotExist()}); - } - } -} \ No newline at end of file diff --git a/src/Ocelot.Library/Infrastructure/UrlPathTemplateRepository/UrlPathTemplateMap.cs b/src/Ocelot.Library/Infrastructure/UrlPathTemplateRepository/UrlPathTemplateMap.cs deleted file mode 100644 index 1471813c..00000000 --- a/src/Ocelot.Library/Infrastructure/UrlPathTemplateRepository/UrlPathTemplateMap.cs +++ /dev/null @@ -1,14 +0,0 @@ -namespace Ocelot.Library.Infrastructure.UrlPathTemplateRepository -{ - public class UrlPathTemplateMap - { - public UrlPathTemplateMap(string downstreamUrlPathTemplate, string upstreamUrlPathTemplate) - { - DownstreamUrlPathTemplate = downstreamUrlPathTemplate; - UpstreamUrlPathTemplate = upstreamUrlPathTemplate; - } - - public string DownstreamUrlPathTemplate {get;private set;} - public string UpstreamUrlPathTemplate {get;private set;} - } -} \ No newline at end of file diff --git a/src/Ocelot.Library/Infrastructure/UrlTemplateReplacer/DownstreamUrlTemplateVariableReplacer.cs b/src/Ocelot.Library/Infrastructure/UrlTemplateReplacer/DownstreamUrlTemplateVariableReplacer.cs new file mode 100644 index 00000000..204eb212 --- /dev/null +++ b/src/Ocelot.Library/Infrastructure/UrlTemplateReplacer/DownstreamUrlTemplateVariableReplacer.cs @@ -0,0 +1,22 @@ +using System.Text; +using Ocelot.Library.Infrastructure.DownstreamRouteFinder; + +namespace Ocelot.Library.Infrastructure.UrlTemplateReplacer +{ + public class DownstreamUrlTemplateVariableReplacer : IDownstreamUrlTemplateVariableReplacer + { + public string ReplaceTemplateVariable(DownstreamRoute downstreamRoute) + { + var upstreamUrl = new StringBuilder(); + + upstreamUrl.Append(downstreamRoute.DownstreamUrlTemplate); + + foreach (var templateVarAndValue in downstreamRoute.TemplateVariableNameAndValues) + { + upstreamUrl.Replace(templateVarAndValue.TemplateVariableName, templateVarAndValue.TemplateVariableValue); + } + + return upstreamUrl.ToString(); + } + } +} \ No newline at end of file diff --git a/src/Ocelot.Library/Infrastructure/UrlTemplateReplacer/IDownstreamUrlPathTemplateVariableReplacer.cs b/src/Ocelot.Library/Infrastructure/UrlTemplateReplacer/IDownstreamUrlPathTemplateVariableReplacer.cs new file mode 100644 index 00000000..bc50a8fa --- /dev/null +++ b/src/Ocelot.Library/Infrastructure/UrlTemplateReplacer/IDownstreamUrlPathTemplateVariableReplacer.cs @@ -0,0 +1,10 @@ +using Ocelot.Library.Infrastructure.DownstreamRouteFinder; +using Ocelot.Library.Infrastructure.UrlMatcher; + +namespace Ocelot.Library.Infrastructure.UrlTemplateReplacer +{ + public interface IDownstreamUrlTemplateVariableReplacer + { + string ReplaceTemplateVariable(DownstreamRoute downstreamRoute); + } +} \ No newline at end of file diff --git a/src/Ocelot.Library/Middleware/ProxyMiddleware.cs b/src/Ocelot.Library/Middleware/ProxyMiddleware.cs index a56fbd17..1dd90dc6 100644 --- a/src/Ocelot.Library/Middleware/ProxyMiddleware.cs +++ b/src/Ocelot.Library/Middleware/ProxyMiddleware.cs @@ -1,67 +1,62 @@ -using System; +using System.Net; +using System.Net.Http; using System.Threading.Tasks; using Microsoft.AspNetCore.Http; -using Ocelot.Library.Infrastructure.HostUrlRepository; -using Ocelot.Library.Infrastructure.UrlPathMatcher; -using Ocelot.Library.Infrastructure.UrlPathReplacer; -using Ocelot.Library.Infrastructure.UrlPathTemplateRepository; +using Microsoft.Extensions.Options; +using Ocelot.Library.Infrastructure.Configuration; +using Ocelot.Library.Infrastructure.DownstreamRouteFinder; +using Ocelot.Library.Infrastructure.UrlTemplateReplacer; namespace Ocelot.Library.Middleware { - using System.Net; - public class ProxyMiddleware { private readonly RequestDelegate _next; - private readonly IUrlPathToUrlPathTemplateMatcher _urlMatcher; - private readonly IUrlPathTemplateMapRepository _urlPathRepository; - private readonly IHostUrlMapRepository _hostUrlRepository; - private readonly IUpstreamUrlPathTemplateVariableReplacer _urlReplacer; + private readonly IDownstreamUrlTemplateVariableReplacer _urlReplacer; + private readonly IOptions _configuration; + private readonly IDownstreamRouteFinder _downstreamRouteFinder; + public ProxyMiddleware(RequestDelegate next, - IUrlPathToUrlPathTemplateMatcher urlMatcher, - IUrlPathTemplateMapRepository urlPathRepository, - IHostUrlMapRepository hostUrlRepository, - IUpstreamUrlPathTemplateVariableReplacer urlReplacer) + IDownstreamUrlTemplateVariableReplacer urlReplacer, + IOptions configuration, + IDownstreamRouteFinder downstreamRouteFinder) { _next = next; - _urlMatcher = urlMatcher; - _urlPathRepository = urlPathRepository; - _hostUrlRepository = hostUrlRepository; _urlReplacer = urlReplacer; + _configuration = configuration; + _downstreamRouteFinder = downstreamRouteFinder; } public async Task Invoke(HttpContext context) - { - - var path = context.Request.Path.ToString(); + { + var upstreamUrlPath = context.Request.Path.ToString(); - var urlPathTemplateMaps = _urlPathRepository.All; + var downstreamRoute = _downstreamRouteFinder.FindDownstreamRoute(upstreamUrlPath); - UrlPathMatch urlPathMatch = null; - string upstreamPathUrlTemplate = string.Empty; - - foreach (var template in urlPathTemplateMaps.Data) - { - urlPathMatch = _urlMatcher.Match(path, template.DownstreamUrlPathTemplate); - - if (urlPathMatch.Match) - { - upstreamPathUrlTemplate = template.UpstreamUrlPathTemplate; - break; - } - } - - if (urlPathMatch == null || !urlPathMatch.Match) + if (downstreamRoute.IsError) { context.Response.StatusCode = (int)HttpStatusCode.NotFound; return; } - - var upstreamHostUrl = _hostUrlRepository.GetBaseUrlMap(urlPathMatch.DownstreamUrlPathTemplate); - var pathUrl = _urlReplacer.ReplaceTemplateVariable(upstreamPathUrlTemplate, urlPathMatch); + var downstreamUrl = _urlReplacer.ReplaceTemplateVariable(downstreamRoute.Data); //make a http request to this endpoint...maybe bring in a library + using (var httpClient = new HttpClient()) + { + var httpMethod = new HttpMethod(context.Request.Method); + + var httpRequestMessage = new HttpRequestMessage(httpMethod, downstreamUrl); + + var response = await httpClient.SendAsync(httpRequestMessage); + + if (!response.IsSuccessStatusCode) + { + context.Response.StatusCode = (int)response.StatusCode; + return; + } + await context.Response.WriteAsync(await response.Content.ReadAsStringAsync()); + } await _next.Invoke(context); } diff --git a/src/Ocelot.Library/project.json b/src/Ocelot.Library/project.json index ca884c95..7037f0a7 100644 --- a/src/Ocelot.Library/project.json +++ b/src/Ocelot.Library/project.json @@ -1,23 +1,24 @@ { "version": "1.0.0-*", - "dependencies": { - "Microsoft.NETCore.App": { - "version": "1.0.0", - "type": "platform" - }, - "Microsoft.AspNetCore.Mvc": "1.0.0", - "Microsoft.AspNetCore.Server.IISIntegration": "1.0.0", - "Microsoft.AspNetCore.Server.Kestrel": "1.0.0", - "Microsoft.Extensions.Configuration.EnvironmentVariables": "1.0.0", - "Microsoft.Extensions.Configuration.FileExtensions": "1.0.0", - "Microsoft.Extensions.Configuration.Json": "1.0.0", - "Microsoft.Extensions.Logging": "1.0.0", - "Microsoft.Extensions.Logging.Console": "1.0.0", - "Microsoft.Extensions.Logging.Debug": "1.0.0", - "Microsoft.Extensions.Options.ConfigurationExtensions": "1.0.0", - "Microsoft.AspNetCore.Http": "1.0.0" + "dependencies": { + "Microsoft.NETCore.App": { + "version": "1.0.0", + "type": "platform" }, + "Microsoft.AspNetCore.Mvc": "1.0.0", + "Microsoft.AspNetCore.Server.IISIntegration": "1.0.0", + "Microsoft.AspNetCore.Server.Kestrel": "1.0.0", + "Microsoft.Extensions.Configuration.EnvironmentVariables": "1.0.0", + "Microsoft.Extensions.Configuration.FileExtensions": "1.0.0", + "Microsoft.Extensions.Configuration.Json": "1.0.0", + "Microsoft.Extensions.Logging": "1.0.0", + "Microsoft.Extensions.Logging.Console": "1.0.0", + "Microsoft.Extensions.Logging.Debug": "1.0.0", + "Microsoft.Extensions.Options.ConfigurationExtensions": "1.0.0", + "Microsoft.AspNetCore.Http": "1.0.0", + "YamlDotNet": "3.9.0" + }, "frameworks": { "netcoreapp1.0": { diff --git a/src/Ocelot/Startup.cs b/src/Ocelot/Startup.cs index d95b6f65..18d5ba6b 100644 --- a/src/Ocelot/Startup.cs +++ b/src/Ocelot/Startup.cs @@ -1,17 +1,16 @@ using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; -using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; +using Ocelot.Library.Infrastructure.DownstreamRouteFinder; using Ocelot.Library.Middleware; namespace Ocelot { - using Library.Infrastructure.HostUrlRepository; - using Library.Infrastructure.UrlPathMatcher; - using Library.Infrastructure.UrlPathReplacer; - using Library.Infrastructure.UrlPathTemplateRepository; + using Library.Infrastructure.Configuration; + using Library.Infrastructure.UrlMatcher; + using Library.Infrastructure.UrlTemplateReplacer; public class Startup { @@ -21,6 +20,7 @@ namespace Ocelot .SetBasePath(env.ContentRootPath) .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true) .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true) + .AddYamlFile("configuration.yaml") .AddEnvironmentVariables(); Configuration = builder.Build(); } @@ -30,12 +30,14 @@ namespace Ocelot // This method gets called by the runtime. Use this method to add services to the container. public void ConfigureServices(IServiceCollection services) { + services.AddOptions(); + + services.Configure(Configuration); + // Add framework services. - services.AddSingleton(); - services.AddSingleton(); - services.AddSingleton(); - services.AddSingleton(); - services.AddSingleton(); + services.AddSingleton(); + services.AddSingleton(); + services.AddSingleton(); } // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. diff --git a/src/Ocelot/project.json b/src/Ocelot/project.json index ba309f23..d77d3493 100644 --- a/src/Ocelot/project.json +++ b/src/Ocelot/project.json @@ -15,7 +15,8 @@ "Microsoft.Extensions.Logging.Console": "1.0.0", "Microsoft.Extensions.Logging.Debug": "1.0.0", "Microsoft.Extensions.Options.ConfigurationExtensions": "1.0.0", - "Ocelot.Library": "1.0.0-*" + "Ocelot.Library": "1.0.0-*", + "NetEscapades.Configuration.Yaml": "1.1.0" }, "tools": { diff --git a/test/Ocelot.AcceptanceTests/OcelotTests.cs b/test/Ocelot.AcceptanceTests/OcelotTests.cs new file mode 100644 index 00000000..6eea27ab --- /dev/null +++ b/test/Ocelot.AcceptanceTests/OcelotTests.cs @@ -0,0 +1,113 @@ +namespace Ocelot.AcceptanceTests +{ + using System; + using System.Net.Http; + using Microsoft.AspNetCore.Hosting; + using Microsoft.AspNetCore.TestHost; + using Xunit; + using Ocelot.AcceptanceTests.Fake; + using Shouldly; + using System.Collections.Generic; + using System.IO; + using System.Net; + using Library.Infrastructure.Configuration; + using TestStack.BDDfy; + using YamlDotNet.Serialization; + + public class OcelotTests : IDisposable + { + private readonly FakeService _fakeService; + private TestServer _server; + private HttpClient _client; + private HttpResponseMessage _response; + + public OcelotTests() + { + _fakeService = new FakeService(); + } + + [Fact] + public void should_return_response_404() + { + this.Given(x => x.GivenTheApiGatewayIsRunning()) + .When(x => x.WhenIRequestTheUrlOnTheApiGateway("/")) + .Then(x => x.ThenTheStatusCodeShouldBe(HttpStatusCode.NotFound)) + .BDDfy(); + } + + [Fact] + public void should_return_response_200() + { + this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:51879")) + .And(x => x.GivenThereIsAConfiguration(new Configuration + { + ReRoutes = new List + { + new ReRoute + { + DownstreamTemplate = "http://localhost:51879/", + UpstreamTemplate = "/" + } + } + })) + .And(x => x.GivenTheApiGatewayIsRunning()) + .When(x => x.WhenIRequestTheUrlOnTheApiGateway("/")) + .Then(x => x.ThenTheStatusCodeShouldBe(HttpStatusCode.OK)) + .And(x => x.ThenTheResponseBodyShouldBe("Hello from Laura")) + .BDDfy(); + } + + /// + /// This is annoying cos it should be in the constructor but we need to set up the yaml file before calling startup so its a step. + /// + private void GivenTheApiGatewayIsRunning() + { + _server = new TestServer(new WebHostBuilder() + .UseStartup()); + + _client = _server.CreateClient(); + } + + private void GivenThereIsAConfiguration(Configuration configuration) + { + var serializer = new Serializer(); + + if (File.Exists("./configuration.yaml")) + { + File.Delete("./configuration.yaml"); + } + + using (TextWriter writer = File.CreateText("./configuration.yaml")) + { + serializer.Serialize(writer, configuration); + } + } + + private void GivenThereIsAServiceRunningOn(string url) + { + _fakeService.Start(url); + } + + private void WhenIRequestTheUrlOnTheApiGateway(string url) + { + _response = _client.GetAsync(url).Result; + } + + private void ThenTheStatusCodeShouldBe(HttpStatusCode expectedHttpStatusCode) + { + _response.StatusCode.ShouldBe(expectedHttpStatusCode); + } + + private void ThenTheResponseBodyShouldBe(string expectedBody) + { + _response.Content.ReadAsStringAsync().Result.ShouldBe(expectedBody); + } + + public void Dispose() + { + _fakeService.Stop(); + _client.Dispose(); + _server.Dispose(); + } + } +} diff --git a/test/Ocelot.AcceptanceTests/RouterTests.cs b/test/Ocelot.AcceptanceTests/RouterTests.cs deleted file mode 100644 index 2d4d2c4e..00000000 --- a/test/Ocelot.AcceptanceTests/RouterTests.cs +++ /dev/null @@ -1,56 +0,0 @@ -using System; -using System.Net.Http; -using Microsoft.AspNetCore.Hosting; -using Microsoft.AspNetCore.TestHost; -using Xunit; -using Ocelot.AcceptanceTests.Fake; -using Shouldly; - -namespace Ocelot.AcceptanceTests -{ - using System.Net; - using TestStack.BDDfy; - - public class RouterTests : IDisposable - { - private readonly FakeService _fakeService; - private readonly TestServer _server; - private readonly HttpClient _client; - private HttpResponseMessage _response; - - public RouterTests() - { - _server = new TestServer(new WebHostBuilder() - .UseStartup()); - - _client = _server.CreateClient(); - - _fakeService = new FakeService(); - } - - [Fact] - public void should_return_response_404() - { - this.When(x => x.WhenIRequestTheUrl("/")) - .Then(x => x.ThenTheStatusCodeShouldBe(HttpStatusCode.NotFound)) - .BDDfy(); - } - - private void WhenIRequestTheUrl(string url) - { - _response = _client.GetAsync("/").Result; - } - - private void ThenTheStatusCodeShouldBe(HttpStatusCode expectedHttpStatusCode) - { - _response.StatusCode.ShouldBe(expectedHttpStatusCode); - } - - public void Dispose() - { - _fakeService.Stop(); - _client.Dispose(); - _server.Dispose(); - } - } -} diff --git a/test/Ocelot.AcceptanceTests/configuration.yaml b/test/Ocelot.AcceptanceTests/configuration.yaml new file mode 100644 index 00000000..97b35e41 --- /dev/null +++ b/test/Ocelot.AcceptanceTests/configuration.yaml @@ -0,0 +1,3 @@ +ReRoutes: +- DownstreamTemplate: http://localhost:51879/ + UpstreamTemplate: / diff --git a/test/Ocelot.AcceptanceTests/project.json b/test/Ocelot.AcceptanceTests/project.json index c350a62b..c672997c 100644 --- a/test/Ocelot.AcceptanceTests/project.json +++ b/test/Ocelot.AcceptanceTests/project.json @@ -1,39 +1,48 @@ { - "version": "1.0.0-*", + "version": "1.0.0-*", - "testRunner": "xunit", - - "dependencies": { - "Microsoft.NETCore.App": { - "version": "1.0.0", - "type": "platform" - }, - "Microsoft.AspNetCore.Mvc": "1.0.0", - "Microsoft.AspNetCore.Server.IISIntegration": "1.0.0", - "Microsoft.AspNetCore.Server.Kestrel": "1.0.0", - "Microsoft.Extensions.Configuration.EnvironmentVariables": "1.0.0", - "Microsoft.Extensions.Configuration.FileExtensions": "1.0.0", - "Microsoft.Extensions.Configuration.Json": "1.0.0", - "Microsoft.Extensions.Logging": "1.0.0", - "Microsoft.Extensions.Logging.Console": "1.0.0", - "Microsoft.Extensions.Logging.Debug": "1.0.0", - "Microsoft.Extensions.Options.ConfigurationExtensions": "1.0.0", - "Microsoft.AspNetCore.Http": "1.0.0", - "Ocelot.Library": "1.0.0-*", - "xunit": "2.1.0", - "dotnet-test-xunit": "2.2.0-preview2-build1029", - "Shouldly": "2.8.0", - "Ocelot": "1.0.0-*", - "Microsoft.AspNetCore.TestHost": "1.0.0", - "TestStack.BDDfy": "4.3.1" - }, - - "frameworks": { - "netcoreapp1.0": { - "imports": [ - "dotnet5.6", - "portable-net45+win8" - ] - } + "buildOptions": { + "copyToOutput": { + "include": [ + "configuration.yaml" + ] } + }, + + "testRunner": "xunit", + + "dependencies": { + "Microsoft.NETCore.App": { + "version": "1.0.0", + "type": "platform" + }, + "Microsoft.AspNetCore.Mvc": "1.0.0", + "Microsoft.AspNetCore.Server.IISIntegration": "1.0.0", + "Microsoft.AspNetCore.Server.Kestrel": "1.0.0", + "Microsoft.Extensions.Configuration.EnvironmentVariables": "1.0.0", + "Microsoft.Extensions.Configuration.FileExtensions": "1.0.0", + "Microsoft.Extensions.Configuration.Json": "1.0.0", + "Microsoft.Extensions.Logging": "1.0.0", + "Microsoft.Extensions.Logging.Console": "1.0.0", + "Microsoft.Extensions.Logging.Debug": "1.0.0", + "Microsoft.Extensions.Options.ConfigurationExtensions": "1.0.0", + "Microsoft.AspNetCore.Http": "1.0.0", + "Ocelot.Library": "1.0.0-*", + "xunit": "2.1.0", + "dotnet-test-xunit": "2.2.0-preview2-build1029", + "Shouldly": "2.8.0", + "Ocelot": "1.0.0-*", + "Microsoft.AspNetCore.TestHost": "1.0.0", + "TestStack.BDDfy": "4.3.1", + "YamlDotNet": "3.9.0" + }, + + "frameworks": { + "netcoreapp1.0": { + "imports": [ + "dotnet5.6", + "portable-net45+win8" + ] + } + } } diff --git a/test/Ocelot.UnitTests/DownstreamRouteFinderTests.cs b/test/Ocelot.UnitTests/DownstreamRouteFinderTests.cs new file mode 100644 index 00000000..212e2029 --- /dev/null +++ b/test/Ocelot.UnitTests/DownstreamRouteFinderTests.cs @@ -0,0 +1,132 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.Extensions.Options; +using Moq; +using Ocelot.Library.Infrastructure.Configuration; +using Ocelot.Library.Infrastructure.DownstreamRouteFinder; +using Ocelot.Library.Infrastructure.Responses; +using Ocelot.Library.Infrastructure.UrlMatcher; +using Shouldly; +using TestStack.BDDfy; +using Xunit; + +namespace Ocelot.UnitTests +{ + public class DownstreamRouteFinderTests + { + private readonly IDownstreamRouteFinder _downstreamRouteFinder; + private readonly Mock> _mockConfig; + private readonly Mock _mockMatcher; + private string _upstreamUrlPath; + private Response _result; + private Response _response; + private Configuration _configuration; + private UrlMatch _match; + + public DownstreamRouteFinderTests() + { + _mockConfig = new Mock>(); + _mockMatcher = new Mock(); + _downstreamRouteFinder = new DownstreamRouteFinder(_mockConfig.Object, _mockMatcher.Object); + } + + [Fact] + public void should_return_route() + { + this.Given(x => x.GivenThereIsAnUpstreamUrlPath("somePath")) + .And(x => x.GivenTheConfigurationIs(new Configuration { + ReRoutes = new List + { + new ReRoute() + { + UpstreamTemplate = "somePath", + DownstreamTemplate = "somPath" + } + } + })) + .And(x => x.GivenTheUrlMatcherReturns(new UrlMatch(true, new List(), "somePath"))) + .When(x => x.WhenICallTheFinder()) + .Then( + x => x.ThenTheFollowingIsReturned(new DownstreamRoute(new List(), "somePath"))) + .And(x => x.ThenTheUrlMatcherIsCalledCorrectly()) + .BDDfy(); + } + + [Fact] + public void should_not_return_route() + { + this.Given(x => x.GivenThereIsAnUpstreamUrlPath("somePath")) + .And(x => x.GivenTheConfigurationIs(new Configuration + { + ReRoutes = new List + { + new ReRoute() + { + UpstreamTemplate = "somePath", + DownstreamTemplate = "somPath" + } + } + })) + .And(x => x.GivenTheUrlMatcherReturns(new UrlMatch(false, new List(), null))) + .When(x => x.WhenICallTheFinder()) + .Then( + x => x.ThenAnErrorResponseIsReturned()) + .And(x => x.ThenTheUrlMatcherIsCalledCorrectly()) + .BDDfy(); + } + + private void ThenAnErrorResponseIsReturned() + { + _result.IsError.ShouldBeTrue(); + } + + private void ThenTheUrlMatcherIsCalledCorrectly() + { + _mockMatcher + .Verify(x => x.Match(_upstreamUrlPath, _configuration.ReRoutes[0].UpstreamTemplate), Times.Once); + } + + private void GivenTheUrlMatcherReturns(UrlMatch match) + { + _match = match; + _mockMatcher + .Setup(x => x.Match(It.IsAny(), It.IsAny())) + .Returns(_match); + } + + private void GivenTheConfigurationIs(Configuration configuration) + { + _configuration = configuration; + _mockConfig + .Setup(x => x.Value) + .Returns(_configuration); + } + + private void GivenThereIsAnUpstreamUrlPath(string upstreamUrlPath) + { + _upstreamUrlPath = upstreamUrlPath; + } + + private void WhenICallTheFinder() + { + _result = _downstreamRouteFinder.FindDownstreamRoute(_upstreamUrlPath); + } + + private void ThenTheFollowingIsReturned(DownstreamRoute expected) + { + _result.Data.DownstreamUrlTemplate.ShouldBe(expected.DownstreamUrlTemplate); + for (int i = 0; i < _result.Data.TemplateVariableNameAndValues.Count; i++) + { + _result.Data.TemplateVariableNameAndValues[i].TemplateVariableName.ShouldBe( + expected.TemplateVariableNameAndValues[i].TemplateVariableName); + + _result.Data.TemplateVariableNameAndValues[i].TemplateVariableValue.ShouldBe( + expected.TemplateVariableNameAndValues[i].TemplateVariableValue); + } + + _result.IsError.ShouldBeFalse(); + } + } +} diff --git a/test/Ocelot.UnitTests/HostUrlMapRepositoryTests.cs b/test/Ocelot.UnitTests/HostUrlMapRepositoryTests.cs deleted file mode 100644 index 045dfab1..00000000 --- a/test/Ocelot.UnitTests/HostUrlMapRepositoryTests.cs +++ /dev/null @@ -1,117 +0,0 @@ -using Ocelot.Library.Infrastructure.Responses; -using Ocelot.Library.Infrastructure.HostUrlRepository; -using Shouldly; -using Xunit; - -namespace Ocelot.UnitTests -{ - using TestStack.BDDfy; - - public class HostUrlMapRepositoryTests - { - private string _upstreamBaseUrl; - private string _downstreamBaseUrl; - private readonly IHostUrlMapRepository _repository; - private Response _response; - private Response _getRouteResponse; - - public HostUrlMapRepositoryTests() - { - _repository = new InMemoryHostUrlMapRepository(); - } - - [Fact] - public void can_add_route() - { - this.Given(x => x.GivenIHaveAnUpstreamBaseUrl("www.someapi.com")) - .And(x => x.GivenIWantToRouteRequestsFromMyDownstreamBaseUrl("api")) - .When(x => x.WhenIAddTheConfiguration()) - .Then(x => x.ThenTheResponseIsSuccesful()) - .BDDfy(); - } - - [Fact] - public void can_get_route_by_key() - { - this.Given(x => x.GivenIHaveSetUpAnApiKeyAndUpstreamUrl("api2", "www.someapi.com")) - .When(x => x.WhenIRetrieveTheRouteByKey()) - .Then(x => x.ThenTheRouteIsReturned()) - .BDDfy(); - } - - [Fact] - public void should_return_error_response_when_key_already_used() - { - this.Given(x => x.GivenIHaveSetUpAnApiKeyAndUpstreamUrl("api2", "www.someapi.com")) - .When(x => x.WhenITryToUseTheSameKey()) - .Then(x => x.ThenTheKeyHasAlreadyBeenUsed()) - .BDDfy(); - } - - [Fact] - public void should_return_error_response_if_key_doesnt_exist() - { - this.Given(x => x.GivenIWantToRouteRequestsFromMyDownstreamBaseUrl("api")) - .When(x => x.WhenIRetrieveTheRouteByKey()) - .Then(x => x.ThenTheKeyDoesNotExist()) - .BDDfy(); - } - - private void WhenITryToUseTheSameKey() - { - WhenIAddTheConfiguration(); - } - - private void ThenTheKeyHasAlreadyBeenUsed() - { - _response.ShouldNotBeNull(); - _response.ShouldBeOfType(); - _response.Errors[0].Message.ShouldBe("This key has already been used"); - } - - private void ThenTheKeyDoesNotExist() - { - _getRouteResponse.ShouldNotBeNull(); - _getRouteResponse.ShouldBeOfType>(); - _getRouteResponse.Errors[0].Message.ShouldBe("This key does not exist"); - } - - private void WhenIRetrieveTheRouteByKey() - { - _getRouteResponse = _repository.GetBaseUrlMap(_downstreamBaseUrl); - } - - private void ThenTheRouteIsReturned() - { - _getRouteResponse.Data.UrlPathTemplate.ShouldBe(_downstreamBaseUrl); - _getRouteResponse.Data.UpstreamHostUrl.ShouldBe(_upstreamBaseUrl); - } - - private void GivenIHaveSetUpAnApiKeyAndUpstreamUrl(string apiKey, string upstreamUrl) - { - GivenIHaveAnUpstreamBaseUrl(upstreamUrl); - GivenIWantToRouteRequestsFromMyDownstreamBaseUrl(apiKey); - WhenIAddTheConfiguration(); - } - - private void GivenIHaveAnUpstreamBaseUrl(string upstreamApiUrl) - { - _upstreamBaseUrl = upstreamApiUrl; - } - - private void GivenIWantToRouteRequestsFromMyDownstreamBaseUrl(string downstreamBaseUrl) - { - _downstreamBaseUrl = downstreamBaseUrl; - } - - private void WhenIAddTheConfiguration() - { - _response = _repository.AddBaseUrlMap(new HostUrlMap(_downstreamBaseUrl, _upstreamBaseUrl)); - } - - private void ThenTheResponseIsSuccesful() - { - _response.ShouldBeOfType(); - } - } -} \ No newline at end of file diff --git a/test/Ocelot.UnitTests/UpstreamBaseUrlFinderTests.cs b/test/Ocelot.UnitTests/UpstreamBaseUrlFinderTests.cs deleted file mode 100644 index 6a36b312..00000000 --- a/test/Ocelot.UnitTests/UpstreamBaseUrlFinderTests.cs +++ /dev/null @@ -1,68 +0,0 @@ -using Ocelot.Library.Infrastructure.HostUrlRepository; -using Ocelot.Library.Infrastructure.UrlFinder; -using Ocelot.Library.Infrastructure.Responses; -using Xunit; -using Shouldly; -using TestStack.BDDfy; - -namespace Ocelot.UnitTests -{ - public class UpstreamBaseUrlFinderTests - { - private readonly IUpstreamHostUrlFinder _upstreamBaseUrlFinder; - private readonly IHostUrlMapRepository _hostUrlMapRepository; - private string _downstreamBaseUrl; - private Response _result; - public UpstreamBaseUrlFinderTests() - { - _hostUrlMapRepository = new InMemoryHostUrlMapRepository(); - _upstreamBaseUrlFinder = new UpstreamHostUrlFinder(_hostUrlMapRepository); - } - - [Fact] - public void can_find_base_url() - { - this.Given(x => x.GivenTheBaseUrlMapExists(new HostUrlMap("api.tom.com", "api.laura.com"))) - .And(x => x.GivenTheDownstreamBaseUrlIs("api.tom.com")) - .When(x => x.WhenIFindTheMatchingUpstreamBaseUrl()) - .Then(x => x.ThenTheFollowingIsReturned("api.laura.com")) - .BDDfy(); - } - - [Fact] - public void cant_find_base_url() - { - this.Given(x => x.GivenTheDownstreamBaseUrlIs("api.tom.com")) - .When(x => x.WhenIFindTheMatchingUpstreamBaseUrl()) - .Then(x => x.ThenAnErrorIsReturned()) - .BDDfy(); - } - - private void ThenAnErrorIsReturned() - { - _result.Errors.Count.ShouldBe(1); - } - - private void GivenTheBaseUrlMapExists(HostUrlMap baseUrlMap) - { - _hostUrlMapRepository.AddBaseUrlMap(baseUrlMap); - - } - - private void GivenTheDownstreamBaseUrlIs(string downstreamBaseUrl) - { - _downstreamBaseUrl = downstreamBaseUrl; - } - - private void WhenIFindTheMatchingUpstreamBaseUrl() - { - _result = _upstreamBaseUrlFinder.FindUpstreamHostUrl(_downstreamBaseUrl); - - } - - private void ThenTheFollowingIsReturned(string expectedBaseUrl) - { - _result.Data.ShouldBe(expectedBaseUrl); - } - } -} \ No newline at end of file diff --git a/test/Ocelot.UnitTests/UpstreamUrlPathTemplateVariableReplacerTests.cs b/test/Ocelot.UnitTests/UpstreamUrlPathTemplateVariableReplacerTests.cs index fd4deacf..b280e04f 100644 --- a/test/Ocelot.UnitTests/UpstreamUrlPathTemplateVariableReplacerTests.cs +++ b/test/Ocelot.UnitTests/UpstreamUrlPathTemplateVariableReplacerTests.cs @@ -1,6 +1,7 @@ using System.Collections.Generic; -using Ocelot.Library.Infrastructure.UrlPathMatcher; -using Ocelot.Library.Infrastructure.UrlPathReplacer; +using Ocelot.Library.Infrastructure.DownstreamRouteFinder; +using Ocelot.Library.Infrastructure.UrlMatcher; +using Ocelot.Library.Infrastructure.UrlTemplateReplacer; using Shouldly; using Xunit; @@ -10,53 +11,57 @@ namespace Ocelot.UnitTests public class UpstreamUrlPathTemplateVariableReplacerTests { - private string _upstreamUrlPath; - private UrlPathMatch _urlPathMatch; + private DownstreamRoute _downstreamRoute; private string _result; - private readonly IUpstreamUrlPathTemplateVariableReplacer _upstreamUrlPathReplacer; + private readonly IDownstreamUrlTemplateVariableReplacer _downstreamUrlPathReplacer; public UpstreamUrlPathTemplateVariableReplacerTests() { - _upstreamUrlPathReplacer = new UpstreamUrlPathTemplateVariableReplacer(); + _downstreamUrlPathReplacer = new DownstreamUrlTemplateVariableReplacer(); } [Fact] public void can_replace_no_template_variables() { - this.Given(x => x.GivenThereIsAnUpstreamUrlPath("")) - .And(x => x.GivenThereIsAUrlPathMatch(new UrlPathMatch(true, new List(), ""))) + this.Given(x => x.GivenThereIsAUrlMatch(new DownstreamRoute(new List(), ""))) .When(x => x.WhenIReplaceTheTemplateVariables()) - .Then(x => x.ThenTheUpstreamUrlPathIsReturned("")) + .Then(x => x.ThenTheDownstreamUrlPathIsReturned("")) + .BDDfy(); + } + + [Fact] + public void can_replace_no_template_variables_with_slash() + { + this.Given(x => x.GivenThereIsAUrlMatch(new DownstreamRoute(new List(), "/"))) + .When(x => x.WhenIReplaceTheTemplateVariables()) + .Then(x => x.ThenTheDownstreamUrlPathIsReturned("/")) .BDDfy(); } [Fact] public void can_replace_url_no_slash() { - this.Given(x => x.GivenThereIsAnUpstreamUrlPath("api")) - .And(x => x.GivenThereIsAUrlPathMatch(new UrlPathMatch(true, new List(), "api"))) + this.Given(x => x.GivenThereIsAUrlMatch(new DownstreamRoute(new List(), "api"))) .When(x => x.WhenIReplaceTheTemplateVariables()) - .Then(x => x.ThenTheUpstreamUrlPathIsReturned("api")) + .Then(x => x.ThenTheDownstreamUrlPathIsReturned("api")) .BDDfy(); } [Fact] public void can_replace_url_one_slash() { - this.Given(x => x.GivenThereIsAnUpstreamUrlPath("api/")) - .And(x => x.GivenThereIsAUrlPathMatch(new UrlPathMatch(true, new List(), "api/"))) + this.Given(x => x.GivenThereIsAUrlMatch(new DownstreamRoute(new List(), "api/"))) .When(x => x.WhenIReplaceTheTemplateVariables()) - .Then(x => x.ThenTheUpstreamUrlPathIsReturned("api/")) + .Then(x => x.ThenTheDownstreamUrlPathIsReturned("api/")) .BDDfy(); } [Fact] public void can_replace_url_multiple_slash() { - this.Given(x => x.GivenThereIsAnUpstreamUrlPath("api/product/products/")) - .And(x => x.GivenThereIsAUrlPathMatch(new UrlPathMatch(true, new List(), "api/product/products/"))) + this.Given(x => x.GivenThereIsAUrlMatch(new DownstreamRoute(new List(), "api/product/products/"))) .When(x => x.WhenIReplaceTheTemplateVariables()) - .Then(x => x.ThenTheUpstreamUrlPathIsReturned("api/product/products/")) + .Then(x => x.ThenTheDownstreamUrlPathIsReturned("api/product/products/")) .BDDfy(); } @@ -68,10 +73,9 @@ namespace Ocelot.UnitTests new TemplateVariableNameAndValue("{productId}", "1") }; - this.Given(x => x.GivenThereIsAnUpstreamUrlPath("productservice/products/{productId}/")) - .And(x => x.GivenThereIsAUrlPathMatch(new UrlPathMatch(true, templateVariables, "api/products/{productId}/"))) + this.Given(x => x.GivenThereIsAUrlMatch(new DownstreamRoute(templateVariables, "productservice/products/{productId}/"))) .When(x => x.WhenIReplaceTheTemplateVariables()) - .Then(x => x.ThenTheUpstreamUrlPathIsReturned("productservice/products/1/")) + .Then(x => x.ThenTheDownstreamUrlPathIsReturned("productservice/products/1/")) .BDDfy(); } @@ -83,10 +87,9 @@ namespace Ocelot.UnitTests new TemplateVariableNameAndValue("{productId}", "1") }; - this.Given(x => x.GivenThereIsAnUpstreamUrlPath("productservice/products/{productId}/variants")) - .And(x => x.GivenThereIsAUrlPathMatch(new UrlPathMatch(true, templateVariables, "api/products/{productId}/"))) + this.Given(x => x.GivenThereIsAUrlMatch(new DownstreamRoute(templateVariables, "productservice/products/{productId}/variants"))) .When(x => x.WhenIReplaceTheTemplateVariables()) - .Then(x => x.ThenTheUpstreamUrlPathIsReturned("productservice/products/1/variants")) + .Then(x => x.ThenTheDownstreamUrlPathIsReturned("productservice/products/1/variants")) .BDDfy(); } @@ -99,10 +102,9 @@ namespace Ocelot.UnitTests new TemplateVariableNameAndValue("{variantId}", "12") }; - this.Given(x => x.GivenThereIsAnUpstreamUrlPath("productservice/products/{productId}/variants/{variantId}")) - .And(x => x.GivenThereIsAUrlPathMatch(new UrlPathMatch(true, templateVariables, "api/products/{productId}/{variantId}"))) + this.Given(x => x.GivenThereIsAUrlMatch(new DownstreamRoute(templateVariables, "productservice/products/{productId}/variants/{variantId}"))) .When(x => x.WhenIReplaceTheTemplateVariables()) - .Then(x => x.ThenTheUpstreamUrlPathIsReturned("productservice/products/1/variants/12")) + .Then(x => x.ThenTheDownstreamUrlPathIsReturned("productservice/products/1/variants/12")) .BDDfy(); } @@ -116,29 +118,23 @@ namespace Ocelot.UnitTests new TemplateVariableNameAndValue("{categoryId}", "34") }; - this.Given(x => x.GivenThereIsAnUpstreamUrlPath("productservice/category/{categoryId}/products/{productId}/variants/{variantId}")) - .And(x => x.GivenThereIsAUrlPathMatch(new UrlPathMatch(true, templateVariables, "api/products/{categoryId}/{productId}/{variantId}"))) + this.Given(x => x.GivenThereIsAUrlMatch(new DownstreamRoute(templateVariables, "productservice/category/{categoryId}/products/{productId}/variants/{variantId}"))) .When(x => x.WhenIReplaceTheTemplateVariables()) - .Then(x => x.ThenTheUpstreamUrlPathIsReturned("productservice/category/34/products/1/variants/12")) + .Then(x => x.ThenTheDownstreamUrlPathIsReturned("productservice/category/34/products/1/variants/12")) .BDDfy(); } - private void GivenThereIsAnUpstreamUrlPath(string upstreamUrlPath) + private void GivenThereIsAUrlMatch(DownstreamRoute downstreamRoute) { - _upstreamUrlPath = upstreamUrlPath; - } - - private void GivenThereIsAUrlPathMatch(UrlPathMatch urlPathMatch) - { - _urlPathMatch = urlPathMatch; + _downstreamRoute = downstreamRoute; } private void WhenIReplaceTheTemplateVariables() { - _result = _upstreamUrlPathReplacer.ReplaceTemplateVariable(_upstreamUrlPath, _urlPathMatch); + _result = _downstreamUrlPathReplacer.ReplaceTemplateVariable(_downstreamRoute); } - private void ThenTheUpstreamUrlPathIsReturned(string expected) + private void ThenTheDownstreamUrlPathIsReturned(string expected) { _result.ShouldBe(expected); } diff --git a/test/Ocelot.UnitTests/UrlPathTemplateMapRepositoryTests.cs b/test/Ocelot.UnitTests/UrlPathTemplateMapRepositoryTests.cs deleted file mode 100644 index 98de6ba9..00000000 --- a/test/Ocelot.UnitTests/UrlPathTemplateMapRepositoryTests.cs +++ /dev/null @@ -1,138 +0,0 @@ -using System.Collections.Generic; -using Ocelot.Library.Infrastructure.Responses; -using Ocelot.Library.Infrastructure.UrlPathTemplateRepository; -using Shouldly; -using Xunit; - -namespace Ocelot.UnitTests -{ - using TestStack.BDDfy; - - public class UrlPathTemplateMapRepositoryTests - { - private string _upstreamUrlPath; - private string _downstreamUrlPath; - private IUrlPathTemplateMapRepository _repository; - private Response _response; - private Response _getResponse; - private Response> _listResponse; - - public UrlPathTemplateMapRepositoryTests() - { - _repository = new InMemoryUrlPathTemplateMapRepository(); - } - - [Fact] - public void can_add_url_path() - { - this.Given(x => x.GivenIHaveAnUpstreamUrlPath("/api/products/products/{productId}")) - .And(x => x.GivenIWantToRouteRequestsToMyUpstreamUrlPath("/api/products/{productId}")) - .When(x => x.WhenIAddTheConfiguration()) - .Then(x => x.ThenTheResponseIsSuccesful()) - .BDDfy(); - } - - [Fact] - public void can_get_url_path() - { - this.Given(x => x.GivenIHaveSetUpADownstreamUrlPathAndAnUpstreamUrlPath("/api2", "http://www.someapi.com/api2")) - .When(x => x.WhenIRetrieveTheUrlPathByDownstreamUrl()) - .Then(x => x.ThenTheUrlPathIsReturned()) - .BDDfy(); - } - - [Fact] - public void can_get_all_urls() - { - this.Given(x => x.GivenIHaveSetUpADownstreamUrlPathAndAnUpstreamUrlPath("/api2", "http://www.someapi.com/api2")) - .When(x => x.WhenIRetrieveTheUrls()) - .Then(x => x.ThenTheUrlsAreReturned()) - .BDDfy(); - } - - [Fact] - public void should_return_error_response_when_url_path_already_used() - { - this.Given(x => x.GivenIHaveSetUpADownstreamUrlPathAndAnUpstreamUrlPath("/api2", "http://www.someapi.com/api2")) - .When(x => x.WhenITryToUseTheSameDownstreamUrl()) - .Then(x => x.ThenTheDownstreamUrlAlreadyBeenUsed()) - .BDDfy(); - } - - [Fact] - public void should_return_error_response_if_key_doesnt_exist() - { - this.Given(x => x.GivenIWantToRouteRequestsToMyUpstreamUrlPath("/api")) - .When(x => x.WhenIRetrieveTheUrlPathByDownstreamUrl()) - .Then(x => x.ThenTheKeyDoesNotExist()) - .BDDfy(); - } - - private void WhenITryToUseTheSameDownstreamUrl() - { - WhenIAddTheConfiguration(); - } - - private void ThenTheDownstreamUrlAlreadyBeenUsed() - { - _response.ShouldNotBeNull(); - _response.ShouldBeOfType(); - _response.Errors[0].Message.ShouldBe("This key has already been used"); - } - - private void ThenTheKeyDoesNotExist() - { - _getResponse.ShouldNotBeNull(); - _getResponse.ShouldBeOfType>(); - _getResponse.Errors[0].Message.ShouldBe("This key does not exist"); - } - - private void WhenIRetrieveTheUrlPathByDownstreamUrl() - { - _getResponse = _repository.GetUrlPathTemplateMap(_downstreamUrlPath); - } - - private void WhenIRetrieveTheUrls() - { - _listResponse = _repository.All; - } - - private void ThenTheUrlPathIsReturned() - { - _getResponse.Data.DownstreamUrlPathTemplate.ShouldBe(_downstreamUrlPath); - _getResponse.Data.UpstreamUrlPathTemplate.ShouldBe(_upstreamUrlPath); - } - - private void ThenTheUrlsAreReturned() - { - _listResponse.Data.Count.ShouldBeGreaterThan(0); - } - - private void GivenIHaveSetUpADownstreamUrlPathAndAnUpstreamUrlPath(string downstream, string upstreamApiUrl) - { - GivenIHaveAnUpstreamUrlPath(upstreamApiUrl); - GivenIWantToRouteRequestsToMyUpstreamUrlPath(downstream); - WhenIAddTheConfiguration(); - } - - private void GivenIHaveAnUpstreamUrlPath(string upstreamApiUrl) - { - _upstreamUrlPath = upstreamApiUrl; - } - - private void GivenIWantToRouteRequestsToMyUpstreamUrlPath(string apiKey) - { - _downstreamUrlPath = apiKey; - } - - private void WhenIAddTheConfiguration() - { - _response = _repository.AddUrlPathTemplateMap(new UrlPathTemplateMap(_downstreamUrlPath, _upstreamUrlPath)); - } - - private void ThenTheResponseIsSuccesful() - { - _response.ShouldBeOfType(); - } - } -} \ No newline at end of file diff --git a/test/Ocelot.UnitTests/UrlPathToUrlPathTemplateMatcherTests.cs b/test/Ocelot.UnitTests/UrlPathToUrlTemplateMatcherTests.cs similarity index 63% rename from test/Ocelot.UnitTests/UrlPathToUrlPathTemplateMatcherTests.cs rename to test/Ocelot.UnitTests/UrlPathToUrlTemplateMatcherTests.cs index 0a3b105d..eb3ff139 100644 --- a/test/Ocelot.UnitTests/UrlPathToUrlPathTemplateMatcherTests.cs +++ b/test/Ocelot.UnitTests/UrlPathToUrlTemplateMatcherTests.cs @@ -1,6 +1,6 @@ using System.Collections.Generic; using System.Linq; -using Ocelot.Library.Infrastructure.UrlPathMatcher; +using Ocelot.Library.Infrastructure.UrlMatcher; using Shouldly; using Xunit; @@ -8,26 +8,26 @@ namespace Ocelot.UnitTests { using TestStack.BDDfy; - public class UrlPathToUrlPathTemplateMatcherTests + public class UrlPathToUrlTemplateMatcherTests { - private readonly IUrlPathToUrlPathTemplateMatcher _urlMapper; - private string _downstreamPath; + private readonly IUrlPathToUrlTemplateMatcher _urlMatcher; + private string _downstreamUrlPath; private string _downstreamPathTemplate; - private UrlPathMatch _result; - public UrlPathToUrlPathTemplateMatcherTests() + private UrlMatch _result; + public UrlPathToUrlTemplateMatcherTests() { - _urlMapper = new UrlPathToUrlPathTemplateMatcher(); + _urlMatcher = new UrlPathToUrlTemplateMatcher(); } [Fact] public void can_match_down_stream_url() { this.Given(x => x.GivenIHaveADownstreamPath("")) - .And(x => x.GivenIHaveAnDownstreamPathTemplate("")) + .And(x => x.GivenIHaveAnDownstreamUrlTemplate("")) .When(x => x.WhenIMatchThePaths()) .And(x => x.ThenTheResultIsTrue()) - .And(x => x.ThenTheTemplatesDictionaryIs(new List())) - .And(x => x.ThenTheUrlPathTemplateIs("")) + .And(x => x.ThenTheTemplatesVariablesAre(new List())) + .And(x => x.ThenTheDownstreamUrlTemplateIs("")) .BDDfy(); } @@ -35,23 +35,23 @@ namespace Ocelot.UnitTests public void can_match_down_stream_url_with_no_slash() { this.Given(x => x.GivenIHaveADownstreamPath("api")) - .Given(x => x.GivenIHaveAnDownstreamPathTemplate("api")) + .Given(x => x.GivenIHaveAnDownstreamUrlTemplate("api")) .When(x => x.WhenIMatchThePaths()) .Then(x => x.ThenTheResultIsTrue()) - .And(x => x.ThenTheTemplatesDictionaryIs(new List())) - .And(x => x.ThenTheUrlPathTemplateIs("api")) + .And(x => x.ThenTheTemplatesVariablesAre(new List())) + .And(x => x.ThenTheDownstreamUrlTemplateIs("api")) .BDDfy(); } - [Fact] + [Fact] public void can_match_down_stream_url_with_one_slash() { this.Given(x => x.GivenIHaveADownstreamPath("api/")) - .Given(x => x.GivenIHaveAnDownstreamPathTemplate("api/")) + .Given(x => x.GivenIHaveAnDownstreamUrlTemplate("api/")) .When(x => x.WhenIMatchThePaths()) .Then(x => x.ThenTheResultIsTrue()) - .And(x => x.ThenTheTemplatesDictionaryIs(new List())) - .And(x => x.ThenTheUrlPathTemplateIs("api/")) + .And(x => x.ThenTheTemplatesVariablesAre(new List())) + .And(x => x.ThenTheDownstreamUrlTemplateIs("api/")) .BDDfy(); } @@ -59,11 +59,11 @@ namespace Ocelot.UnitTests public void can_match_down_stream_url_with_downstream_template() { this.Given(x => x.GivenIHaveADownstreamPath("api/product/products/")) - .Given(x => x.GivenIHaveAnDownstreamPathTemplate("api/product/products/")) + .Given(x => x.GivenIHaveAnDownstreamUrlTemplate("api/product/products/")) .When(x => x.WhenIMatchThePaths()) .Then(x => x.ThenTheResultIsTrue()) - .And(x => x.ThenTheTemplatesDictionaryIs(new List())) - .And(x => x.ThenTheUrlPathTemplateIs("api/product/products/")) + .And(x => x.ThenTheTemplatesVariablesAre(new List())) + .And(x => x.ThenTheDownstreamUrlTemplateIs("api/product/products/")) .BDDfy(); } @@ -71,11 +71,11 @@ namespace Ocelot.UnitTests public void can_match_down_stream_url_with_downstream_template_with_one_query_string_parameter() { this.Given(x => x.GivenIHaveADownstreamPath("api/product/products/?soldout=false")) - .Given(x => x.GivenIHaveAnDownstreamPathTemplate("api/product/products/")) + .Given(x => x.GivenIHaveAnDownstreamUrlTemplate("api/product/products/")) .When(x => x.WhenIMatchThePaths()) .Then(x => x.ThenTheResultIsTrue()) - .And(x => x.ThenTheTemplatesDictionaryIs(new List())) - .And(x => x.ThenTheUrlPathTemplateIs("api/product/products/")) + .And(x => x.ThenTheTemplatesVariablesAre(new List())) + .And(x => x.ThenTheDownstreamUrlTemplateIs("api/product/products/")) .BDDfy(); } @@ -88,11 +88,11 @@ namespace Ocelot.UnitTests }; this.Given(x => x.GivenIHaveADownstreamPath("api/product/products/1/variants/?soldout=false")) - .Given(x => x.GivenIHaveAnDownstreamPathTemplate("api/product/products/{productId}/variants/")) + .Given(x => x.GivenIHaveAnDownstreamUrlTemplate("api/product/products/{productId}/variants/")) .When(x => x.WhenIMatchThePaths()) .Then(x => x.ThenTheResultIsTrue()) - .And(x => x.ThenTheTemplatesDictionaryIs(expectedTemplates)) - .And(x => x.ThenTheUrlPathTemplateIs("api/product/products/{productId}/variants/")) + .And(x => x.ThenTheTemplatesVariablesAre(expectedTemplates)) + .And(x => x.ThenTheDownstreamUrlTemplateIs("api/product/products/{productId}/variants/")) .BDDfy(); } @@ -105,11 +105,11 @@ namespace Ocelot.UnitTests }; this.Given(x => x.GivenIHaveADownstreamPath("api/product/products/1")) - .Given(x => x.GivenIHaveAnDownstreamPathTemplate("api/product/products/{productId}")) + .Given(x => x.GivenIHaveAnDownstreamUrlTemplate("api/product/products/{productId}")) .When(x => x.WhenIMatchThePaths()) .Then(x => x.ThenTheResultIsTrue()) - .And(x => x.ThenTheTemplatesDictionaryIs(expectedTemplates)) - .And(x => x.ThenTheUrlPathTemplateIs("api/product/products/{productId}")) + .And(x => x.ThenTheTemplatesVariablesAre(expectedTemplates)) + .And(x => x.ThenTheDownstreamUrlTemplateIs("api/product/products/{productId}")) .BDDfy(); } @@ -123,11 +123,11 @@ namespace Ocelot.UnitTests }; this.Given(x => x.GivenIHaveADownstreamPath("api/product/products/1/2")) - .Given(x => x.GivenIHaveAnDownstreamPathTemplate("api/product/products/{productId}/{categoryId}")) + .Given(x => x.GivenIHaveAnDownstreamUrlTemplate("api/product/products/{productId}/{categoryId}")) .When(x => x.WhenIMatchThePaths()) .Then(x => x.ThenTheResultIsTrue()) - .And(x => x.ThenTheTemplatesDictionaryIs(expectedTemplates)) - .And(x => x.ThenTheUrlPathTemplateIs("api/product/products/{productId}/{categoryId}")) + .And(x => x.ThenTheTemplatesVariablesAre(expectedTemplates)) + .And(x => x.ThenTheDownstreamUrlTemplateIs("api/product/products/{productId}/{categoryId}")) .BDDfy(); } @@ -141,11 +141,11 @@ namespace Ocelot.UnitTests }; this.Given(x => x.GivenIHaveADownstreamPath("api/product/products/1/categories/2")) - .And(x => x.GivenIHaveAnDownstreamPathTemplate("api/product/products/{productId}/categories/{categoryId}")) + .And(x => x.GivenIHaveAnDownstreamUrlTemplate("api/product/products/{productId}/categories/{categoryId}")) .When(x => x.WhenIMatchThePaths()) .Then(x => x.ThenTheResultIsTrue()) - .And(x => x.ThenTheTemplatesDictionaryIs(expectedTemplates)) - .And(x => x.ThenTheUrlPathTemplateIs("api/product/products/{productId}/categories/{categoryId}")) + .And(x => x.ThenTheTemplatesVariablesAre(expectedTemplates)) + .And(x => x.ThenTheDownstreamUrlTemplateIs("api/product/products/{productId}/categories/{categoryId}")) .BDDfy(); } @@ -160,11 +160,11 @@ namespace Ocelot.UnitTests }; this.Given(x => x.GivenIHaveADownstreamPath("api/product/products/1/categories/2/variant/123")) - .And(x => x.GivenIHaveAnDownstreamPathTemplate("api/product/products/{productId}/categories/{categoryId}/variant/{variantId}")) + .And(x => x.GivenIHaveAnDownstreamUrlTemplate("api/product/products/{productId}/categories/{categoryId}/variant/{variantId}")) .When(x => x.WhenIMatchThePaths()) .Then(x => x.ThenTheResultIsTrue()) - .And(x => x.ThenTheTemplatesDictionaryIs(expectedTemplates)) - .And(x => x.ThenTheUrlPathTemplateIs("api/product/products/{productId}/categories/{categoryId}/variant/{variantId}")) + .And(x => x.ThenTheTemplatesVariablesAre(expectedTemplates)) + .And(x => x.ThenTheDownstreamUrlTemplateIs("api/product/products/{productId}/categories/{categoryId}/variant/{variantId}")) .BDDfy(); } @@ -178,15 +178,15 @@ namespace Ocelot.UnitTests }; this.Given(x => x.GivenIHaveADownstreamPath("api/product/products/1/categories/2/variant/")) - .And(x => x.GivenIHaveAnDownstreamPathTemplate("api/product/products/{productId}/categories/{categoryId}/variant/")) + .And(x => x.GivenIHaveAnDownstreamUrlTemplate("api/product/products/{productId}/categories/{categoryId}/variant/")) .When(x => x.WhenIMatchThePaths()) .Then(x => x.ThenTheResultIsTrue()) - .And(x => x.ThenTheTemplatesDictionaryIs(expectedTemplates)) - .And(x => x.ThenTheUrlPathTemplateIs("api/product/products/{productId}/categories/{categoryId}/variant/")) + .And(x => x.ThenTheTemplatesVariablesAre(expectedTemplates)) + .And(x => x.ThenTheDownstreamUrlTemplateIs("api/product/products/{productId}/categories/{categoryId}/variant/")) .BDDfy(); } - private void ThenTheTemplatesDictionaryIs(List expectedResults) + private void ThenTheTemplatesVariablesAre(List expectedResults) { foreach (var expectedResult in expectedResults) { @@ -196,23 +196,23 @@ namespace Ocelot.UnitTests } } - private void ThenTheUrlPathTemplateIs(string expectedUrlPathTemplate) + private void ThenTheDownstreamUrlTemplateIs(string expectedDownstreamUrlTemplate) { - _result.DownstreamUrlPathTemplate.ShouldBe(expectedUrlPathTemplate); + _result.DownstreamUrlTemplate.ShouldBe(expectedDownstreamUrlTemplate); } private void GivenIHaveADownstreamPath(string downstreamPath) { - _downstreamPath = downstreamPath; + _downstreamUrlPath = downstreamPath; } - private void GivenIHaveAnDownstreamPathTemplate(string downstreamTemplate) + private void GivenIHaveAnDownstreamUrlTemplate(string downstreamUrlTemplate) { - _downstreamPathTemplate = downstreamTemplate; + _downstreamPathTemplate = downstreamUrlTemplate; } private void WhenIMatchThePaths() { - _result = _urlMapper.Match(_downstreamPath, _downstreamPathTemplate); + _result = _urlMatcher.Match(_downstreamUrlPath, _downstreamPathTemplate); } private void ThenTheResultIsTrue() diff --git a/test/Ocelot.UnitTests/project.json b/test/Ocelot.UnitTests/project.json index f415f589..7b0acc6e 100644 --- a/test/Ocelot.UnitTests/project.json +++ b/test/Ocelot.UnitTests/project.json @@ -3,28 +3,30 @@ "testRunner": "xunit", - "dependencies": { - "Microsoft.NETCore.App": { - "version": "1.0.0", - "type": "platform" - }, - "Microsoft.AspNetCore.Mvc": "1.0.0", - "Microsoft.AspNetCore.Server.IISIntegration": "1.0.0", - "Microsoft.AspNetCore.Server.Kestrel": "1.0.0", - "Microsoft.Extensions.Configuration.EnvironmentVariables": "1.0.0", - "Microsoft.Extensions.Configuration.FileExtensions": "1.0.0", - "Microsoft.Extensions.Configuration.Json": "1.0.0", - "Microsoft.Extensions.Logging": "1.0.0", - "Microsoft.Extensions.Logging.Console": "1.0.0", - "Microsoft.Extensions.Logging.Debug": "1.0.0", - "Microsoft.Extensions.Options.ConfigurationExtensions": "1.0.0", - "Microsoft.AspNetCore.Http": "1.0.0", - "Ocelot.Library": "1.0.0-*", - "xunit": "2.1.0", - "dotnet-test-xunit": "2.2.0-preview2-build1029", - "Shouldly": "2.8.0", - "TestStack.BDDfy": "4.3.1" + "dependencies": { + "Microsoft.NETCore.App": { + "version": "1.0.0", + "type": "platform" }, + "Microsoft.AspNetCore.Mvc": "1.0.0", + "Microsoft.AspNetCore.Server.IISIntegration": "1.0.0", + "Microsoft.AspNetCore.Server.Kestrel": "1.0.0", + "Microsoft.Extensions.Configuration.EnvironmentVariables": "1.0.0", + "Microsoft.Extensions.Configuration.FileExtensions": "1.0.0", + "Microsoft.Extensions.Configuration.Json": "1.0.0", + "Microsoft.Extensions.Logging": "1.0.0", + "Microsoft.Extensions.Logging.Console": "1.0.0", + "Microsoft.Extensions.Logging.Debug": "1.0.0", + "Microsoft.Extensions.Options.ConfigurationExtensions": "1.0.0", + "Microsoft.AspNetCore.Http": "1.0.0", + "Ocelot.Library": "1.0.0-*", + "xunit": "2.1.0", + "dotnet-test-xunit": "2.2.0-preview2-build1029", + "Shouldly": "2.8.0", + "TestStack.BDDfy": "4.3.1", + "YamlDotNet": "3.9.0", + "Moq": "4.6.38-alpha" + }, "frameworks": { "netcoreapp1.0": {