diff --git a/src/Ocelot.Library/Infrastructure/Configuration/Configuration.cs b/src/Ocelot.Library/Infrastructure/Configuration/Configuration.cs deleted file mode 100644 index f1cc9b90..00000000 --- a/src/Ocelot.Library/Infrastructure/Configuration/Configuration.cs +++ /dev/null @@ -1,14 +0,0 @@ -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/DownstreamTemplateAlreadyUsedError.cs b/src/Ocelot.Library/Infrastructure/Configuration/DownstreamTemplateAlreadyUsedError.cs deleted file mode 100644 index 3992cb4e..00000000 --- a/src/Ocelot.Library/Infrastructure/Configuration/DownstreamTemplateAlreadyUsedError.cs +++ /dev/null @@ -1,15 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; -using Ocelot.Library.Infrastructure.Responses; - -namespace Ocelot.Library.Infrastructure.Configuration -{ - public class DownstreamTemplateAlreadyUsedError : Error - { - public DownstreamTemplateAlreadyUsedError(string message) : base(message) - { - } - } -} diff --git a/src/Ocelot.Library/Infrastructure/Configuration/IConfigurationValidator.cs b/src/Ocelot.Library/Infrastructure/Configuration/IConfigurationValidator.cs deleted file mode 100644 index 595ea21f..00000000 --- a/src/Ocelot.Library/Infrastructure/Configuration/IConfigurationValidator.cs +++ /dev/null @@ -1,13 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; -using Ocelot.Library.Infrastructure.Responses; - -namespace Ocelot.Library.Infrastructure.Configuration -{ - public interface IConfigurationValidator - { - Response IsValid(Configuration configuration); - } -} diff --git a/src/Ocelot.Library/Infrastructure/Configuration/IOcelotConfiguration.cs b/src/Ocelot.Library/Infrastructure/Configuration/IOcelotConfiguration.cs new file mode 100644 index 00000000..837edbaf --- /dev/null +++ b/src/Ocelot.Library/Infrastructure/Configuration/IOcelotConfiguration.cs @@ -0,0 +1,9 @@ +using System.Collections.Generic; + +namespace Ocelot.Library.Infrastructure.Configuration +{ + public interface IOcelotConfiguration + { + List ReRoutes { get; } + } +} \ No newline at end of file diff --git a/src/Ocelot.Library/Infrastructure/Configuration/OcelotConfiguration.cs b/src/Ocelot.Library/Infrastructure/Configuration/OcelotConfiguration.cs new file mode 100644 index 00000000..be544d6a --- /dev/null +++ b/src/Ocelot.Library/Infrastructure/Configuration/OcelotConfiguration.cs @@ -0,0 +1,57 @@ +using System.Collections.Generic; +using Microsoft.Extensions.Options; +using Ocelot.Library.Infrastructure.Configuration.Yaml; + +namespace Ocelot.Library.Infrastructure.Configuration +{ + public class OcelotConfiguration : IOcelotConfiguration + { + private readonly IOptions _options; + private readonly List _reRoutes; + private const string RegExMatchEverything = ".*"; + private const string RegExMatchEndString = "$"; + + public OcelotConfiguration(IOptions options) + { + _options = options; + _reRoutes = new List(); + SetReRoutes(); + } + + private void SetReRoutes() + { + foreach(var reRoute in _options.Value.ReRoutes) + { + var upstreamTemplate = reRoute.UpstreamTemplate; + var placeholders = new List(); + + for (int i = 0; i < upstreamTemplate.Length; i++) + { + if (IsPlaceHolder(upstreamTemplate, i)) + { + var postitionOfPlaceHolderClosingBracket = upstreamTemplate.IndexOf('}', i); + var difference = postitionOfPlaceHolderClosingBracket - i + 1; + var variableName = upstreamTemplate.Substring(i, difference); + placeholders.Add(variableName); + } + } + + foreach (var placeholder in placeholders) + { + upstreamTemplate = upstreamTemplate.Replace(placeholder, RegExMatchEverything); + } + + upstreamTemplate = $"{upstreamTemplate}{RegExMatchEndString}"; + + _reRoutes.Add(new ReRoute(reRoute.DownstreamTemplate, reRoute.UpstreamTemplate, reRoute.UpstreamHttpMethod, upstreamTemplate)); + } + } + + private static bool IsPlaceHolder(string upstreamTemplate, int i) + { + return upstreamTemplate[i] == '{'; + } + + public List ReRoutes => _reRoutes; + } +} \ No newline at end of file diff --git a/src/Ocelot.Library/Infrastructure/Configuration/ReRoute.cs b/src/Ocelot.Library/Infrastructure/Configuration/ReRoute.cs index 12698ed4..6d0f6497 100644 --- a/src/Ocelot.Library/Infrastructure/Configuration/ReRoute.cs +++ b/src/Ocelot.Library/Infrastructure/Configuration/ReRoute.cs @@ -2,8 +2,17 @@ { public class ReRoute { - public string DownstreamTemplate { get; set; } - public string UpstreamTemplate { get; set; } - public string UpstreamHttpMethod { get; set; } + public ReRoute(string downstreamTemplate, string upstreamTemplate, string upstreamHttpMethod, string upstreamTemplatePattern) + { + DownstreamTemplate = downstreamTemplate; + UpstreamTemplate = upstreamTemplate; + UpstreamHttpMethod = upstreamHttpMethod; + UpstreamTemplatePattern = upstreamTemplatePattern; + } + + public string DownstreamTemplate { get; private set; } + public string UpstreamTemplate { get; private set; } + public string UpstreamTemplatePattern { get; private set; } + public string UpstreamHttpMethod { get; private set; } } -} +} \ No newline at end of file diff --git a/src/Ocelot.Library/Infrastructure/Configuration/ConfigurationValidationResult.cs b/src/Ocelot.Library/Infrastructure/Configuration/Yaml/ConfigurationValidationResult.cs similarity index 90% rename from src/Ocelot.Library/Infrastructure/Configuration/ConfigurationValidationResult.cs rename to src/Ocelot.Library/Infrastructure/Configuration/Yaml/ConfigurationValidationResult.cs index abbbcfae..aa3a0d00 100644 --- a/src/Ocelot.Library/Infrastructure/Configuration/ConfigurationValidationResult.cs +++ b/src/Ocelot.Library/Infrastructure/Configuration/Yaml/ConfigurationValidationResult.cs @@ -1,7 +1,7 @@ using System.Collections.Generic; using Ocelot.Library.Infrastructure.Responses; -namespace Ocelot.Library.Infrastructure.Configuration +namespace Ocelot.Library.Infrastructure.Configuration.Yaml { public class ConfigurationValidationResult { diff --git a/src/Ocelot.Library/Infrastructure/Configuration/ConfigurationValidator.cs b/src/Ocelot.Library/Infrastructure/Configuration/Yaml/ConfigurationValidator.cs similarity index 88% rename from src/Ocelot.Library/Infrastructure/Configuration/ConfigurationValidator.cs rename to src/Ocelot.Library/Infrastructure/Configuration/Yaml/ConfigurationValidator.cs index 5038baf3..777a6c84 100644 --- a/src/Ocelot.Library/Infrastructure/Configuration/ConfigurationValidator.cs +++ b/src/Ocelot.Library/Infrastructure/Configuration/Yaml/ConfigurationValidator.cs @@ -2,11 +2,11 @@ using System.Linq; using Ocelot.Library.Infrastructure.Responses; -namespace Ocelot.Library.Infrastructure.Configuration +namespace Ocelot.Library.Infrastructure.Configuration.Yaml { public class ConfigurationValidator : IConfigurationValidator { - public Response IsValid(Configuration configuration) + public Response IsValid(YamlConfiguration configuration) { var duplicateUpstreamTemplates = configuration.ReRoutes .Select(r => r.DownstreamTemplate) diff --git a/src/Ocelot.Library/Infrastructure/Configuration/Yaml/DownstreamTemplateAlreadyUsedError.cs b/src/Ocelot.Library/Infrastructure/Configuration/Yaml/DownstreamTemplateAlreadyUsedError.cs new file mode 100644 index 00000000..5a256f91 --- /dev/null +++ b/src/Ocelot.Library/Infrastructure/Configuration/Yaml/DownstreamTemplateAlreadyUsedError.cs @@ -0,0 +1,11 @@ +using Ocelot.Library.Infrastructure.Responses; + +namespace Ocelot.Library.Infrastructure.Configuration.Yaml +{ + public class DownstreamTemplateAlreadyUsedError : Error + { + public DownstreamTemplateAlreadyUsedError(string message) : base(message) + { + } + } +} diff --git a/src/Ocelot.Library/Infrastructure/Configuration/Yaml/IConfigurationValidator.cs b/src/Ocelot.Library/Infrastructure/Configuration/Yaml/IConfigurationValidator.cs new file mode 100644 index 00000000..dd491928 --- /dev/null +++ b/src/Ocelot.Library/Infrastructure/Configuration/Yaml/IConfigurationValidator.cs @@ -0,0 +1,9 @@ +using Ocelot.Library.Infrastructure.Responses; + +namespace Ocelot.Library.Infrastructure.Configuration.Yaml +{ + public interface IConfigurationValidator + { + Response IsValid(YamlConfiguration configuration); + } +} diff --git a/src/Ocelot.Library/Infrastructure/Configuration/Yaml/YamlConfiguration.cs b/src/Ocelot.Library/Infrastructure/Configuration/Yaml/YamlConfiguration.cs new file mode 100644 index 00000000..69a7eb7a --- /dev/null +++ b/src/Ocelot.Library/Infrastructure/Configuration/Yaml/YamlConfiguration.cs @@ -0,0 +1,14 @@ +using System.Collections.Generic; + +namespace Ocelot.Library.Infrastructure.Configuration.Yaml +{ + public class YamlConfiguration + { + public YamlConfiguration() + { + ReRoutes = new List(); + } + + public List ReRoutes { get; set; } + } +} diff --git a/src/Ocelot.Library/Infrastructure/Configuration/Yaml/YamlReRoute.cs b/src/Ocelot.Library/Infrastructure/Configuration/Yaml/YamlReRoute.cs new file mode 100644 index 00000000..b012d19a --- /dev/null +++ b/src/Ocelot.Library/Infrastructure/Configuration/Yaml/YamlReRoute.cs @@ -0,0 +1,9 @@ +namespace Ocelot.Library.Infrastructure.Configuration.Yaml +{ + public class YamlReRoute + { + public string DownstreamTemplate { get; set; } + public string UpstreamTemplate { get; set; } + public string UpstreamHttpMethod { get; 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 index f02000c3..d87b4ccd 100644 --- a/src/Ocelot.Library/Infrastructure/DownstreamRouteFinder/DownstreamRouteFinder.cs +++ b/src/Ocelot.Library/Infrastructure/DownstreamRouteFinder/DownstreamRouteFinder.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Linq; using Microsoft.Extensions.Options; +using Ocelot.Library.Infrastructure.Configuration; using Ocelot.Library.Infrastructure.Responses; using Ocelot.Library.Infrastructure.UrlMatcher; @@ -9,24 +10,29 @@ namespace Ocelot.Library.Infrastructure.DownstreamRouteFinder { public class DownstreamRouteFinder : IDownstreamRouteFinder { - private readonly IOptions _configuration; + private readonly IOcelotConfiguration _configuration; private readonly IUrlPathToUrlTemplateMatcher _urlMatcher; + private readonly ITemplateVariableNameAndValueFinder _templateVariableNameAndValueFinder; - public DownstreamRouteFinder(IOptions configuration, IUrlPathToUrlTemplateMatcher urlMatcher) + public DownstreamRouteFinder(IOcelotConfiguration configuration, IUrlPathToUrlTemplateMatcher urlMatcher, ITemplateVariableNameAndValueFinder templateVariableNameAndValueFinder) { _configuration = configuration; _urlMatcher = urlMatcher; + _templateVariableNameAndValueFinder = templateVariableNameAndValueFinder; } public Response FindDownstreamRoute(string upstreamUrlPath, string upstreamHttpMethod) { - foreach (var template in _configuration.Value.ReRoutes.Where(r => string.Equals(r.UpstreamHttpMethod, upstreamHttpMethod, StringComparison.CurrentCultureIgnoreCase))) + foreach (var template in _configuration.ReRoutes.Where(r => string.Equals(r.UpstreamHttpMethod, upstreamHttpMethod, StringComparison.CurrentCultureIgnoreCase))) { - var urlMatch = _urlMatcher.Match(upstreamUrlPath, template.UpstreamTemplate); + var urlMatch = _urlMatcher.Match(upstreamUrlPath, template.UpstreamTemplatePattern); - if (urlMatch.Match) + if (urlMatch.Data.Match) { - return new OkResponse(new DownstreamRoute(urlMatch.TemplateVariableNameAndValues, template.DownstreamTemplate)); + var templateVariableNameAndValues = _templateVariableNameAndValueFinder.Find(upstreamUrlPath, + template.UpstreamTemplate); + + return new OkResponse(new DownstreamRoute(templateVariableNameAndValues.Data, template.DownstreamTemplate)); } } diff --git a/src/Ocelot.Library/Infrastructure/RequestBuilder/HttpRequestBuilder.cs b/src/Ocelot.Library/Infrastructure/RequestBuilder/HttpRequestBuilder.cs index 6a0b7c8f..2aa6c9e2 100644 --- a/src/Ocelot.Library/Infrastructure/RequestBuilder/HttpRequestBuilder.cs +++ b/src/Ocelot.Library/Infrastructure/RequestBuilder/HttpRequestBuilder.cs @@ -5,12 +5,13 @@ using System.Net.Http; using System.Net.Http.Headers; using System.Threading.Tasks; using Microsoft.AspNetCore.Http; +using Ocelot.Library.Infrastructure.Responses; namespace Ocelot.Library.Infrastructure.RequestBuilder { public class HttpRequestBuilder : IRequestBuilder { - public async Task Build(string httpMethod, string downstreamUrl, Stream content, IHeaderDictionary headers, + public async Task> Build(string httpMethod, string downstreamUrl, Stream content, IHeaderDictionary headers, IRequestCookieCollection cookies, string queryString, string contentType) { var method = new HttpMethod(httpMethod); @@ -64,9 +65,8 @@ namespace Ocelot.Library.Infrastructure.RequestBuilder cookieContainer.Add(uri, new Cookie(cookie.Key, cookie.Value)); } } - - - return new Request(httpRequestMessage, cookieContainer); + + return new OkResponse(new Request(httpRequestMessage, cookieContainer)); } } } \ No newline at end of file diff --git a/src/Ocelot.Library/Infrastructure/RequestBuilder/IRequestBuilder.cs b/src/Ocelot.Library/Infrastructure/RequestBuilder/IRequestBuilder.cs index cace3b70..296e4442 100644 --- a/src/Ocelot.Library/Infrastructure/RequestBuilder/IRequestBuilder.cs +++ b/src/Ocelot.Library/Infrastructure/RequestBuilder/IRequestBuilder.cs @@ -1,12 +1,13 @@ using System.IO; using System.Threading.Tasks; using Microsoft.AspNetCore.Http; +using Ocelot.Library.Infrastructure.Responses; namespace Ocelot.Library.Infrastructure.RequestBuilder { public interface IRequestBuilder { - Task Build(string httpMethod, + Task> Build(string httpMethod, string downstreamUrl, Stream content, IHeaderDictionary headers, diff --git a/src/Ocelot.Library/Infrastructure/UrlMatcher/ITemplateVariableNameAndValueFinder.cs b/src/Ocelot.Library/Infrastructure/UrlMatcher/ITemplateVariableNameAndValueFinder.cs new file mode 100644 index 00000000..3cadce39 --- /dev/null +++ b/src/Ocelot.Library/Infrastructure/UrlMatcher/ITemplateVariableNameAndValueFinder.cs @@ -0,0 +1,10 @@ +using System.Collections.Generic; +using Ocelot.Library.Infrastructure.Responses; + +namespace Ocelot.Library.Infrastructure.UrlMatcher +{ + public interface ITemplateVariableNameAndValueFinder + { + Response> Find(string upstreamUrlPath, string upstreamUrlPathTemplate); + } +} diff --git a/src/Ocelot.Library/Infrastructure/UrlMatcher/IUrlPathToUrlTemplateMatcher.cs b/src/Ocelot.Library/Infrastructure/UrlMatcher/IUrlPathToUrlTemplateMatcher.cs index 89e3e5a5..6be56a81 100644 --- a/src/Ocelot.Library/Infrastructure/UrlMatcher/IUrlPathToUrlTemplateMatcher.cs +++ b/src/Ocelot.Library/Infrastructure/UrlMatcher/IUrlPathToUrlTemplateMatcher.cs @@ -1,7 +1,9 @@ +using Ocelot.Library.Infrastructure.Responses; + namespace Ocelot.Library.Infrastructure.UrlMatcher { public interface IUrlPathToUrlTemplateMatcher { - UrlMatch Match(string upstreamUrlPath, string upstreamUrlPathTemplate); + Response Match(string upstreamUrlPath, string upstreamUrlPathTemplate); } } \ No newline at end of file diff --git a/src/Ocelot.Library/Infrastructure/UrlMatcher/RegExUrlMatcher.cs b/src/Ocelot.Library/Infrastructure/UrlMatcher/RegExUrlMatcher.cs new file mode 100644 index 00000000..55855eca --- /dev/null +++ b/src/Ocelot.Library/Infrastructure/UrlMatcher/RegExUrlMatcher.cs @@ -0,0 +1,17 @@ +using System.Text.RegularExpressions; +using Ocelot.Library.Infrastructure.Responses; + +namespace Ocelot.Library.Infrastructure.UrlMatcher +{ + public class RegExUrlMatcher : IUrlPathToUrlTemplateMatcher + { + public Response Match(string upstreamUrlPath, string upstreamUrlPathTemplate) + { + var regex = new Regex(upstreamUrlPathTemplate); + + return regex.IsMatch(upstreamUrlPath) + ? new OkResponse(new UrlMatch(true)) + : new OkResponse(new UrlMatch(false)); + } + } +} diff --git a/src/Ocelot.Library/Infrastructure/UrlMatcher/UrlPathToUrlTemplateMatcher.cs b/src/Ocelot.Library/Infrastructure/UrlMatcher/TemplateVariableNameAndValueFinder.cs similarity index 81% rename from src/Ocelot.Library/Infrastructure/UrlMatcher/UrlPathToUrlTemplateMatcher.cs rename to src/Ocelot.Library/Infrastructure/UrlMatcher/TemplateVariableNameAndValueFinder.cs index 4e5aed52..30658afc 100644 --- a/src/Ocelot.Library/Infrastructure/UrlMatcher/UrlPathToUrlTemplateMatcher.cs +++ b/src/Ocelot.Library/Infrastructure/UrlMatcher/TemplateVariableNameAndValueFinder.cs @@ -1,23 +1,16 @@ -using System; using System.Collections.Generic; +using Ocelot.Library.Infrastructure.Responses; namespace Ocelot.Library.Infrastructure.UrlMatcher { - public class UrlPathToUrlTemplateMatcher : IUrlPathToUrlTemplateMatcher + public class TemplateVariableNameAndValueFinder : ITemplateVariableNameAndValueFinder { - public UrlMatch Match(string upstreamUrlPath, string upstreamUrlPathTemplate) + public Response> Find(string upstreamUrlPath, string upstreamUrlPathTemplate) { - if (upstreamUrlPath.Length > upstreamUrlPathTemplate.Length) - { - return new UrlMatch(false, new List(), string.Empty); - } - - var urlPathTemplateCopy = upstreamUrlPathTemplate; - var templateKeysAndValues = new List(); int counterForUrl = 0; - + for (int counterForTemplate = 0; counterForTemplate < upstreamUrlPathTemplate.Length; counterForTemplate++) { if (CharactersDontMatch(upstreamUrlPathTemplate[counterForTemplate], upstreamUrlPath[counterForUrl]) && ContinueScanningUrl(counterForUrl,upstreamUrlPath.Length)) @@ -37,15 +30,14 @@ namespace Ocelot.Library.Infrastructure.UrlMatcher counterForUrl = GetNextCounterPosition(upstreamUrlPath, counterForUrl, '/'); continue; - } - else - { - return new UrlMatch(false, templateKeysAndValues, string.Empty); - } + } + + return new OkResponse>(templateKeysAndValues); } counterForUrl++; } - return new UrlMatch(true, templateKeysAndValues, urlPathTemplateCopy); + + return new OkResponse>(templateKeysAndValues); } private string GetPlaceholderVariableValue(string urlPath, int counterForUrl) diff --git a/src/Ocelot.Library/Infrastructure/UrlMatcher/UrlMatch.cs b/src/Ocelot.Library/Infrastructure/UrlMatcher/UrlMatch.cs index 0eb4cb47..db569d4a 100644 --- a/src/Ocelot.Library/Infrastructure/UrlMatcher/UrlMatch.cs +++ b/src/Ocelot.Library/Infrastructure/UrlMatcher/UrlMatch.cs @@ -1,17 +1,11 @@ -using System.Collections.Generic; - namespace Ocelot.Library.Infrastructure.UrlMatcher { public class UrlMatch { - public UrlMatch(bool match, List templateVariableNameAndValues, string downstreamUrlTemplate) + public UrlMatch(bool match) { 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/UrlTemplateReplacer/DownstreamUrlTemplateVariableReplacer.cs b/src/Ocelot.Library/Infrastructure/UrlTemplateReplacer/DownstreamUrlTemplateVariableReplacer.cs index 34987a8b..d9502341 100644 --- a/src/Ocelot.Library/Infrastructure/UrlTemplateReplacer/DownstreamUrlTemplateVariableReplacer.cs +++ b/src/Ocelot.Library/Infrastructure/UrlTemplateReplacer/DownstreamUrlTemplateVariableReplacer.cs @@ -1,11 +1,12 @@ using System.Text; using Ocelot.Library.Infrastructure.DownstreamRouteFinder; +using Ocelot.Library.Infrastructure.Responses; namespace Ocelot.Library.Infrastructure.UrlTemplateReplacer { public class DownstreamUrlTemplateVariableReplacer : IDownstreamUrlTemplateVariableReplacer { - public string ReplaceTemplateVariables(DownstreamRoute downstreamRoute) + public Response ReplaceTemplateVariables(DownstreamRoute downstreamRoute) { var upstreamUrl = new StringBuilder(); @@ -16,7 +17,7 @@ namespace Ocelot.Library.Infrastructure.UrlTemplateReplacer upstreamUrl.Replace(templateVarAndValue.TemplateVariableName, templateVarAndValue.TemplateVariableValue); } - return upstreamUrl.ToString(); + return new OkResponse(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 index 9f27db84..3d76671b 100644 --- a/src/Ocelot.Library/Infrastructure/UrlTemplateReplacer/IDownstreamUrlPathTemplateVariableReplacer.cs +++ b/src/Ocelot.Library/Infrastructure/UrlTemplateReplacer/IDownstreamUrlPathTemplateVariableReplacer.cs @@ -1,10 +1,10 @@ using Ocelot.Library.Infrastructure.DownstreamRouteFinder; -using Ocelot.Library.Infrastructure.UrlMatcher; +using Ocelot.Library.Infrastructure.Responses; namespace Ocelot.Library.Infrastructure.UrlTemplateReplacer { public interface IDownstreamUrlTemplateVariableReplacer { - string ReplaceTemplateVariables(DownstreamRoute downstreamRoute); + Response ReplaceTemplateVariables(DownstreamRoute downstreamRoute); } } \ No newline at end of file diff --git a/src/Ocelot.Library/Middleware/DownstreamRouteFinderMiddleware.cs b/src/Ocelot.Library/Middleware/DownstreamRouteFinderMiddleware.cs index eff4b94e..598f953e 100644 --- a/src/Ocelot.Library/Middleware/DownstreamRouteFinderMiddleware.cs +++ b/src/Ocelot.Library/Middleware/DownstreamRouteFinderMiddleware.cs @@ -2,25 +2,22 @@ using System.Threading.Tasks; using Microsoft.AspNetCore.Http; using Ocelot.Library.Infrastructure.DownstreamRouteFinder; using Ocelot.Library.Infrastructure.Repository; -using Ocelot.Library.Infrastructure.Responder; namespace Ocelot.Library.Middleware { - public class DownstreamRouteFinderMiddleware + public class DownstreamRouteFinderMiddleware : OcelotMiddleware { private readonly RequestDelegate _next; private readonly IDownstreamRouteFinder _downstreamRouteFinder; - private readonly IHttpResponder _responder; private readonly IScopedRequestDataRepository _scopedRequestDataRepository; public DownstreamRouteFinderMiddleware(RequestDelegate next, IDownstreamRouteFinder downstreamRouteFinder, - IHttpResponder responder, IScopedRequestDataRepository scopedRequestDataRepository) + :base(scopedRequestDataRepository) { _next = next; _downstreamRouteFinder = downstreamRouteFinder; - _responder = responder; _scopedRequestDataRepository = scopedRequestDataRepository; } @@ -32,12 +29,12 @@ namespace Ocelot.Library.Middleware if (downstreamRoute.IsError) { - await _responder.CreateNotFoundResponse(context); + SetPipelineError(downstreamRoute.Errors); return; } _scopedRequestDataRepository.Add("DownstreamRoute", downstreamRoute.Data); - + await _next.Invoke(context); } } diff --git a/src/Ocelot.Library/Middleware/DownstreamUrlCreatorMiddleware.cs b/src/Ocelot.Library/Middleware/DownstreamUrlCreatorMiddleware.cs index ed0f330d..2627a722 100644 --- a/src/Ocelot.Library/Middleware/DownstreamUrlCreatorMiddleware.cs +++ b/src/Ocelot.Library/Middleware/DownstreamUrlCreatorMiddleware.cs @@ -7,22 +7,20 @@ using Ocelot.Library.Infrastructure.UrlTemplateReplacer; namespace Ocelot.Library.Middleware { - public class DownstreamUrlCreatorMiddleware + public class DownstreamUrlCreatorMiddleware : OcelotMiddleware { private readonly RequestDelegate _next; private readonly IDownstreamUrlTemplateVariableReplacer _urlReplacer; private readonly IScopedRequestDataRepository _scopedRequestDataRepository; - private readonly IHttpResponder _responder; public DownstreamUrlCreatorMiddleware(RequestDelegate next, IDownstreamUrlTemplateVariableReplacer urlReplacer, - IScopedRequestDataRepository scopedRequestDataRepository, - IHttpResponder responder) + IScopedRequestDataRepository scopedRequestDataRepository) + :base(scopedRequestDataRepository) { _next = next; _urlReplacer = urlReplacer; _scopedRequestDataRepository = scopedRequestDataRepository; - _responder = responder; } public async Task Invoke(HttpContext context) @@ -31,13 +29,19 @@ namespace Ocelot.Library.Middleware if (downstreamRoute.IsError) { - await _responder.CreateNotFoundResponse(context); + SetPipelineError(downstreamRoute.Errors); return; } var downstreamUrl = _urlReplacer.ReplaceTemplateVariables(downstreamRoute.Data); - _scopedRequestDataRepository.Add("DownstreamUrl", downstreamUrl); + if (downstreamUrl.IsError) + { + SetPipelineError(downstreamUrl.Errors); + return; + } + + _scopedRequestDataRepository.Add("DownstreamUrl", downstreamUrl.Data); await _next.Invoke(context); } diff --git a/src/Ocelot.Library/Middleware/HttpRequestBuilderMiddleware.cs b/src/Ocelot.Library/Middleware/HttpRequestBuilderMiddleware.cs index e41b1417..b800a3d7 100644 --- a/src/Ocelot.Library/Middleware/HttpRequestBuilderMiddleware.cs +++ b/src/Ocelot.Library/Middleware/HttpRequestBuilderMiddleware.cs @@ -1,27 +1,22 @@ using System.Threading.Tasks; using Microsoft.AspNetCore.Http; using Ocelot.Library.Infrastructure.Repository; -using Ocelot.Library.Infrastructure.Requester; -using Ocelot.Library.Infrastructure.Responder; +using Ocelot.Library.Infrastructure.RequestBuilder; namespace Ocelot.Library.Middleware { - using Infrastructure.RequestBuilder; - - public class HttpRequestBuilderMiddleware + public class HttpRequestBuilderMiddleware : OcelotMiddleware { private readonly RequestDelegate _next; - private readonly IHttpResponder _responder; private readonly IScopedRequestDataRepository _scopedRequestDataRepository; private readonly IRequestBuilder _requestBuilder; public HttpRequestBuilderMiddleware(RequestDelegate next, - IHttpResponder responder, IScopedRequestDataRepository scopedRequestDataRepository, IRequestBuilder requestBuilder) + :base(scopedRequestDataRepository) { _next = next; - _responder = responder; _scopedRequestDataRepository = scopedRequestDataRepository; _requestBuilder = requestBuilder; } @@ -32,7 +27,7 @@ namespace Ocelot.Library.Middleware if (downstreamUrl.IsError) { - await _responder.CreateNotFoundResponse(context); + SetPipelineError(downstreamUrl.Errors); return; } @@ -40,7 +35,13 @@ namespace Ocelot.Library.Middleware .Build(context.Request.Method, downstreamUrl.Data, context.Request.Body, context.Request.Headers, context.Request.Cookies, context.Request.QueryString.Value, context.Request.ContentType); - _scopedRequestDataRepository.Add("Request", request); + if (request.IsError) + { + SetPipelineError(request.Errors); + return; + } + + _scopedRequestDataRepository.Add("Request", request.Data); await _next.Invoke(context); } diff --git a/src/Ocelot.Library/Middleware/HttpRequesterMiddleware.cs b/src/Ocelot.Library/Middleware/HttpRequesterMiddleware.cs index e35121ca..7c2c4b9d 100644 --- a/src/Ocelot.Library/Middleware/HttpRequesterMiddleware.cs +++ b/src/Ocelot.Library/Middleware/HttpRequesterMiddleware.cs @@ -1,29 +1,24 @@ -using System.Net.Http; using System.Threading.Tasks; using Microsoft.AspNetCore.Http; using Ocelot.Library.Infrastructure.Repository; +using Ocelot.Library.Infrastructure.RequestBuilder; using Ocelot.Library.Infrastructure.Requester; -using Ocelot.Library.Infrastructure.Responder; namespace Ocelot.Library.Middleware { - using Infrastructure.RequestBuilder; - - public class HttpRequesterMiddleware + public class HttpRequesterMiddleware : OcelotMiddleware { private readonly RequestDelegate _next; private readonly IHttpRequester _requester; - private readonly IHttpResponder _responder; private readonly IScopedRequestDataRepository _scopedRequestDataRepository; public HttpRequesterMiddleware(RequestDelegate next, IHttpRequester requester, - IHttpResponder responder, IScopedRequestDataRepository scopedRequestDataRepository) + :base(scopedRequestDataRepository) { _next = next; _requester = requester; - _responder = responder; _scopedRequestDataRepository = scopedRequestDataRepository; } @@ -33,16 +28,19 @@ namespace Ocelot.Library.Middleware if (request.IsError) { - await _responder.CreateNotFoundResponse(context); + SetPipelineError(request.Errors); return; } - var response = await _requester - .GetResponse(request.Data); + var response = await _requester.GetResponse(request.Data); - _scopedRequestDataRepository.Add("Response", response.Data); - - await _next.Invoke(context); + if (response.IsError) + { + SetPipelineError(response.Errors); + return; + } + + _scopedRequestDataRepository.Add("Response", response.Data); } } } \ No newline at end of file diff --git a/src/Ocelot.Library/Middleware/HttpResponderMiddleware.cs b/src/Ocelot.Library/Middleware/HttpResponderMiddleware.cs index 09b31f70..7974ad62 100644 --- a/src/Ocelot.Library/Middleware/HttpResponderMiddleware.cs +++ b/src/Ocelot.Library/Middleware/HttpResponderMiddleware.cs @@ -6,10 +6,7 @@ using Ocelot.Library.Infrastructure.Responder; namespace Ocelot.Library.Middleware { - /// - /// Terminating middleware that is responsible for returning a http response to the client - /// - public class HttpResponderMiddleware + public class HttpResponderMiddleware : OcelotMiddleware { private readonly RequestDelegate _next; private readonly IHttpResponder _responder; @@ -18,6 +15,7 @@ namespace Ocelot.Library.Middleware public HttpResponderMiddleware(RequestDelegate next, IHttpResponder responder, IScopedRequestDataRepository scopedRequestDataRepository) + :base(scopedRequestDataRepository) { _next = next; _responder = responder; @@ -26,9 +24,22 @@ namespace Ocelot.Library.Middleware public async Task Invoke(HttpContext context) { - var response = _scopedRequestDataRepository.Get("Response"); + await _next.Invoke(context); - await _responder.CreateResponse(context, response.Data); + if (PipelineError()) + { + //todo obviously this needs to be better...prob look at response errors + // and make a decision i guess + var errors = GetPipelineErrors(); + + await _responder.CreateNotFoundResponse(context); + } + else + { + var response = _scopedRequestDataRepository.Get("Response"); + + await _responder.CreateResponse(context, response.Data); + } } } } \ No newline at end of file diff --git a/src/Ocelot.Library/Middleware/OcelotMiddleware.cs b/src/Ocelot.Library/Middleware/OcelotMiddleware.cs new file mode 100644 index 00000000..f20daa96 --- /dev/null +++ b/src/Ocelot.Library/Middleware/OcelotMiddleware.cs @@ -0,0 +1,34 @@ +using System.Collections.Generic; +using Ocelot.Library.Infrastructure.Repository; +using Ocelot.Library.Infrastructure.Responses; + +namespace Ocelot.Library.Middleware +{ + public class OcelotMiddleware + { + private readonly IScopedRequestDataRepository _scopedRequestDataRepository; + + public OcelotMiddleware(IScopedRequestDataRepository scopedRequestDataRepository) + { + _scopedRequestDataRepository = scopedRequestDataRepository; + } + + public void SetPipelineError(List errors) + { + _scopedRequestDataRepository.Add("OcelotMiddlewareError", true); + _scopedRequestDataRepository.Add("OcelotMiddlewareErrors", errors); + } + + public bool PipelineError() + { + var response = _scopedRequestDataRepository.Get("OcelotMiddlewareError"); + return response.Data; + } + + public List GetPipelineErrors() + { + var response = _scopedRequestDataRepository.Get>("OcelotMiddlewareErrors"); + return response.Data; + } + } +} diff --git a/src/Ocelot.Library/project.json b/src/Ocelot.Library/project.json index b3d22c5c..e889d22f 100644 --- a/src/Ocelot.Library/project.json +++ b/src/Ocelot.Library/project.json @@ -17,6 +17,7 @@ "Microsoft.Extensions.Logging.Debug": "1.0.0", "Microsoft.Extensions.Options.ConfigurationExtensions": "1.0.0", "Microsoft.AspNetCore.Http": "1.0.0", + "System.Text.RegularExpressions": "4.1.0", "YamlDotNet": "3.9.0" }, diff --git a/src/Ocelot/Startup.cs b/src/Ocelot/Startup.cs index ed685d57..e2ecb505 100644 --- a/src/Ocelot/Startup.cs +++ b/src/Ocelot/Startup.cs @@ -1,10 +1,14 @@ -using Microsoft.AspNetCore.Builder; +using System.Collections.Generic; +using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.Configuration.Memory; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; using Ocelot.Library.Infrastructure.Configuration; +using Ocelot.Library.Infrastructure.Configuration.Yaml; using Ocelot.Library.Infrastructure.DownstreamRouteFinder; using Ocelot.Library.Infrastructure.Repository; using Ocelot.Library.Infrastructure.RequestBuilder; @@ -26,6 +30,7 @@ namespace Ocelot .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true) .AddYamlFile("configuration.yaml") .AddEnvironmentVariables(); + Configuration = builder.Build(); } @@ -35,11 +40,13 @@ namespace Ocelot public void ConfigureServices(IServiceCollection services) { services.AddOptions(); - - services.Configure(Configuration); + + services.Configure(Configuration); // Add framework services. - services.AddSingleton(); + services.AddSingleton(); + services.AddSingleton(); + services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); @@ -58,6 +65,8 @@ namespace Ocelot loggerFactory.AddDebug(); + app.UseHttpResponderMiddleware(); + app.UseDownstreamRouteFinderMiddleware(); app.UserDownstreamUrlCreatorMiddleware(); @@ -65,8 +74,6 @@ namespace Ocelot app.UseHttpRequestBuilderMiddleware(); app.UseHttpRequesterMiddleware(); - - app.UseHttpResponderMiddleware(); } } } diff --git a/test/Ocelot.AcceptanceTests/OcelotTests.cs b/test/Ocelot.AcceptanceTests/OcelotTests.cs index 4d57adf2..a4c3d5d5 100644 --- a/test/Ocelot.AcceptanceTests/OcelotTests.cs +++ b/test/Ocelot.AcceptanceTests/OcelotTests.cs @@ -6,7 +6,7 @@ using System.Net.Http; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.TestHost; using Ocelot.AcceptanceTests.Fake; -using Ocelot.Library.Infrastructure.Configuration; +using Ocelot.Library.Infrastructure.Configuration.Yaml; using Shouldly; using TestStack.BDDfy; using Xunit; @@ -32,7 +32,7 @@ namespace Ocelot.AcceptanceTests [Fact] public void should_return_response_404() { - this.Given(x => x.GivenThereIsAConfiguration(new Configuration())) + this.Given(x => x.GivenThereIsAConfiguration(new YamlConfiguration())) .And(x => x.GivenTheApiGatewayIsRunning()) .When(x => x.WhenIGetUrlOnTheApiGateway("/")) .Then(x => x.ThenTheStatusCodeShouldBe(HttpStatusCode.NotFound)) @@ -43,11 +43,11 @@ namespace Ocelot.AcceptanceTests public void should_return_response_200() { this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:51879")) - .And(x => x.GivenThereIsAConfiguration(new Configuration + .And(x => x.GivenThereIsAConfiguration(new YamlConfiguration { - ReRoutes = new List + ReRoutes = new List { - new ReRoute + new YamlReRoute { DownstreamTemplate = "http://localhost:51879/", UpstreamTemplate = "/", @@ -66,11 +66,11 @@ namespace Ocelot.AcceptanceTests public void should_return_response_201() { this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:51879")) - .And(x => x.GivenThereIsAConfiguration(new Configuration + .And(x => x.GivenThereIsAConfiguration(new YamlConfiguration { - ReRoutes = new List + ReRoutes = new List { - new ReRoute + new YamlReRoute { DownstreamTemplate = "http://localhost:51879/", UpstreamTemplate = "/", @@ -100,7 +100,7 @@ namespace Ocelot.AcceptanceTests _client = _server.CreateClient(); } - private void GivenThereIsAConfiguration(Configuration configuration) + private void GivenThereIsAConfiguration(YamlConfiguration yamlConfiguration) { var serializer = new Serializer(); @@ -111,7 +111,7 @@ namespace Ocelot.AcceptanceTests using (TextWriter writer = File.CreateText(_configurationPath)) { - serializer.Serialize(writer, configuration); + serializer.Serialize(writer, yamlConfiguration); } } diff --git a/test/Ocelot.UnitTests/Configuration/ConfigurationValidationTests.cs b/test/Ocelot.UnitTests/Configuration/ConfigurationValidationTests.cs index 3ddc8d38..3f3526e8 100644 --- a/test/Ocelot.UnitTests/Configuration/ConfigurationValidationTests.cs +++ b/test/Ocelot.UnitTests/Configuration/ConfigurationValidationTests.cs @@ -1,5 +1,5 @@ using System.Collections.Generic; -using Ocelot.Library.Infrastructure.Configuration; +using Ocelot.Library.Infrastructure.Configuration.Yaml; using Ocelot.Library.Infrastructure.Responses; using Shouldly; using TestStack.BDDfy; @@ -9,7 +9,7 @@ namespace Ocelot.UnitTests.Configuration { public class ConfigurationValidationTests { - private Library.Infrastructure.Configuration.Configuration _configuration; + private YamlConfiguration _yamlConfiguration; private readonly IConfigurationValidator _configurationValidator; private Response _result; @@ -21,11 +21,11 @@ namespace Ocelot.UnitTests.Configuration [Fact] public void configuration_is_valid_with_one_reroute() { - this.Given(x => x.GivenAConfiguration(new Library.Infrastructure.Configuration.Configuration() + this.Given(x => x.GivenAConfiguration(new YamlConfiguration() { - ReRoutes = new List + ReRoutes = new List { - new ReRoute + new YamlReRoute { DownstreamTemplate = "http://www.bbc.co.uk", UpstreamTemplate = "http://asdf.com" @@ -40,16 +40,16 @@ namespace Ocelot.UnitTests.Configuration [Fact] public void configuration_is_not_valid_with_duplicate_reroutes() { - this.Given(x => x.GivenAConfiguration(new Library.Infrastructure.Configuration.Configuration() + this.Given(x => x.GivenAConfiguration(new YamlConfiguration() { - ReRoutes = new List + ReRoutes = new List { - new ReRoute + new YamlReRoute { DownstreamTemplate = "http://www.bbc.co.uk", UpstreamTemplate = "http://asdf.com" }, - new ReRoute + new YamlReRoute { DownstreamTemplate = "http://www.bbc.co.uk", UpstreamTemplate = "http://lol.com" @@ -62,14 +62,14 @@ namespace Ocelot.UnitTests.Configuration .BDDfy(); } - private void GivenAConfiguration(Library.Infrastructure.Configuration.Configuration configuration) + private void GivenAConfiguration(YamlConfiguration yamlConfiguration) { - _configuration = configuration; + _yamlConfiguration = yamlConfiguration; } private void WhenIValidateTheConfiguration() { - _result = _configurationValidator.IsValid(_configuration); + _result = _configurationValidator.IsValid(_yamlConfiguration); } private void ThenTheResultIsValid() diff --git a/test/Ocelot.UnitTests/Configuration/OcelotConfigurationTests.cs b/test/Ocelot.UnitTests/Configuration/OcelotConfigurationTests.cs new file mode 100644 index 00000000..1c030e6f --- /dev/null +++ b/test/Ocelot.UnitTests/Configuration/OcelotConfigurationTests.cs @@ -0,0 +1,142 @@ +using System.Collections.Generic; +using Microsoft.Extensions.Options; +using Moq; +using Ocelot.Library.Infrastructure.Configuration; +using Ocelot.Library.Infrastructure.Configuration.Yaml; +using Shouldly; +using TestStack.BDDfy; +using Xunit; + +namespace Ocelot.UnitTests.Configuration +{ + public class OcelotConfigurationTests + { + private readonly Mock> _yamlConfig; + private OcelotConfiguration _config; + private YamlConfiguration _yamlConfiguration; + + public OcelotConfigurationTests() + { + _yamlConfig = new Mock>(); + } + + [Fact] + public void should_create_template_pattern_that_matches_anything_to_end_of_string() + { + this.Given(x => x.GivenTheYamlConfigIs(new YamlConfiguration + { + ReRoutes = new List + { + new YamlReRoute + { + UpstreamTemplate = "/api/products/{productId}", + DownstreamTemplate = "/products/{productId}", + UpstreamHttpMethod = "Get" + } + } + })) + .When(x => x.WhenIInstanciateTheOcelotConfig()) + .Then(x => x.ThenTheReRoutesAre(new List + { + new ReRoute("/products/{productId}","/api/products/{productId}", "Get", "/api/products/.*$") + })) + .BDDfy(); + } + + [Fact] + public void should_create_template_pattern_that_matches_more_than_one_placeholder() + { + this.Given(x => x.GivenTheYamlConfigIs(new YamlConfiguration + { + ReRoutes = new List + { + new YamlReRoute + { + UpstreamTemplate = "/api/products/{productId}/variants/{variantId}", + DownstreamTemplate = "/products/{productId}", + UpstreamHttpMethod = "Get" + } + } + })) + .When(x => x.WhenIInstanciateTheOcelotConfig()) + .Then(x => x.ThenTheReRoutesAre(new List + { + new ReRoute("/products/{productId}","/api/products/{productId}/variants/{variantId}", "Get", "/api/products/.*/variants/.*$") + })) + .BDDfy(); + } + + [Fact] + public void should_create_template_pattern_that_matches_more_than_one_placeholder_with_trailing_slash() + { + this.Given(x => x.GivenTheYamlConfigIs(new YamlConfiguration + { + ReRoutes = new List + { + new YamlReRoute + { + UpstreamTemplate = "/api/products/{productId}/variants/{variantId}/", + DownstreamTemplate = "/products/{productId}", + UpstreamHttpMethod = "Get" + } + } + })) + .When(x => x.WhenIInstanciateTheOcelotConfig()) + .Then(x => x.ThenTheReRoutesAre(new List + { + new ReRoute("/products/{productId}","/api/products/{productId}/variants/{variantId}/", "Get", "/api/products/.*/variants/.*/$") + })) + .BDDfy(); + } + + [Fact] + public void should_create_template_pattern_that_matches_to_end_of_string() + { + this.Given(x => x.GivenTheYamlConfigIs(new YamlConfiguration + { + ReRoutes = new List + { + new YamlReRoute + { + UpstreamTemplate = "/", + DownstreamTemplate = "/api/products/", + UpstreamHttpMethod = "Get" + } + } + })) + .When(x => x.WhenIInstanciateTheOcelotConfig()) + .Then(x => x.ThenTheReRoutesAre(new List + { + new ReRoute("/api/products/","/", "Get", "/$") + })) + .BDDfy(); + } + + private void GivenTheYamlConfigIs(YamlConfiguration yamlConfiguration) + { + _yamlConfiguration = yamlConfiguration; + _yamlConfig + .Setup(x => x.Value) + .Returns(_yamlConfiguration); + } + + private void WhenIInstanciateTheOcelotConfig() + { + _config = new OcelotConfiguration(_yamlConfig.Object); + } + + private void ThenTheReRoutesAre(List expectedReRoutes) + { + for (int i = 0; i < _config.ReRoutes.Count; i++) + { + var result = _config.ReRoutes[i]; + var expected = expectedReRoutes[i]; + + result.DownstreamTemplate.ShouldBe(expected.DownstreamTemplate); + result.UpstreamHttpMethod.ShouldBe(expected.UpstreamHttpMethod); + result.UpstreamTemplate.ShouldBe(expected.UpstreamTemplate); + result.UpstreamTemplatePattern.ShouldBe(expected.UpstreamTemplatePattern); + } + } + } +} diff --git a/test/Ocelot.UnitTests/DownstreamRouteFinder/DownstreamRouteFinderTests.cs b/test/Ocelot.UnitTests/DownstreamRouteFinder/DownstreamRouteFinderTests.cs index a1c23bee..ee35836b 100644 --- a/test/Ocelot.UnitTests/DownstreamRouteFinder/DownstreamRouteFinderTests.cs +++ b/test/Ocelot.UnitTests/DownstreamRouteFinder/DownstreamRouteFinderTests.cs @@ -1,5 +1,4 @@ using System.Collections.Generic; -using Microsoft.Extensions.Options; using Moq; using Ocelot.Library.Infrastructure.Configuration; using Ocelot.Library.Infrastructure.DownstreamRouteFinder; @@ -14,38 +13,35 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder public class DownstreamRouteFinderTests { private readonly IDownstreamRouteFinder _downstreamRouteFinder; - private readonly Mock> _mockConfig; + private readonly Mock _mockConfig; private readonly Mock _mockMatcher; + private readonly Mock _finder; private string _upstreamUrlPath; private Response _result; private Response _response; - private Library.Infrastructure.Configuration.Configuration _configuration; - private UrlMatch _match; + private List _reRoutesConfig; + private Response _match; private string _upstreamHttpMethod; public DownstreamRouteFinderTests() { - _mockConfig = new Mock>(); + _mockConfig = new Mock(); _mockMatcher = new Mock(); - _downstreamRouteFinder = new Library.Infrastructure.DownstreamRouteFinder.DownstreamRouteFinder(_mockConfig.Object, _mockMatcher.Object); + _finder = new Mock(); + _downstreamRouteFinder = new Library.Infrastructure.DownstreamRouteFinder.DownstreamRouteFinder(_mockConfig.Object, _mockMatcher.Object, _finder.Object); } [Fact] public void should_return_route() { this.Given(x => x.GivenThereIsAnUpstreamUrlPath("someUpstreamPath")) - .And(x => x.GivenTheConfigurationIs(new Library.Infrastructure.Configuration.Configuration { - ReRoutes = new List + .And(x => x.GivenTheTemplateVariableAndNameFinderReturns(new OkResponse>(new List()))) + .And(x => x.GivenTheConfigurationIs(new List { - new ReRoute() - { - UpstreamTemplate = "someUpstreamPath", - DownstreamTemplate = "someDownstreamPath", - UpstreamHttpMethod = "Get" - } + new ReRoute("someDownstreamPath","someUpstreamPath", "Get", "someUpstreamPath") } - })) - .And(x => x.GivenTheUrlMatcherReturns(new UrlMatch(true, new List(), "someDownstreamPath"))) + )) + .And(x => x.GivenTheUrlMatcherReturns(new OkResponse(new UrlMatch(true)))) .And(x => x.GivenTheUpstreamHttpMethodIs("Get")) .When(x => x.WhenICallTheFinder()) .Then( @@ -58,25 +54,14 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder public void should_return_correct_route_for_http_verb() { this.Given(x => x.GivenThereIsAnUpstreamUrlPath("someUpstreamPath")) - .And(x => x.GivenTheConfigurationIs(new Library.Infrastructure.Configuration.Configuration - { - ReRoutes = new List + .And(x => x.GivenTheTemplateVariableAndNameFinderReturns(new OkResponse>(new List()))) + .And(x => x.GivenTheConfigurationIs(new List { - new ReRoute() - { - UpstreamTemplate = "someUpstreamPath", - DownstreamTemplate = "someDownstreamPath", - UpstreamHttpMethod = "Get" - }, - new ReRoute() - { - UpstreamTemplate = "someUpstreamPath", - DownstreamTemplate = "someDownstreamPathForAPost", - UpstreamHttpMethod = "Post" - } + new ReRoute("someDownstreamPath", "someUpstreamPath", "Get", string.Empty), + new ReRoute("someDownstreamPathForAPost", "someUpstreamPath", "Post", string.Empty) } - })) - .And(x => x.GivenTheUrlMatcherReturns(new UrlMatch(true, new List(), "someDownstreamPathForAPost"))) + )) + .And(x => x.GivenTheUrlMatcherReturns(new OkResponse(new UrlMatch(true)))) .And(x => x.GivenTheUpstreamHttpMethodIs("Post")) .When(x => x.WhenICallTheFinder()) .Then( @@ -88,19 +73,12 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder public void should_not_return_route() { this.Given(x => x.GivenThereIsAnUpstreamUrlPath("somePath")) - .And(x => x.GivenTheConfigurationIs(new Library.Infrastructure.Configuration.Configuration - { - ReRoutes = new List + .And(x => x.GivenTheConfigurationIs(new List { - new ReRoute() - { - UpstreamTemplate = "somePath", - DownstreamTemplate = "somPath", - UpstreamHttpMethod = "Get" - } + new ReRoute("somPath", "somePath", "Get", "somePath") } - })) - .And(x => x.GivenTheUrlMatcherReturns(new UrlMatch(false, new List(), null))) + )) + .And(x => x.GivenTheUrlMatcherReturns(new OkResponse(new UrlMatch(false)))) .And(x => x.GivenTheUpstreamHttpMethodIs("Get")) .When(x => x.WhenICallTheFinder()) .Then( @@ -109,6 +87,13 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder .BDDfy(); } + private void GivenTheTemplateVariableAndNameFinderReturns(Response> response) + { + _finder + .Setup(x => x.Find(It.IsAny(), It.IsAny())) + .Returns(response); + } + private void GivenTheUpstreamHttpMethodIs(string upstreamHttpMethod) { _upstreamHttpMethod = upstreamHttpMethod; @@ -122,10 +107,10 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder private void ThenTheUrlMatcherIsCalledCorrectly() { _mockMatcher - .Verify(x => x.Match(_upstreamUrlPath, _configuration.ReRoutes[0].UpstreamTemplate), Times.Once); + .Verify(x => x.Match(_upstreamUrlPath, _reRoutesConfig[0].UpstreamTemplate), Times.Once); } - private void GivenTheUrlMatcherReturns(UrlMatch match) + private void GivenTheUrlMatcherReturns(Response match) { _match = match; _mockMatcher @@ -133,12 +118,12 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder .Returns(_match); } - private void GivenTheConfigurationIs(Library.Infrastructure.Configuration.Configuration configuration) + private void GivenTheConfigurationIs(List reRoutesConfig) { - _configuration = configuration; + _reRoutesConfig = reRoutesConfig; _mockConfig - .Setup(x => x.Value) - .Returns(_configuration); + .Setup(x => x.ReRoutes) + .Returns(_reRoutesConfig); } private void GivenThereIsAnUpstreamUrlPath(string upstreamUrlPath) diff --git a/test/Ocelot.UnitTests/RequestBuilder/RequestBuilderTests.cs b/test/Ocelot.UnitTests/RequestBuilder/RequestBuilderTests.cs index db6cf5e6..ad11ae2a 100644 --- a/test/Ocelot.UnitTests/RequestBuilder/RequestBuilderTests.cs +++ b/test/Ocelot.UnitTests/RequestBuilder/RequestBuilderTests.cs @@ -6,6 +6,7 @@ using System.Net.Http; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http.Internal; using Ocelot.Library.Infrastructure.RequestBuilder; +using Ocelot.Library.Infrastructure.Responses; using Shouldly; using TestStack.BDDfy; using Xunit; @@ -22,7 +23,7 @@ namespace Ocelot.UnitTests.RequestBuilder private string _query; private string _contentType; private readonly IRequestBuilder _requestBuilder; - private Request _result; + private Response _result; public RequestBuilderTests() { @@ -131,7 +132,7 @@ namespace Ocelot.UnitTests.RequestBuilder private void ThenTheCorrectQueryStringIsUsed(string expected) { - _result.HttpRequestMessage.RequestUri.Query.ShouldBe(expected); + _result.Data.HttpRequestMessage.RequestUri.Query.ShouldBe(expected); } private void GivenTheQueryStringIs(string query) @@ -141,7 +142,7 @@ namespace Ocelot.UnitTests.RequestBuilder private void ThenTheCorrectCookiesAreUsed(IRequestCookieCollection expected) { - var resultCookies = _result.CookieContainer.GetCookies(new Uri(_downstreamUrl + _query)); + var resultCookies = _result.Data.CookieContainer.GetCookies(new Uri(_downstreamUrl + _query)); var resultDictionary = resultCookies.Cast().ToDictionary(cook => cook.Name, cook => cook.Value); foreach (var expectedCookie in expected) @@ -162,7 +163,7 @@ namespace Ocelot.UnitTests.RequestBuilder foreach (var expectedHeader in expectedHeaders) { - _result.HttpRequestMessage.Headers.ShouldContain(x => x.Key == expectedHeader.Key && x.Value.First() == expectedHeader.Value[0]); + _result.Data.HttpRequestMessage.Headers.ShouldContain(x => x.Key == expectedHeader.Key && x.Value.First() == expectedHeader.Value[0]); } } @@ -172,7 +173,7 @@ namespace Ocelot.UnitTests.RequestBuilder foreach (var expectedHeader in expectedHeaders) { - _result.HttpRequestMessage.Content.Headers.ShouldContain(x => x.Key == expectedHeader.Key + _result.Data.HttpRequestMessage.Content.Headers.ShouldContain(x => x.Key == expectedHeader.Key && x.Value.First() == expectedHeader.Value[0] ); } @@ -207,17 +208,17 @@ namespace Ocelot.UnitTests.RequestBuilder private void ThenTheCorrectDownstreamUrlIsUsed(string expected) { - _result.HttpRequestMessage.RequestUri.AbsoluteUri.ShouldBe(expected); + _result.Data.HttpRequestMessage.RequestUri.AbsoluteUri.ShouldBe(expected); } private void ThenTheCorrectHttpMethodIsUsed(HttpMethod expected) { - _result.HttpRequestMessage.Method.Method.ShouldBe(expected.Method); + _result.Data.HttpRequestMessage.Method.Method.ShouldBe(expected.Method); } private void ThenTheCorrectContentIsUsed(HttpContent expected) { - _result.HttpRequestMessage.Content.ReadAsStringAsync().Result.ShouldBe(expected.ReadAsStringAsync().Result); + _result.Data.HttpRequestMessage.Content.ReadAsStringAsync().Result.ShouldBe(expected.ReadAsStringAsync().Result); } } } diff --git a/test/Ocelot.UnitTests/UrlMatcher/RegExUrlMatcherTests.cs b/test/Ocelot.UnitTests/UrlMatcher/RegExUrlMatcherTests.cs new file mode 100644 index 00000000..5774c573 --- /dev/null +++ b/test/Ocelot.UnitTests/UrlMatcher/RegExUrlMatcherTests.cs @@ -0,0 +1,156 @@ +using Ocelot.Library.Infrastructure.Responses; +using Ocelot.Library.Infrastructure.UrlMatcher; +using Shouldly; +using TestStack.BDDfy; +using Xunit; + +namespace Ocelot.UnitTests.UrlMatcher +{ + public class RegExUrlMatcherTests + { + private readonly IUrlPathToUrlTemplateMatcher _urlMatcher; + private string _downstreamUrlPath; + private string _downstreamPathTemplate; + private Response _result; + + public RegExUrlMatcherTests() + { + _urlMatcher = new RegExUrlMatcher(); + } + + [Fact] + public void should_find_match_when_template_smaller_than_valid_path() + { + this.Given(x => x.GivenIHaveAUpstreamPath("/api/products/2354325435624623464235")) + .And(x => x.GivenIHaveAnUpstreamUrlTemplatePattern("/api/products/.*$")) + .When(x => x.WhenIMatchThePaths()) + .And(x => x.ThenTheResultIsTrue()) + .BDDfy(); + } + + [Fact] + public void should_not_find_match() + { + this.Given(x => x.GivenIHaveAUpstreamPath("/api/values")) + .And(x => x.GivenIHaveAnUpstreamUrlTemplatePattern("/$")) + .When(x => x.WhenIMatchThePaths()) + .And(x => x.ThenTheResultIsFalse()) + .BDDfy(); + } + + [Fact] + public void can_match_down_stream_url() + { + this.Given(x => x.GivenIHaveAUpstreamPath("")) + .And(x => x.GivenIHaveAnUpstreamUrlTemplatePattern("$")) + .When(x => x.WhenIMatchThePaths()) + .And(x => x.ThenTheResultIsTrue()) + .BDDfy(); + } + + [Fact] + public void can_match_down_stream_url_with_no_slash() + { + this.Given(x => x.GivenIHaveAUpstreamPath("api")) + .Given(x => x.GivenIHaveAnUpstreamUrlTemplatePattern("api$")) + .When(x => x.WhenIMatchThePaths()) + .Then(x => x.ThenTheResultIsTrue()) + .BDDfy(); + } + + [Fact] + public void can_match_down_stream_url_with_one_slash() + { + this.Given(x => x.GivenIHaveAUpstreamPath("api/")) + .Given(x => x.GivenIHaveAnUpstreamUrlTemplatePattern("api/$")) + .When(x => x.WhenIMatchThePaths()) + .Then(x => x.ThenTheResultIsTrue()) + .BDDfy(); + } + + [Fact] + public void can_match_down_stream_url_with_downstream_template() + { + this.Given(x => x.GivenIHaveAUpstreamPath("api/product/products/")) + .Given(x => x.GivenIHaveAnUpstreamUrlTemplatePattern("api/product/products/$")) + .When(x => x.WhenIMatchThePaths()) + .Then(x => x.ThenTheResultIsTrue()) + .BDDfy(); + } + + [Fact] + public void can_match_down_stream_url_with_downstream_template_with_one_place_holder() + { + this.Given(x => x.GivenIHaveAUpstreamPath("api/product/products/1")) + .Given(x => x.GivenIHaveAnUpstreamUrlTemplatePattern("api/product/products/.*$")) + .When(x => x.WhenIMatchThePaths()) + .Then(x => x.ThenTheResultIsTrue()) + .BDDfy(); + } + + [Fact] + public void can_match_down_stream_url_with_downstream_template_with_two_place_holders() + { + this.Given(x => x.GivenIHaveAUpstreamPath("api/product/products/1/2")) + .Given(x => x.GivenIHaveAnUpstreamUrlTemplatePattern("api/product/products/.*/.*$")) + .When(x => x.WhenIMatchThePaths()) + .Then(x => x.ThenTheResultIsTrue()) + .BDDfy(); + } + + [Fact] + public void can_match_down_stream_url_with_downstream_template_with_two_place_holders_seperated_by_something() + { + this.Given(x => x.GivenIHaveAUpstreamPath("api/product/products/1/categories/2")) + .And(x => x.GivenIHaveAnUpstreamUrlTemplatePattern("api/product/products/.*/categories/.*$")) + .When(x => x.WhenIMatchThePaths()) + .Then(x => x.ThenTheResultIsTrue()) + .BDDfy(); + } + + [Fact] + public void can_match_down_stream_url_with_downstream_template_with_three_place_holders_seperated_by_something() + { + this.Given(x => x.GivenIHaveAUpstreamPath("api/product/products/1/categories/2/variant/123")) + .And(x => x.GivenIHaveAnUpstreamUrlTemplatePattern("api/product/products/.*/categories/.*/variant/.*$")) + .When(x => x.WhenIMatchThePaths()) + .Then(x => x.ThenTheResultIsTrue()) + .BDDfy(); + } + + [Fact] + public void can_match_down_stream_url_with_downstream_template_with_three_place_holders() + { + this.Given(x => x.GivenIHaveAUpstreamPath("api/product/products/1/categories/2/variant/")) + .And(x => x.GivenIHaveAnUpstreamUrlTemplatePattern("api/product/products/.*/categories/.*/variant/$")) + .When(x => x.WhenIMatchThePaths()) + .Then(x => x.ThenTheResultIsTrue()) + .BDDfy(); + } + + private void GivenIHaveAUpstreamPath(string downstreamPath) + { + _downstreamUrlPath = downstreamPath; + } + + private void GivenIHaveAnUpstreamUrlTemplatePattern(string downstreamUrlTemplate) + { + _downstreamPathTemplate = downstreamUrlTemplate; + } + + private void WhenIMatchThePaths() + { + _result = _urlMatcher.Match(_downstreamUrlPath, _downstreamPathTemplate); + } + + private void ThenTheResultIsTrue() + { + _result.Data.Match.ShouldBeTrue(); + } + + private void ThenTheResultIsFalse() + { + _result.Data.Match.ShouldBeFalse(); + } + } +} \ No newline at end of file diff --git a/test/Ocelot.UnitTests/UrlMatcher/UrlPathToUrlTemplateMatcherTests.cs b/test/Ocelot.UnitTests/UrlMatcher/TemplateVariableNameAndValueFinderTests.cs similarity index 64% rename from test/Ocelot.UnitTests/UrlMatcher/UrlPathToUrlTemplateMatcherTests.cs rename to test/Ocelot.UnitTests/UrlMatcher/TemplateVariableNameAndValueFinderTests.cs index d4502552..6f7f4d7f 100644 --- a/test/Ocelot.UnitTests/UrlMatcher/UrlPathToUrlTemplateMatcherTests.cs +++ b/test/Ocelot.UnitTests/UrlMatcher/TemplateVariableNameAndValueFinderTests.cs @@ -1,5 +1,6 @@ using System.Collections.Generic; using System.Linq; +using Ocelot.Library.Infrastructure.Responses; using Ocelot.Library.Infrastructure.UrlMatcher; using Shouldly; using TestStack.BDDfy; @@ -9,33 +10,14 @@ namespace Ocelot.UnitTests.UrlMatcher { public class UrlPathToUrlTemplateMatcherTests { - private readonly IUrlPathToUrlTemplateMatcher _urlMatcher; + private readonly ITemplateVariableNameAndValueFinder _finder; private string _downstreamUrlPath; private string _downstreamPathTemplate; - private UrlMatch _result; + private Response> _result; + public UrlPathToUrlTemplateMatcherTests() { - _urlMatcher = new UrlPathToUrlTemplateMatcher(); - } - - [Fact] - public void should_find_match_when_template_smaller_than_valid_path() - { - this.Given(x => x.GivenIHaveAUpstreamPath("/api/products/2354325435624623464235")) - .And(x => x.GivenIHaveAnUpstreamUrlTemplate("/api/products/{productId}")) - .When(x => x.WhenIMatchThePaths()) - .And(x => x.ThenTheResultIsTrue()) - .BDDfy(); - } - - [Fact] - public void should_not_find_match() - { - this.Given(x => x.GivenIHaveAUpstreamPath("/api/values")) - .And(x => x.GivenIHaveAnUpstreamUrlTemplate("/")) - .When(x => x.WhenIMatchThePaths()) - .And(x => x.ThenTheResultIsFalse()) - .BDDfy(); + _finder = new TemplateVariableNameAndValueFinder(); } [Fact] @@ -43,10 +25,8 @@ namespace Ocelot.UnitTests.UrlMatcher { this.Given(x => x.GivenIHaveAUpstreamPath("")) .And(x => x.GivenIHaveAnUpstreamUrlTemplate("")) - .When(x => x.WhenIMatchThePaths()) - .And(x => x.ThenTheResultIsTrue()) + .When(x => x.WhenIFindTheUrlVariableNamesAndValues()) .And(x => x.ThenTheTemplatesVariablesAre(new List())) - .And(x => x.ThenTheDownstreamUrlTemplateIs("")) .BDDfy(); } @@ -55,10 +35,8 @@ namespace Ocelot.UnitTests.UrlMatcher { this.Given(x => x.GivenIHaveAUpstreamPath("api")) .Given(x => x.GivenIHaveAnUpstreamUrlTemplate("api")) - .When(x => x.WhenIMatchThePaths()) - .Then(x => x.ThenTheResultIsTrue()) + .When(x => x.WhenIFindTheUrlVariableNamesAndValues()) .And(x => x.ThenTheTemplatesVariablesAre(new List())) - .And(x => x.ThenTheDownstreamUrlTemplateIs("api")) .BDDfy(); } @@ -67,10 +45,8 @@ namespace Ocelot.UnitTests.UrlMatcher { this.Given(x => x.GivenIHaveAUpstreamPath("api/")) .Given(x => x.GivenIHaveAnUpstreamUrlTemplate("api/")) - .When(x => x.WhenIMatchThePaths()) - .Then(x => x.ThenTheResultIsTrue()) + .When(x => x.WhenIFindTheUrlVariableNamesAndValues()) .And(x => x.ThenTheTemplatesVariablesAre(new List())) - .And(x => x.ThenTheDownstreamUrlTemplateIs("api/")) .BDDfy(); } @@ -79,10 +55,8 @@ namespace Ocelot.UnitTests.UrlMatcher { this.Given(x => x.GivenIHaveAUpstreamPath("api/product/products/")) .Given(x => x.GivenIHaveAnUpstreamUrlTemplate("api/product/products/")) - .When(x => x.WhenIMatchThePaths()) - .Then(x => x.ThenTheResultIsTrue()) + .When(x => x.WhenIFindTheUrlVariableNamesAndValues()) .And(x => x.ThenTheTemplatesVariablesAre(new List())) - .And(x => x.ThenTheDownstreamUrlTemplateIs("api/product/products/")) .BDDfy(); } @@ -96,10 +70,8 @@ namespace Ocelot.UnitTests.UrlMatcher this.Given(x => x.GivenIHaveAUpstreamPath("api/product/products/1")) .Given(x => x.GivenIHaveAnUpstreamUrlTemplate("api/product/products/{productId}")) - .When(x => x.WhenIMatchThePaths()) - .Then(x => x.ThenTheResultIsTrue()) + .When(x => x.WhenIFindTheUrlVariableNamesAndValues()) .And(x => x.ThenTheTemplatesVariablesAre(expectedTemplates)) - .And(x => x.ThenTheDownstreamUrlTemplateIs("api/product/products/{productId}")) .BDDfy(); } @@ -114,10 +86,8 @@ namespace Ocelot.UnitTests.UrlMatcher this.Given(x => x.GivenIHaveAUpstreamPath("api/product/products/1/2")) .Given(x => x.GivenIHaveAnUpstreamUrlTemplate("api/product/products/{productId}/{categoryId}")) - .When(x => x.WhenIMatchThePaths()) - .Then(x => x.ThenTheResultIsTrue()) + .When(x => x.WhenIFindTheUrlVariableNamesAndValues()) .And(x => x.ThenTheTemplatesVariablesAre(expectedTemplates)) - .And(x => x.ThenTheDownstreamUrlTemplateIs("api/product/products/{productId}/{categoryId}")) .BDDfy(); } @@ -132,10 +102,8 @@ namespace Ocelot.UnitTests.UrlMatcher this.Given(x => x.GivenIHaveAUpstreamPath("api/product/products/1/categories/2")) .And(x => x.GivenIHaveAnUpstreamUrlTemplate("api/product/products/{productId}/categories/{categoryId}")) - .When(x => x.WhenIMatchThePaths()) - .Then(x => x.ThenTheResultIsTrue()) + .When(x => x.WhenIFindTheUrlVariableNamesAndValues()) .And(x => x.ThenTheTemplatesVariablesAre(expectedTemplates)) - .And(x => x.ThenTheDownstreamUrlTemplateIs("api/product/products/{productId}/categories/{categoryId}")) .BDDfy(); } @@ -151,10 +119,8 @@ namespace Ocelot.UnitTests.UrlMatcher this.Given(x => x.GivenIHaveAUpstreamPath("api/product/products/1/categories/2/variant/123")) .And(x => x.GivenIHaveAnUpstreamUrlTemplate("api/product/products/{productId}/categories/{categoryId}/variant/{variantId}")) - .When(x => x.WhenIMatchThePaths()) - .Then(x => x.ThenTheResultIsTrue()) + .When(x => x.WhenIFindTheUrlVariableNamesAndValues()) .And(x => x.ThenTheTemplatesVariablesAre(expectedTemplates)) - .And(x => x.ThenTheDownstreamUrlTemplateIs("api/product/products/{productId}/categories/{categoryId}/variant/{variantId}")) .BDDfy(); } @@ -169,10 +135,8 @@ namespace Ocelot.UnitTests.UrlMatcher this.Given(x => x.GivenIHaveAUpstreamPath("api/product/products/1/categories/2/variant/")) .And(x => x.GivenIHaveAnUpstreamUrlTemplate("api/product/products/{productId}/categories/{categoryId}/variant/")) - .When(x => x.WhenIMatchThePaths()) - .Then(x => x.ThenTheResultIsTrue()) + .When(x => x.WhenIFindTheUrlVariableNamesAndValues()) .And(x => x.ThenTheTemplatesVariablesAre(expectedTemplates)) - .And(x => x.ThenTheDownstreamUrlTemplateIs("api/product/products/{productId}/categories/{categoryId}/variant/")) .BDDfy(); } @@ -180,16 +144,12 @@ namespace Ocelot.UnitTests.UrlMatcher { foreach (var expectedResult in expectedResults) { - var result = _result.TemplateVariableNameAndValues + var result = _result.Data .First(t => t.TemplateVariableName == expectedResult.TemplateVariableName); result.TemplateVariableValue.ShouldBe(expectedResult.TemplateVariableValue); } } - private void ThenTheDownstreamUrlTemplateIs(string expectedDownstreamUrlTemplate) - { - _result.DownstreamUrlTemplate.ShouldBe(expectedDownstreamUrlTemplate); - } private void GivenIHaveAUpstreamPath(string downstreamPath) { _downstreamUrlPath = downstreamPath; @@ -200,19 +160,9 @@ namespace Ocelot.UnitTests.UrlMatcher _downstreamPathTemplate = downstreamUrlTemplate; } - private void WhenIMatchThePaths() + private void WhenIFindTheUrlVariableNamesAndValues() { - _result = _urlMatcher.Match(_downstreamUrlPath, _downstreamPathTemplate); - } - - private void ThenTheResultIsTrue() - { - _result.Match.ShouldBeTrue(); - } - - private void ThenTheResultIsFalse() - { - _result.Match.ShouldBeFalse(); + _result = _finder.Find(_downstreamUrlPath, _downstreamPathTemplate); } } } \ No newline at end of file diff --git a/test/Ocelot.UnitTests/UrlTemplateReplacer/UpstreamUrlPathTemplateVariableReplacerTests.cs b/test/Ocelot.UnitTests/UrlTemplateReplacer/UpstreamUrlPathTemplateVariableReplacerTests.cs index ef03aa70..597c7d74 100644 --- a/test/Ocelot.UnitTests/UrlTemplateReplacer/UpstreamUrlPathTemplateVariableReplacerTests.cs +++ b/test/Ocelot.UnitTests/UrlTemplateReplacer/UpstreamUrlPathTemplateVariableReplacerTests.cs @@ -1,5 +1,6 @@ using System.Collections.Generic; using Ocelot.Library.Infrastructure.DownstreamRouteFinder; +using Ocelot.Library.Infrastructure.Responses; using Ocelot.Library.Infrastructure.UrlMatcher; using Ocelot.Library.Infrastructure.UrlTemplateReplacer; using Shouldly; @@ -11,7 +12,7 @@ namespace Ocelot.UnitTests.UrlTemplateReplacer public class UpstreamUrlPathTemplateVariableReplacerTests { private DownstreamRoute _downstreamRoute; - private string _result; + private Response _result; private readonly IDownstreamUrlTemplateVariableReplacer _downstreamUrlPathReplacer; public UpstreamUrlPathTemplateVariableReplacerTests() @@ -135,7 +136,7 @@ namespace Ocelot.UnitTests.UrlTemplateReplacer private void ThenTheDownstreamUrlPathIsReturned(string expected) { - _result.ShouldBe(expected); + _result.Data.ShouldBe(expected); } }