mirror of
				https://github.com/nsnail/Ocelot.git
				synced 2025-10-31 23:15:28 +08:00 
			
		
		
		
	regex for url match, means annoying constructor ocelot configuration object but cant work out a better way to do this at the moment
This commit is contained in:
		| @@ -1,14 +0,0 @@ | |||||||
| using System.Collections.Generic; |  | ||||||
|  |  | ||||||
| namespace Ocelot.Library.Infrastructure.Configuration |  | ||||||
| { |  | ||||||
|     public class Configuration |  | ||||||
|     { |  | ||||||
|         public Configuration() |  | ||||||
|         { |  | ||||||
|             ReRoutes = new List<ReRoute>(); |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         public List<ReRoute> ReRoutes { get; set; } |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| @@ -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) |  | ||||||
|         { |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| @@ -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<ConfigurationValidationResult> IsValid(Configuration configuration); |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| @@ -0,0 +1,9 @@ | |||||||
|  | using System.Collections.Generic; | ||||||
|  |  | ||||||
|  | namespace Ocelot.Library.Infrastructure.Configuration | ||||||
|  | { | ||||||
|  |     public interface IOcelotConfiguration | ||||||
|  |     { | ||||||
|  |         List<ReRoute> ReRoutes { get; } | ||||||
|  |     } | ||||||
|  | } | ||||||
| @@ -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<YamlConfiguration> _options; | ||||||
|  |         private readonly List<ReRoute> _reRoutes; | ||||||
|  |         private const string RegExMatchEverything = ".*"; | ||||||
|  |         private const string RegExMatchEndString = "$"; | ||||||
|  |  | ||||||
|  |         public OcelotConfiguration(IOptions<YamlConfiguration> options) | ||||||
|  |         { | ||||||
|  |             _options = options; | ||||||
|  |             _reRoutes = new List<ReRoute>(); | ||||||
|  |             SetReRoutes(); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         private void SetReRoutes() | ||||||
|  |         { | ||||||
|  |             foreach(var reRoute in _options.Value.ReRoutes) | ||||||
|  |             { | ||||||
|  |                 var upstreamTemplate = reRoute.UpstreamTemplate; | ||||||
|  |                 var placeholders = new List<string>(); | ||||||
|  |  | ||||||
|  |                 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<ReRoute> ReRoutes => _reRoutes; | ||||||
|  |     } | ||||||
|  | } | ||||||
| @@ -2,8 +2,17 @@ | |||||||
| { | { | ||||||
|     public class ReRoute |     public class ReRoute | ||||||
|     { |     { | ||||||
|         public string DownstreamTemplate { get; set; } |         public ReRoute(string downstreamTemplate, string upstreamTemplate, string upstreamHttpMethod, string upstreamTemplatePattern) | ||||||
|         public string UpstreamTemplate { get; set; } |         { | ||||||
|         public string UpstreamHttpMethod { get; set; } |             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; } | ||||||
|     } |     } | ||||||
| } | } | ||||||
| @@ -1,7 +1,7 @@ | |||||||
| using System.Collections.Generic; | using System.Collections.Generic; | ||||||
| using Ocelot.Library.Infrastructure.Responses; | using Ocelot.Library.Infrastructure.Responses; | ||||||
| 
 | 
 | ||||||
| namespace Ocelot.Library.Infrastructure.Configuration | namespace Ocelot.Library.Infrastructure.Configuration.Yaml | ||||||
| { | { | ||||||
|     public class ConfigurationValidationResult |     public class ConfigurationValidationResult | ||||||
|     { |     { | ||||||
| @@ -2,11 +2,11 @@ | |||||||
| using System.Linq; | using System.Linq; | ||||||
| using Ocelot.Library.Infrastructure.Responses; | using Ocelot.Library.Infrastructure.Responses; | ||||||
| 
 | 
 | ||||||
| namespace Ocelot.Library.Infrastructure.Configuration | namespace Ocelot.Library.Infrastructure.Configuration.Yaml | ||||||
| { | { | ||||||
|     public class ConfigurationValidator : IConfigurationValidator |     public class ConfigurationValidator : IConfigurationValidator | ||||||
|     { |     { | ||||||
|         public Response<ConfigurationValidationResult> IsValid(Configuration configuration) |         public Response<ConfigurationValidationResult> IsValid(YamlConfiguration configuration) | ||||||
|         { |         { | ||||||
|             var duplicateUpstreamTemplates = configuration.ReRoutes |             var duplicateUpstreamTemplates = configuration.ReRoutes | ||||||
|                 .Select(r => r.DownstreamTemplate) |                 .Select(r => r.DownstreamTemplate) | ||||||
| @@ -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) | ||||||
|  |         { | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
| @@ -0,0 +1,9 @@ | |||||||
|  | using Ocelot.Library.Infrastructure.Responses; | ||||||
|  |  | ||||||
|  | namespace Ocelot.Library.Infrastructure.Configuration.Yaml | ||||||
|  | { | ||||||
|  |     public interface IConfigurationValidator | ||||||
|  |     { | ||||||
|  |         Response<ConfigurationValidationResult> IsValid(YamlConfiguration configuration); | ||||||
|  |     } | ||||||
|  | } | ||||||
| @@ -0,0 +1,14 @@ | |||||||
|  | using System.Collections.Generic; | ||||||
|  |  | ||||||
|  | namespace Ocelot.Library.Infrastructure.Configuration.Yaml | ||||||
|  | { | ||||||
|  |     public class YamlConfiguration | ||||||
|  |     { | ||||||
|  |         public YamlConfiguration() | ||||||
|  |         { | ||||||
|  |             ReRoutes = new List<YamlReRoute>(); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         public List<YamlReRoute> ReRoutes { get; set; } | ||||||
|  |     } | ||||||
|  | } | ||||||
| @@ -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; } | ||||||
|  |     } | ||||||
|  | } | ||||||
| @@ -2,6 +2,7 @@ | |||||||
| using System.Collections.Generic; | using System.Collections.Generic; | ||||||
| using System.Linq; | using System.Linq; | ||||||
| using Microsoft.Extensions.Options; | using Microsoft.Extensions.Options; | ||||||
|  | using Ocelot.Library.Infrastructure.Configuration; | ||||||
| using Ocelot.Library.Infrastructure.Responses; | using Ocelot.Library.Infrastructure.Responses; | ||||||
| using Ocelot.Library.Infrastructure.UrlMatcher; | using Ocelot.Library.Infrastructure.UrlMatcher; | ||||||
|  |  | ||||||
| @@ -9,24 +10,29 @@ namespace Ocelot.Library.Infrastructure.DownstreamRouteFinder | |||||||
| { | { | ||||||
|     public class DownstreamRouteFinder : IDownstreamRouteFinder |     public class DownstreamRouteFinder : IDownstreamRouteFinder | ||||||
|     { |     { | ||||||
|         private readonly IOptions<Configuration.Configuration> _configuration; |         private readonly IOcelotConfiguration _configuration; | ||||||
|         private readonly IUrlPathToUrlTemplateMatcher _urlMatcher; |         private readonly IUrlPathToUrlTemplateMatcher _urlMatcher; | ||||||
|  |         private readonly ITemplateVariableNameAndValueFinder _templateVariableNameAndValueFinder; | ||||||
|  |  | ||||||
|         public DownstreamRouteFinder(IOptions<Configuration.Configuration> configuration, IUrlPathToUrlTemplateMatcher urlMatcher) |         public DownstreamRouteFinder(IOcelotConfiguration configuration, IUrlPathToUrlTemplateMatcher urlMatcher, ITemplateVariableNameAndValueFinder templateVariableNameAndValueFinder) | ||||||
|         { |         { | ||||||
|             _configuration = configuration; |             _configuration = configuration; | ||||||
|             _urlMatcher = urlMatcher; |             _urlMatcher = urlMatcher; | ||||||
|  |             _templateVariableNameAndValueFinder = templateVariableNameAndValueFinder; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         public Response<DownstreamRoute> FindDownstreamRoute(string upstreamUrlPath, string upstreamHttpMethod) |         public Response<DownstreamRoute> 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<DownstreamRoute>(new DownstreamRoute(urlMatch.TemplateVariableNameAndValues, template.DownstreamTemplate)); |                     var templateVariableNameAndValues = _templateVariableNameAndValueFinder.Find(upstreamUrlPath, | ||||||
|  |                         template.UpstreamTemplate); | ||||||
|  |  | ||||||
|  |                     return new OkResponse<DownstreamRoute>(new DownstreamRoute(templateVariableNameAndValues.Data, template.DownstreamTemplate)); | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|          |          | ||||||
|   | |||||||
| @@ -5,12 +5,13 @@ using System.Net.Http; | |||||||
| using System.Net.Http.Headers; | using System.Net.Http.Headers; | ||||||
| using System.Threading.Tasks; | using System.Threading.Tasks; | ||||||
| using Microsoft.AspNetCore.Http; | using Microsoft.AspNetCore.Http; | ||||||
|  | using Ocelot.Library.Infrastructure.Responses; | ||||||
|  |  | ||||||
| namespace Ocelot.Library.Infrastructure.RequestBuilder | namespace Ocelot.Library.Infrastructure.RequestBuilder | ||||||
| { | { | ||||||
|     public class HttpRequestBuilder : IRequestBuilder |     public class HttpRequestBuilder : IRequestBuilder | ||||||
|     { |     { | ||||||
|         public async Task<Request> Build(string httpMethod, string downstreamUrl, Stream content, IHeaderDictionary headers, |         public async Task<Response<Request>> Build(string httpMethod, string downstreamUrl, Stream content, IHeaderDictionary headers, | ||||||
|             IRequestCookieCollection cookies, string queryString, string contentType) |             IRequestCookieCollection cookies, string queryString, string contentType) | ||||||
|         { |         { | ||||||
|             var method = new HttpMethod(httpMethod); |             var method = new HttpMethod(httpMethod); | ||||||
| @@ -64,9 +65,8 @@ namespace Ocelot.Library.Infrastructure.RequestBuilder | |||||||
|                     cookieContainer.Add(uri, new Cookie(cookie.Key, cookie.Value)); |                     cookieContainer.Add(uri, new Cookie(cookie.Key, cookie.Value)); | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|  |              | ||||||
|  |             return new OkResponse<Request>(new Request(httpRequestMessage, cookieContainer)); | ||||||
|             return new Request(httpRequestMessage, cookieContainer); |  | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
| @@ -1,12 +1,13 @@ | |||||||
| using System.IO; | using System.IO; | ||||||
| using System.Threading.Tasks; | using System.Threading.Tasks; | ||||||
| using Microsoft.AspNetCore.Http; | using Microsoft.AspNetCore.Http; | ||||||
|  | using Ocelot.Library.Infrastructure.Responses; | ||||||
|  |  | ||||||
| namespace Ocelot.Library.Infrastructure.RequestBuilder | namespace Ocelot.Library.Infrastructure.RequestBuilder | ||||||
| { | { | ||||||
|     public interface IRequestBuilder |     public interface IRequestBuilder | ||||||
|     { |     { | ||||||
|         Task<Request> Build(string httpMethod, |         Task<Response<Request>> Build(string httpMethod, | ||||||
|             string downstreamUrl, |             string downstreamUrl, | ||||||
|             Stream content, |             Stream content, | ||||||
|             IHeaderDictionary headers, |             IHeaderDictionary headers, | ||||||
|   | |||||||
| @@ -0,0 +1,10 @@ | |||||||
|  | using System.Collections.Generic; | ||||||
|  | using Ocelot.Library.Infrastructure.Responses; | ||||||
|  |  | ||||||
|  | namespace Ocelot.Library.Infrastructure.UrlMatcher | ||||||
|  | { | ||||||
|  |     public interface ITemplateVariableNameAndValueFinder | ||||||
|  |     { | ||||||
|  |         Response<List<TemplateVariableNameAndValue>> Find(string upstreamUrlPath, string upstreamUrlPathTemplate); | ||||||
|  |     } | ||||||
|  | } | ||||||
| @@ -1,7 +1,9 @@ | |||||||
|  | using Ocelot.Library.Infrastructure.Responses; | ||||||
|  |  | ||||||
| namespace Ocelot.Library.Infrastructure.UrlMatcher | namespace Ocelot.Library.Infrastructure.UrlMatcher | ||||||
| { | { | ||||||
|      public interface IUrlPathToUrlTemplateMatcher |      public interface IUrlPathToUrlTemplateMatcher | ||||||
|      { |      { | ||||||
|         UrlMatch Match(string upstreamUrlPath, string upstreamUrlPathTemplate); |         Response<UrlMatch> Match(string upstreamUrlPath, string upstreamUrlPathTemplate); | ||||||
|      } |      } | ||||||
| }  | }  | ||||||
| @@ -0,0 +1,17 @@ | |||||||
|  | using System.Text.RegularExpressions; | ||||||
|  | using Ocelot.Library.Infrastructure.Responses; | ||||||
|  |  | ||||||
|  | namespace Ocelot.Library.Infrastructure.UrlMatcher | ||||||
|  | { | ||||||
|  |     public class RegExUrlMatcher : IUrlPathToUrlTemplateMatcher | ||||||
|  |     { | ||||||
|  |         public Response<UrlMatch> Match(string upstreamUrlPath, string upstreamUrlPathTemplate) | ||||||
|  |         { | ||||||
|  |             var regex = new Regex(upstreamUrlPathTemplate); | ||||||
|  |  | ||||||
|  |             return regex.IsMatch(upstreamUrlPath)  | ||||||
|  |                 ? new OkResponse<UrlMatch>(new UrlMatch(true))  | ||||||
|  |                 : new OkResponse<UrlMatch>(new UrlMatch(false)); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
| @@ -1,23 +1,16 @@ | |||||||
| using System; |  | ||||||
| using System.Collections.Generic; | using System.Collections.Generic; | ||||||
|  | using Ocelot.Library.Infrastructure.Responses; | ||||||
| 
 | 
 | ||||||
| namespace Ocelot.Library.Infrastructure.UrlMatcher | namespace Ocelot.Library.Infrastructure.UrlMatcher | ||||||
| { | { | ||||||
|      public class UrlPathToUrlTemplateMatcher : IUrlPathToUrlTemplateMatcher |      public class TemplateVariableNameAndValueFinder : ITemplateVariableNameAndValueFinder | ||||||
|     { |     { | ||||||
|         public UrlMatch Match(string upstreamUrlPath, string upstreamUrlPathTemplate) |         public Response<List<TemplateVariableNameAndValue>> Find(string upstreamUrlPath, string upstreamUrlPathTemplate) | ||||||
|         { |         { | ||||||
|             if (upstreamUrlPath.Length > upstreamUrlPathTemplate.Length) |  | ||||||
|             { |  | ||||||
|                 return new UrlMatch(false, new List<TemplateVariableNameAndValue>(), string.Empty); |  | ||||||
|             } |  | ||||||
| 
 |  | ||||||
|             var urlPathTemplateCopy = upstreamUrlPathTemplate; |  | ||||||
| 
 |  | ||||||
|             var templateKeysAndValues = new List<TemplateVariableNameAndValue>(); |             var templateKeysAndValues = new List<TemplateVariableNameAndValue>(); | ||||||
| 
 | 
 | ||||||
|             int counterForUrl = 0; |             int counterForUrl = 0; | ||||||
| 
 |           | ||||||
|             for (int counterForTemplate = 0; counterForTemplate < upstreamUrlPathTemplate.Length; counterForTemplate++) |             for (int counterForTemplate = 0; counterForTemplate < upstreamUrlPathTemplate.Length; counterForTemplate++) | ||||||
|             { |             { | ||||||
|                 if (CharactersDontMatch(upstreamUrlPathTemplate[counterForTemplate], upstreamUrlPath[counterForUrl]) && ContinueScanningUrl(counterForUrl,upstreamUrlPath.Length)) |                 if (CharactersDontMatch(upstreamUrlPathTemplate[counterForTemplate], upstreamUrlPath[counterForUrl]) && ContinueScanningUrl(counterForUrl,upstreamUrlPath.Length)) | ||||||
| @@ -37,15 +30,14 @@ namespace Ocelot.Library.Infrastructure.UrlMatcher | |||||||
|                         counterForUrl = GetNextCounterPosition(upstreamUrlPath, counterForUrl, '/'); |                         counterForUrl = GetNextCounterPosition(upstreamUrlPath, counterForUrl, '/'); | ||||||
| 
 | 
 | ||||||
|                         continue; |                         continue; | ||||||
|                     }  |                     } | ||||||
|                     else | 
 | ||||||
|                     { |                     return new OkResponse<List<TemplateVariableNameAndValue>>(templateKeysAndValues); | ||||||
|                         return new UrlMatch(false, templateKeysAndValues, string.Empty); |  | ||||||
|                     }  |  | ||||||
|                 } |                 } | ||||||
|                 counterForUrl++; |                 counterForUrl++; | ||||||
|             } |             } | ||||||
|             return new UrlMatch(true, templateKeysAndValues, urlPathTemplateCopy); | 
 | ||||||
|  |             return new OkResponse<List<TemplateVariableNameAndValue>>(templateKeysAndValues); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         private string GetPlaceholderVariableValue(string urlPath, int counterForUrl) |         private string GetPlaceholderVariableValue(string urlPath, int counterForUrl) | ||||||
| @@ -1,17 +1,11 @@ | |||||||
| using System.Collections.Generic; |  | ||||||
|  |  | ||||||
| namespace Ocelot.Library.Infrastructure.UrlMatcher | namespace Ocelot.Library.Infrastructure.UrlMatcher | ||||||
| { | { | ||||||
|     public class UrlMatch |     public class UrlMatch | ||||||
|     { |     { | ||||||
|         public UrlMatch(bool match, List<TemplateVariableNameAndValue> templateVariableNameAndValues, string downstreamUrlTemplate) |         public UrlMatch(bool match) | ||||||
|         { |         { | ||||||
|             Match = match;  |             Match = match;  | ||||||
|             TemplateVariableNameAndValues = templateVariableNameAndValues; |  | ||||||
|             DownstreamUrlTemplate = downstreamUrlTemplate; |  | ||||||
|         } |         } | ||||||
|         public bool Match {get;private set;} |         public bool Match {get;private set;} | ||||||
|         public List<TemplateVariableNameAndValue> TemplateVariableNameAndValues {get;private set;} |  | ||||||
|         public string DownstreamUrlTemplate {get;private set;} |  | ||||||
|     } |     } | ||||||
| } | } | ||||||
| @@ -1,11 +1,12 @@ | |||||||
| using System.Text; | using System.Text; | ||||||
| using Ocelot.Library.Infrastructure.DownstreamRouteFinder; | using Ocelot.Library.Infrastructure.DownstreamRouteFinder; | ||||||
|  | using Ocelot.Library.Infrastructure.Responses; | ||||||
|  |  | ||||||
| namespace Ocelot.Library.Infrastructure.UrlTemplateReplacer | namespace Ocelot.Library.Infrastructure.UrlTemplateReplacer | ||||||
| { | { | ||||||
|     public class DownstreamUrlTemplateVariableReplacer : IDownstreamUrlTemplateVariableReplacer |     public class DownstreamUrlTemplateVariableReplacer : IDownstreamUrlTemplateVariableReplacer | ||||||
|     { |     { | ||||||
|         public string ReplaceTemplateVariables(DownstreamRoute downstreamRoute) |         public Response<string> ReplaceTemplateVariables(DownstreamRoute downstreamRoute) | ||||||
|         { |         { | ||||||
|             var upstreamUrl = new StringBuilder(); |             var upstreamUrl = new StringBuilder(); | ||||||
|  |  | ||||||
| @@ -16,7 +17,7 @@ namespace Ocelot.Library.Infrastructure.UrlTemplateReplacer | |||||||
|                 upstreamUrl.Replace(templateVarAndValue.TemplateVariableName, templateVarAndValue.TemplateVariableValue); |                 upstreamUrl.Replace(templateVarAndValue.TemplateVariableName, templateVarAndValue.TemplateVariableValue); | ||||||
|             } |             } | ||||||
|  |  | ||||||
|             return upstreamUrl.ToString(); |             return new OkResponse<string>(upstreamUrl.ToString()); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
| @@ -1,10 +1,10 @@ | |||||||
| using Ocelot.Library.Infrastructure.DownstreamRouteFinder; | using Ocelot.Library.Infrastructure.DownstreamRouteFinder; | ||||||
| using Ocelot.Library.Infrastructure.UrlMatcher; | using Ocelot.Library.Infrastructure.Responses; | ||||||
|  |  | ||||||
| namespace Ocelot.Library.Infrastructure.UrlTemplateReplacer | namespace Ocelot.Library.Infrastructure.UrlTemplateReplacer | ||||||
| { | { | ||||||
|     public interface IDownstreamUrlTemplateVariableReplacer |     public interface IDownstreamUrlTemplateVariableReplacer | ||||||
|     { |     { | ||||||
|         string ReplaceTemplateVariables(DownstreamRoute downstreamRoute);    |         Response<string> ReplaceTemplateVariables(DownstreamRoute downstreamRoute);    | ||||||
|     } |     } | ||||||
| } | } | ||||||
| @@ -2,25 +2,22 @@ using System.Threading.Tasks; | |||||||
| using Microsoft.AspNetCore.Http; | using Microsoft.AspNetCore.Http; | ||||||
| using Ocelot.Library.Infrastructure.DownstreamRouteFinder; | using Ocelot.Library.Infrastructure.DownstreamRouteFinder; | ||||||
| using Ocelot.Library.Infrastructure.Repository; | using Ocelot.Library.Infrastructure.Repository; | ||||||
| using Ocelot.Library.Infrastructure.Responder; |  | ||||||
|  |  | ||||||
| namespace Ocelot.Library.Middleware | namespace Ocelot.Library.Middleware | ||||||
| { | { | ||||||
|     public class DownstreamRouteFinderMiddleware |     public class DownstreamRouteFinderMiddleware : OcelotMiddleware | ||||||
|     { |     { | ||||||
|         private readonly RequestDelegate _next; |         private readonly RequestDelegate _next; | ||||||
|         private readonly IDownstreamRouteFinder _downstreamRouteFinder; |         private readonly IDownstreamRouteFinder _downstreamRouteFinder; | ||||||
|         private readonly IHttpResponder _responder; |  | ||||||
|         private readonly IScopedRequestDataRepository _scopedRequestDataRepository; |         private readonly IScopedRequestDataRepository _scopedRequestDataRepository; | ||||||
|  |  | ||||||
|         public DownstreamRouteFinderMiddleware(RequestDelegate next,  |         public DownstreamRouteFinderMiddleware(RequestDelegate next,  | ||||||
|             IDownstreamRouteFinder downstreamRouteFinder,  |             IDownstreamRouteFinder downstreamRouteFinder,  | ||||||
|             IHttpResponder responder, |  | ||||||
|             IScopedRequestDataRepository scopedRequestDataRepository) |             IScopedRequestDataRepository scopedRequestDataRepository) | ||||||
|  |             :base(scopedRequestDataRepository) | ||||||
|         { |         { | ||||||
|             _next = next; |             _next = next; | ||||||
|             _downstreamRouteFinder = downstreamRouteFinder; |             _downstreamRouteFinder = downstreamRouteFinder; | ||||||
|             _responder = responder; |  | ||||||
|             _scopedRequestDataRepository = scopedRequestDataRepository; |             _scopedRequestDataRepository = scopedRequestDataRepository; | ||||||
|         } |         } | ||||||
|  |  | ||||||
| @@ -32,12 +29,12 @@ namespace Ocelot.Library.Middleware | |||||||
|  |  | ||||||
|             if (downstreamRoute.IsError) |             if (downstreamRoute.IsError) | ||||||
|             { |             { | ||||||
|                 await _responder.CreateNotFoundResponse(context); |                 SetPipelineError(downstreamRoute.Errors); | ||||||
|                 return; |                 return; | ||||||
|             } |             } | ||||||
|  |  | ||||||
|             _scopedRequestDataRepository.Add("DownstreamRoute", downstreamRoute.Data); |             _scopedRequestDataRepository.Add("DownstreamRoute", downstreamRoute.Data); | ||||||
|              |  | ||||||
|             await _next.Invoke(context); |             await _next.Invoke(context); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|   | |||||||
| @@ -7,22 +7,20 @@ using Ocelot.Library.Infrastructure.UrlTemplateReplacer; | |||||||
|  |  | ||||||
| namespace Ocelot.Library.Middleware | namespace Ocelot.Library.Middleware | ||||||
| { | { | ||||||
|     public class DownstreamUrlCreatorMiddleware |     public class DownstreamUrlCreatorMiddleware : OcelotMiddleware | ||||||
|     { |     { | ||||||
|         private readonly RequestDelegate _next; |         private readonly RequestDelegate _next; | ||||||
|         private readonly IDownstreamUrlTemplateVariableReplacer _urlReplacer; |         private readonly IDownstreamUrlTemplateVariableReplacer _urlReplacer; | ||||||
|         private readonly IScopedRequestDataRepository _scopedRequestDataRepository; |         private readonly IScopedRequestDataRepository _scopedRequestDataRepository; | ||||||
|         private readonly IHttpResponder _responder; |  | ||||||
|  |  | ||||||
|         public DownstreamUrlCreatorMiddleware(RequestDelegate next,  |         public DownstreamUrlCreatorMiddleware(RequestDelegate next,  | ||||||
|             IDownstreamUrlTemplateVariableReplacer urlReplacer, |             IDownstreamUrlTemplateVariableReplacer urlReplacer, | ||||||
|             IScopedRequestDataRepository scopedRequestDataRepository,  |             IScopedRequestDataRepository scopedRequestDataRepository) | ||||||
|             IHttpResponder responder) |             :base(scopedRequestDataRepository) | ||||||
|         { |         { | ||||||
|             _next = next; |             _next = next; | ||||||
|             _urlReplacer = urlReplacer; |             _urlReplacer = urlReplacer; | ||||||
|             _scopedRequestDataRepository = scopedRequestDataRepository; |             _scopedRequestDataRepository = scopedRequestDataRepository; | ||||||
|             _responder = responder; |  | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         public async Task Invoke(HttpContext context) |         public async Task Invoke(HttpContext context) | ||||||
| @@ -31,13 +29,19 @@ namespace Ocelot.Library.Middleware | |||||||
|  |  | ||||||
|             if (downstreamRoute.IsError) |             if (downstreamRoute.IsError) | ||||||
|             { |             { | ||||||
|                 await _responder.CreateNotFoundResponse(context); |                 SetPipelineError(downstreamRoute.Errors); | ||||||
|                 return; |                 return; | ||||||
|             } |             } | ||||||
|  |  | ||||||
|             var downstreamUrl = _urlReplacer.ReplaceTemplateVariables(downstreamRoute.Data); |             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); |             await _next.Invoke(context); | ||||||
|         } |         } | ||||||
|   | |||||||
| @@ -1,27 +1,22 @@ | |||||||
| using System.Threading.Tasks; | using System.Threading.Tasks; | ||||||
| using Microsoft.AspNetCore.Http; | using Microsoft.AspNetCore.Http; | ||||||
| using Ocelot.Library.Infrastructure.Repository; | using Ocelot.Library.Infrastructure.Repository; | ||||||
| using Ocelot.Library.Infrastructure.Requester; | using Ocelot.Library.Infrastructure.RequestBuilder; | ||||||
| using Ocelot.Library.Infrastructure.Responder; |  | ||||||
|  |  | ||||||
| namespace Ocelot.Library.Middleware | namespace Ocelot.Library.Middleware | ||||||
| { | { | ||||||
|     using Infrastructure.RequestBuilder; |     public class HttpRequestBuilderMiddleware : OcelotMiddleware | ||||||
|  |  | ||||||
|     public class HttpRequestBuilderMiddleware |  | ||||||
|     { |     { | ||||||
|         private readonly RequestDelegate _next; |         private readonly RequestDelegate _next; | ||||||
|         private readonly IHttpResponder _responder; |  | ||||||
|         private readonly IScopedRequestDataRepository _scopedRequestDataRepository; |         private readonly IScopedRequestDataRepository _scopedRequestDataRepository; | ||||||
|         private readonly IRequestBuilder _requestBuilder; |         private readonly IRequestBuilder _requestBuilder; | ||||||
|  |  | ||||||
|         public HttpRequestBuilderMiddleware(RequestDelegate next,  |         public HttpRequestBuilderMiddleware(RequestDelegate next,  | ||||||
|             IHttpResponder responder, |  | ||||||
|             IScopedRequestDataRepository scopedRequestDataRepository,  |             IScopedRequestDataRepository scopedRequestDataRepository,  | ||||||
|             IRequestBuilder requestBuilder) |             IRequestBuilder requestBuilder) | ||||||
|  |             :base(scopedRequestDataRepository) | ||||||
|         { |         { | ||||||
|             _next = next; |             _next = next; | ||||||
|             _responder = responder; |  | ||||||
|             _scopedRequestDataRepository = scopedRequestDataRepository; |             _scopedRequestDataRepository = scopedRequestDataRepository; | ||||||
|             _requestBuilder = requestBuilder; |             _requestBuilder = requestBuilder; | ||||||
|         } |         } | ||||||
| @@ -32,7 +27,7 @@ namespace Ocelot.Library.Middleware | |||||||
|  |  | ||||||
|             if (downstreamUrl.IsError) |             if (downstreamUrl.IsError) | ||||||
|             { |             { | ||||||
|                 await _responder.CreateNotFoundResponse(context); |                 SetPipelineError(downstreamUrl.Errors); | ||||||
|                 return; |                 return; | ||||||
|             } |             } | ||||||
|  |  | ||||||
| @@ -40,7 +35,13 @@ namespace Ocelot.Library.Middleware | |||||||
|               .Build(context.Request.Method, downstreamUrl.Data, context.Request.Body, |               .Build(context.Request.Method, downstreamUrl.Data, context.Request.Body, | ||||||
|               context.Request.Headers, context.Request.Cookies, context.Request.QueryString.Value, context.Request.ContentType); |               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); |             await _next.Invoke(context); | ||||||
|         } |         } | ||||||
|   | |||||||
| @@ -1,29 +1,24 @@ | |||||||
| using System.Net.Http; |  | ||||||
| using System.Threading.Tasks; | using System.Threading.Tasks; | ||||||
| using Microsoft.AspNetCore.Http; | using Microsoft.AspNetCore.Http; | ||||||
| using Ocelot.Library.Infrastructure.Repository; | using Ocelot.Library.Infrastructure.Repository; | ||||||
|  | using Ocelot.Library.Infrastructure.RequestBuilder; | ||||||
| using Ocelot.Library.Infrastructure.Requester; | using Ocelot.Library.Infrastructure.Requester; | ||||||
| using Ocelot.Library.Infrastructure.Responder; |  | ||||||
|  |  | ||||||
| namespace Ocelot.Library.Middleware | namespace Ocelot.Library.Middleware | ||||||
| { | { | ||||||
|     using Infrastructure.RequestBuilder; |     public class HttpRequesterMiddleware : OcelotMiddleware | ||||||
|  |  | ||||||
|     public class HttpRequesterMiddleware |  | ||||||
|     { |     { | ||||||
|         private readonly RequestDelegate _next; |         private readonly RequestDelegate _next; | ||||||
|         private readonly IHttpRequester _requester; |         private readonly IHttpRequester _requester; | ||||||
|         private readonly IHttpResponder _responder; |  | ||||||
|         private readonly IScopedRequestDataRepository _scopedRequestDataRepository; |         private readonly IScopedRequestDataRepository _scopedRequestDataRepository; | ||||||
|  |  | ||||||
|         public HttpRequesterMiddleware(RequestDelegate next,  |         public HttpRequesterMiddleware(RequestDelegate next,  | ||||||
|             IHttpRequester requester,  |             IHttpRequester requester,  | ||||||
|             IHttpResponder responder, |  | ||||||
|             IScopedRequestDataRepository scopedRequestDataRepository) |             IScopedRequestDataRepository scopedRequestDataRepository) | ||||||
|  |             :base(scopedRequestDataRepository) | ||||||
|         { |         { | ||||||
|             _next = next; |             _next = next; | ||||||
|             _requester = requester; |             _requester = requester; | ||||||
|             _responder = responder; |  | ||||||
|             _scopedRequestDataRepository = scopedRequestDataRepository; |             _scopedRequestDataRepository = scopedRequestDataRepository; | ||||||
|         } |         } | ||||||
|  |  | ||||||
| @@ -33,16 +28,19 @@ namespace Ocelot.Library.Middleware | |||||||
|  |  | ||||||
|             if (request.IsError) |             if (request.IsError) | ||||||
|             { |             { | ||||||
|                 await _responder.CreateNotFoundResponse(context); |                 SetPipelineError(request.Errors); | ||||||
|                 return; |                 return; | ||||||
|             } |             } | ||||||
|  |  | ||||||
|             var response = await _requester |             var response = await _requester.GetResponse(request.Data); | ||||||
|                 .GetResponse(request.Data); |  | ||||||
|  |  | ||||||
|             _scopedRequestDataRepository.Add("Response", response.Data); |             if (response.IsError) | ||||||
|              |             { | ||||||
|             await _next.Invoke(context); |                 SetPipelineError(response.Errors); | ||||||
|  |                 return; | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             _scopedRequestDataRepository.Add("Response", response.Data);             | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
| @@ -6,10 +6,7 @@ using Ocelot.Library.Infrastructure.Responder; | |||||||
|  |  | ||||||
| namespace Ocelot.Library.Middleware | namespace Ocelot.Library.Middleware | ||||||
| { | { | ||||||
|     /// <summary> |     public class HttpResponderMiddleware : OcelotMiddleware | ||||||
|     /// Terminating middleware that is responsible for returning a http response to the client |  | ||||||
|     /// </summary> |  | ||||||
|     public class HttpResponderMiddleware |  | ||||||
|     { |     { | ||||||
|         private readonly RequestDelegate _next; |         private readonly RequestDelegate _next; | ||||||
|         private readonly IHttpResponder _responder; |         private readonly IHttpResponder _responder; | ||||||
| @@ -18,6 +15,7 @@ namespace Ocelot.Library.Middleware | |||||||
|         public HttpResponderMiddleware(RequestDelegate next,  |         public HttpResponderMiddleware(RequestDelegate next,  | ||||||
|             IHttpResponder responder, |             IHttpResponder responder, | ||||||
|             IScopedRequestDataRepository scopedRequestDataRepository) |             IScopedRequestDataRepository scopedRequestDataRepository) | ||||||
|  |             :base(scopedRequestDataRepository) | ||||||
|         { |         { | ||||||
|             _next = next; |             _next = next; | ||||||
|             _responder = responder; |             _responder = responder; | ||||||
| @@ -26,9 +24,22 @@ namespace Ocelot.Library.Middleware | |||||||
|  |  | ||||||
|         public async Task Invoke(HttpContext context) |         public async Task Invoke(HttpContext context) | ||||||
|         { |         { | ||||||
|             var response = _scopedRequestDataRepository.Get<HttpResponseMessage>("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<HttpResponseMessage>("Response"); | ||||||
|  |  | ||||||
|  |                 await _responder.CreateResponse(context, response.Data); | ||||||
|  |             } | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
							
								
								
									
										34
									
								
								src/Ocelot.Library/Middleware/OcelotMiddleware.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								src/Ocelot.Library/Middleware/OcelotMiddleware.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -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<Error> errors) | ||||||
|  |         { | ||||||
|  |             _scopedRequestDataRepository.Add("OcelotMiddlewareError", true); | ||||||
|  |             _scopedRequestDataRepository.Add("OcelotMiddlewareErrors", errors); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         public bool PipelineError() | ||||||
|  |         { | ||||||
|  |             var response = _scopedRequestDataRepository.Get<bool>("OcelotMiddlewareError"); | ||||||
|  |             return response.Data; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         public List<Error> GetPipelineErrors() | ||||||
|  |         { | ||||||
|  |             var response = _scopedRequestDataRepository.Get<List<Error>>("OcelotMiddlewareErrors"); | ||||||
|  |             return response.Data; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
| @@ -17,6 +17,7 @@ | |||||||
|         "Microsoft.Extensions.Logging.Debug": "1.0.0", |         "Microsoft.Extensions.Logging.Debug": "1.0.0", | ||||||
|         "Microsoft.Extensions.Options.ConfigurationExtensions": "1.0.0", |         "Microsoft.Extensions.Options.ConfigurationExtensions": "1.0.0", | ||||||
|         "Microsoft.AspNetCore.Http": "1.0.0", |         "Microsoft.AspNetCore.Http": "1.0.0", | ||||||
|  |         "System.Text.RegularExpressions": "4.1.0", | ||||||
|         "YamlDotNet": "3.9.0" |         "YamlDotNet": "3.9.0" | ||||||
|     }, |     }, | ||||||
|  |  | ||||||
|   | |||||||
| @@ -1,10 +1,14 @@ | |||||||
| using Microsoft.AspNetCore.Builder; | using System.Collections.Generic; | ||||||
|  | using Microsoft.AspNetCore.Builder; | ||||||
| using Microsoft.AspNetCore.Hosting; | using Microsoft.AspNetCore.Hosting; | ||||||
| using Microsoft.AspNetCore.Http; | using Microsoft.AspNetCore.Http; | ||||||
| using Microsoft.Extensions.Configuration; | using Microsoft.Extensions.Configuration; | ||||||
|  | using Microsoft.Extensions.Configuration.Memory; | ||||||
| using Microsoft.Extensions.DependencyInjection; | using Microsoft.Extensions.DependencyInjection; | ||||||
| using Microsoft.Extensions.Logging; | using Microsoft.Extensions.Logging; | ||||||
|  | using Microsoft.Extensions.Options; | ||||||
| using Ocelot.Library.Infrastructure.Configuration; | using Ocelot.Library.Infrastructure.Configuration; | ||||||
|  | using Ocelot.Library.Infrastructure.Configuration.Yaml; | ||||||
| using Ocelot.Library.Infrastructure.DownstreamRouteFinder; | using Ocelot.Library.Infrastructure.DownstreamRouteFinder; | ||||||
| using Ocelot.Library.Infrastructure.Repository; | using Ocelot.Library.Infrastructure.Repository; | ||||||
| using Ocelot.Library.Infrastructure.RequestBuilder; | using Ocelot.Library.Infrastructure.RequestBuilder; | ||||||
| @@ -26,6 +30,7 @@ namespace Ocelot | |||||||
|                 .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true) |                 .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true) | ||||||
|                 .AddYamlFile("configuration.yaml") |                 .AddYamlFile("configuration.yaml") | ||||||
|                 .AddEnvironmentVariables(); |                 .AddEnvironmentVariables(); | ||||||
|  |  | ||||||
|             Configuration = builder.Build(); |             Configuration = builder.Build(); | ||||||
|         } |         } | ||||||
|  |  | ||||||
| @@ -35,11 +40,13 @@ namespace Ocelot | |||||||
|         public void ConfigureServices(IServiceCollection services) |         public void ConfigureServices(IServiceCollection services) | ||||||
|         { |         { | ||||||
|             services.AddOptions(); |             services.AddOptions(); | ||||||
|  |                          | ||||||
|             services.Configure<Configuration>(Configuration); |             services.Configure<YamlConfiguration>(Configuration); | ||||||
|  |  | ||||||
|             // Add framework services. |             // Add framework services. | ||||||
|             services.AddSingleton<IUrlPathToUrlTemplateMatcher, UrlPathToUrlTemplateMatcher>(); |             services.AddSingleton<IOcelotConfiguration, OcelotConfiguration>(); | ||||||
|  |             services.AddSingleton<IUrlPathToUrlTemplateMatcher, RegExUrlMatcher>(); | ||||||
|  |             services.AddSingleton<ITemplateVariableNameAndValueFinder, TemplateVariableNameAndValueFinder>(); | ||||||
|             services.AddSingleton<IDownstreamUrlTemplateVariableReplacer, DownstreamUrlTemplateVariableReplacer>(); |             services.AddSingleton<IDownstreamUrlTemplateVariableReplacer, DownstreamUrlTemplateVariableReplacer>(); | ||||||
|             services.AddSingleton<IDownstreamRouteFinder, DownstreamRouteFinder>(); |             services.AddSingleton<IDownstreamRouteFinder, DownstreamRouteFinder>(); | ||||||
|             services.AddSingleton<IHttpRequester, HttpClientHttpRequester>(); |             services.AddSingleton<IHttpRequester, HttpClientHttpRequester>(); | ||||||
| @@ -58,6 +65,8 @@ namespace Ocelot | |||||||
|  |  | ||||||
|             loggerFactory.AddDebug(); |             loggerFactory.AddDebug(); | ||||||
|  |  | ||||||
|  |             app.UseHttpResponderMiddleware(); | ||||||
|  |  | ||||||
|             app.UseDownstreamRouteFinderMiddleware(); |             app.UseDownstreamRouteFinderMiddleware(); | ||||||
|  |  | ||||||
|             app.UserDownstreamUrlCreatorMiddleware(); |             app.UserDownstreamUrlCreatorMiddleware(); | ||||||
| @@ -65,8 +74,6 @@ namespace Ocelot | |||||||
|             app.UseHttpRequestBuilderMiddleware(); |             app.UseHttpRequestBuilderMiddleware(); | ||||||
|  |  | ||||||
|             app.UseHttpRequesterMiddleware(); |             app.UseHttpRequesterMiddleware(); | ||||||
|  |  | ||||||
|             app.UseHttpResponderMiddleware(); |  | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -6,7 +6,7 @@ using System.Net.Http; | |||||||
| using Microsoft.AspNetCore.Hosting; | using Microsoft.AspNetCore.Hosting; | ||||||
| using Microsoft.AspNetCore.TestHost; | using Microsoft.AspNetCore.TestHost; | ||||||
| using Ocelot.AcceptanceTests.Fake; | using Ocelot.AcceptanceTests.Fake; | ||||||
| using Ocelot.Library.Infrastructure.Configuration; | using Ocelot.Library.Infrastructure.Configuration.Yaml; | ||||||
| using Shouldly; | using Shouldly; | ||||||
| using TestStack.BDDfy; | using TestStack.BDDfy; | ||||||
| using Xunit; | using Xunit; | ||||||
| @@ -32,7 +32,7 @@ namespace Ocelot.AcceptanceTests | |||||||
|         [Fact] |         [Fact] | ||||||
|         public void should_return_response_404() |         public void should_return_response_404() | ||||||
|         { |         { | ||||||
|             this.Given(x => x.GivenThereIsAConfiguration(new Configuration())) |             this.Given(x => x.GivenThereIsAConfiguration(new YamlConfiguration())) | ||||||
|                 .And(x => x.GivenTheApiGatewayIsRunning()) |                 .And(x => x.GivenTheApiGatewayIsRunning()) | ||||||
|                 .When(x => x.WhenIGetUrlOnTheApiGateway("/")) |                 .When(x => x.WhenIGetUrlOnTheApiGateway("/")) | ||||||
|                 .Then(x => x.ThenTheStatusCodeShouldBe(HttpStatusCode.NotFound)) |                 .Then(x => x.ThenTheStatusCodeShouldBe(HttpStatusCode.NotFound)) | ||||||
| @@ -43,11 +43,11 @@ namespace Ocelot.AcceptanceTests | |||||||
|         public void should_return_response_200() |         public void should_return_response_200() | ||||||
|         { |         { | ||||||
|             this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:51879")) |             this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:51879")) | ||||||
|                 .And(x => x.GivenThereIsAConfiguration(new Configuration |                 .And(x => x.GivenThereIsAConfiguration(new YamlConfiguration | ||||||
|                 { |                 { | ||||||
|                     ReRoutes = new List<ReRoute> |                     ReRoutes = new List<YamlReRoute> | ||||||
|                     { |                     { | ||||||
|                         new ReRoute |                         new YamlReRoute | ||||||
|                         { |                         { | ||||||
|                             DownstreamTemplate = "http://localhost:51879/", |                             DownstreamTemplate = "http://localhost:51879/", | ||||||
|                             UpstreamTemplate = "/", |                             UpstreamTemplate = "/", | ||||||
| @@ -66,11 +66,11 @@ namespace Ocelot.AcceptanceTests | |||||||
|         public void should_return_response_201() |         public void should_return_response_201() | ||||||
|         { |         { | ||||||
|             this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:51879")) |             this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:51879")) | ||||||
|                 .And(x => x.GivenThereIsAConfiguration(new Configuration |                 .And(x => x.GivenThereIsAConfiguration(new YamlConfiguration | ||||||
|                 { |                 { | ||||||
|                     ReRoutes = new List<ReRoute> |                     ReRoutes = new List<YamlReRoute> | ||||||
|                     { |                     { | ||||||
|                         new ReRoute |                         new YamlReRoute | ||||||
|                         { |                         { | ||||||
|                             DownstreamTemplate = "http://localhost:51879/", |                             DownstreamTemplate = "http://localhost:51879/", | ||||||
|                             UpstreamTemplate = "/", |                             UpstreamTemplate = "/", | ||||||
| @@ -100,7 +100,7 @@ namespace Ocelot.AcceptanceTests | |||||||
|             _client = _server.CreateClient(); |             _client = _server.CreateClient(); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         private void GivenThereIsAConfiguration(Configuration configuration) |         private void GivenThereIsAConfiguration(YamlConfiguration yamlConfiguration) | ||||||
|         { |         { | ||||||
|             var serializer = new Serializer(); |             var serializer = new Serializer(); | ||||||
|  |  | ||||||
| @@ -111,7 +111,7 @@ namespace Ocelot.AcceptanceTests | |||||||
|  |  | ||||||
|             using (TextWriter writer = File.CreateText(_configurationPath)) |             using (TextWriter writer = File.CreateText(_configurationPath)) | ||||||
|             { |             { | ||||||
|                 serializer.Serialize(writer, configuration); |                 serializer.Serialize(writer, yamlConfiguration); | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -1,5 +1,5 @@ | |||||||
| using System.Collections.Generic; | using System.Collections.Generic; | ||||||
| using Ocelot.Library.Infrastructure.Configuration; | using Ocelot.Library.Infrastructure.Configuration.Yaml; | ||||||
| using Ocelot.Library.Infrastructure.Responses; | using Ocelot.Library.Infrastructure.Responses; | ||||||
| using Shouldly; | using Shouldly; | ||||||
| using TestStack.BDDfy; | using TestStack.BDDfy; | ||||||
| @@ -9,7 +9,7 @@ namespace Ocelot.UnitTests.Configuration | |||||||
| { | { | ||||||
|     public class ConfigurationValidationTests |     public class ConfigurationValidationTests | ||||||
|     { |     { | ||||||
|         private Library.Infrastructure.Configuration.Configuration _configuration; |         private YamlConfiguration _yamlConfiguration; | ||||||
|         private readonly IConfigurationValidator _configurationValidator; |         private readonly IConfigurationValidator _configurationValidator; | ||||||
|         private Response<ConfigurationValidationResult> _result; |         private Response<ConfigurationValidationResult> _result; | ||||||
|  |  | ||||||
| @@ -21,11 +21,11 @@ namespace Ocelot.UnitTests.Configuration | |||||||
|         [Fact] |         [Fact] | ||||||
|         public void configuration_is_valid_with_one_reroute() |         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<ReRoute> |                 ReRoutes = new List<YamlReRoute> | ||||||
|                 { |                 { | ||||||
|                     new ReRoute |                     new YamlReRoute | ||||||
|                     { |                     { | ||||||
|                         DownstreamTemplate = "http://www.bbc.co.uk", |                         DownstreamTemplate = "http://www.bbc.co.uk", | ||||||
|                         UpstreamTemplate = "http://asdf.com" |                         UpstreamTemplate = "http://asdf.com" | ||||||
| @@ -40,16 +40,16 @@ namespace Ocelot.UnitTests.Configuration | |||||||
|         [Fact] |         [Fact] | ||||||
|         public void configuration_is_not_valid_with_duplicate_reroutes() |         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<ReRoute> |                 ReRoutes = new List<YamlReRoute> | ||||||
|                 { |                 { | ||||||
|                     new ReRoute |                     new YamlReRoute | ||||||
|                     { |                     { | ||||||
|                         DownstreamTemplate = "http://www.bbc.co.uk", |                         DownstreamTemplate = "http://www.bbc.co.uk", | ||||||
|                         UpstreamTemplate = "http://asdf.com" |                         UpstreamTemplate = "http://asdf.com" | ||||||
|                     }, |                     }, | ||||||
|                     new ReRoute |                     new YamlReRoute | ||||||
|                     { |                     { | ||||||
|                         DownstreamTemplate = "http://www.bbc.co.uk", |                         DownstreamTemplate = "http://www.bbc.co.uk", | ||||||
|                         UpstreamTemplate = "http://lol.com" |                         UpstreamTemplate = "http://lol.com" | ||||||
| @@ -62,14 +62,14 @@ namespace Ocelot.UnitTests.Configuration | |||||||
|                 .BDDfy(); |                 .BDDfy(); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         private void GivenAConfiguration(Library.Infrastructure.Configuration.Configuration configuration) |         private void GivenAConfiguration(YamlConfiguration yamlConfiguration) | ||||||
|         { |         { | ||||||
|             _configuration = configuration; |             _yamlConfiguration = yamlConfiguration; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         private void WhenIValidateTheConfiguration() |         private void WhenIValidateTheConfiguration() | ||||||
|         { |         { | ||||||
|             _result = _configurationValidator.IsValid(_configuration); |             _result = _configurationValidator.IsValid(_yamlConfiguration); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         private void ThenTheResultIsValid() |         private void ThenTheResultIsValid() | ||||||
|   | |||||||
							
								
								
									
										142
									
								
								test/Ocelot.UnitTests/Configuration/OcelotConfigurationTests.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										142
									
								
								test/Ocelot.UnitTests/Configuration/OcelotConfigurationTests.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -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<IOptions<YamlConfiguration>> _yamlConfig; | ||||||
|  |         private OcelotConfiguration _config; | ||||||
|  |         private YamlConfiguration _yamlConfiguration; | ||||||
|  |  | ||||||
|  |         public OcelotConfigurationTests() | ||||||
|  |         { | ||||||
|  |             _yamlConfig = new Mock<IOptions<YamlConfiguration>>(); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         [Fact] | ||||||
|  |         public void should_create_template_pattern_that_matches_anything_to_end_of_string() | ||||||
|  |         { | ||||||
|  |             this.Given(x => x.GivenTheYamlConfigIs(new YamlConfiguration | ||||||
|  |             { | ||||||
|  |                 ReRoutes = new List<YamlReRoute> | ||||||
|  |                 { | ||||||
|  |                     new YamlReRoute | ||||||
|  |                     { | ||||||
|  |                         UpstreamTemplate = "/api/products/{productId}", | ||||||
|  |                         DownstreamTemplate = "/products/{productId}", | ||||||
|  |                         UpstreamHttpMethod = "Get" | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |             })) | ||||||
|  |                 .When(x => x.WhenIInstanciateTheOcelotConfig()) | ||||||
|  |                 .Then(x => x.ThenTheReRoutesAre(new List<ReRoute> | ||||||
|  |                 { | ||||||
|  |                     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<YamlReRoute> | ||||||
|  |                 { | ||||||
|  |                     new YamlReRoute | ||||||
|  |                     { | ||||||
|  |                         UpstreamTemplate = "/api/products/{productId}/variants/{variantId}", | ||||||
|  |                         DownstreamTemplate = "/products/{productId}", | ||||||
|  |                         UpstreamHttpMethod = "Get" | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |             })) | ||||||
|  |                 .When(x => x.WhenIInstanciateTheOcelotConfig()) | ||||||
|  |                 .Then(x => x.ThenTheReRoutesAre(new List<ReRoute> | ||||||
|  |                 { | ||||||
|  |                     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<YamlReRoute> | ||||||
|  |                 { | ||||||
|  |                     new YamlReRoute | ||||||
|  |                     { | ||||||
|  |                         UpstreamTemplate = "/api/products/{productId}/variants/{variantId}/", | ||||||
|  |                         DownstreamTemplate = "/products/{productId}", | ||||||
|  |                         UpstreamHttpMethod = "Get" | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |             })) | ||||||
|  |                 .When(x => x.WhenIInstanciateTheOcelotConfig()) | ||||||
|  |                 .Then(x => x.ThenTheReRoutesAre(new List<ReRoute> | ||||||
|  |                 { | ||||||
|  |                     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<YamlReRoute> | ||||||
|  |                 { | ||||||
|  |                     new YamlReRoute | ||||||
|  |                     { | ||||||
|  |                         UpstreamTemplate = "/", | ||||||
|  |                         DownstreamTemplate = "/api/products/", | ||||||
|  |                         UpstreamHttpMethod = "Get" | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |             })) | ||||||
|  |                 .When(x => x.WhenIInstanciateTheOcelotConfig()) | ||||||
|  |                 .Then(x => x.ThenTheReRoutesAre(new List<ReRoute> | ||||||
|  |                 { | ||||||
|  |                     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<ReRoute> 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); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
| @@ -1,5 +1,4 @@ | |||||||
| using System.Collections.Generic; | using System.Collections.Generic; | ||||||
| using Microsoft.Extensions.Options; |  | ||||||
| using Moq; | using Moq; | ||||||
| using Ocelot.Library.Infrastructure.Configuration; | using Ocelot.Library.Infrastructure.Configuration; | ||||||
| using Ocelot.Library.Infrastructure.DownstreamRouteFinder; | using Ocelot.Library.Infrastructure.DownstreamRouteFinder; | ||||||
| @@ -14,38 +13,35 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder | |||||||
|     public class DownstreamRouteFinderTests |     public class DownstreamRouteFinderTests | ||||||
|     { |     { | ||||||
|         private readonly IDownstreamRouteFinder _downstreamRouteFinder; |         private readonly IDownstreamRouteFinder _downstreamRouteFinder; | ||||||
|         private readonly Mock<IOptions<Library.Infrastructure.Configuration.Configuration>> _mockConfig; |         private readonly Mock<IOcelotConfiguration> _mockConfig; | ||||||
|         private readonly Mock<IUrlPathToUrlTemplateMatcher> _mockMatcher; |         private readonly Mock<IUrlPathToUrlTemplateMatcher> _mockMatcher; | ||||||
|  |         private readonly Mock<ITemplateVariableNameAndValueFinder> _finder; | ||||||
|         private string _upstreamUrlPath; |         private string _upstreamUrlPath; | ||||||
|         private Response<DownstreamRoute> _result; |         private Response<DownstreamRoute> _result; | ||||||
|         private Response<DownstreamRoute> _response; |         private Response<DownstreamRoute> _response; | ||||||
|         private Library.Infrastructure.Configuration.Configuration _configuration; |         private List<ReRoute> _reRoutesConfig; | ||||||
|         private UrlMatch _match; |         private Response<UrlMatch> _match; | ||||||
|         private string _upstreamHttpMethod; |         private string _upstreamHttpMethod; | ||||||
|  |  | ||||||
|         public DownstreamRouteFinderTests() |         public DownstreamRouteFinderTests() | ||||||
|         { |         { | ||||||
|             _mockConfig = new Mock<IOptions<Library.Infrastructure.Configuration.Configuration>>(); |             _mockConfig = new Mock<IOcelotConfiguration>(); | ||||||
|             _mockMatcher = new Mock<IUrlPathToUrlTemplateMatcher>(); |             _mockMatcher = new Mock<IUrlPathToUrlTemplateMatcher>(); | ||||||
|             _downstreamRouteFinder = new Library.Infrastructure.DownstreamRouteFinder.DownstreamRouteFinder(_mockConfig.Object, _mockMatcher.Object); |             _finder = new Mock<ITemplateVariableNameAndValueFinder>(); | ||||||
|  |             _downstreamRouteFinder = new Library.Infrastructure.DownstreamRouteFinder.DownstreamRouteFinder(_mockConfig.Object, _mockMatcher.Object, _finder.Object); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         [Fact] |         [Fact] | ||||||
|         public void should_return_route() |         public void should_return_route() | ||||||
|         { |         { | ||||||
|             this.Given(x => x.GivenThereIsAnUpstreamUrlPath("someUpstreamPath")) |             this.Given(x => x.GivenThereIsAnUpstreamUrlPath("someUpstreamPath")) | ||||||
|                 .And(x => x.GivenTheConfigurationIs(new Library.Infrastructure.Configuration.Configuration { |                 .And(x => x.GivenTheTemplateVariableAndNameFinderReturns(new OkResponse<List<TemplateVariableNameAndValue>>(new List<TemplateVariableNameAndValue>()))) | ||||||
|                     ReRoutes = new List<ReRoute> |                 .And(x => x.GivenTheConfigurationIs(new List<ReRoute> | ||||||
|                     { |                     { | ||||||
|                         new ReRoute() |                         new ReRoute("someDownstreamPath","someUpstreamPath", "Get", "someUpstreamPath") | ||||||
|                         { |  | ||||||
|                             UpstreamTemplate = "someUpstreamPath", |  | ||||||
|                             DownstreamTemplate = "someDownstreamPath", |  | ||||||
|                             UpstreamHttpMethod = "Get" |  | ||||||
|                         } |  | ||||||
|                     } |                     } | ||||||
|                 })) |                 )) | ||||||
|                 .And(x => x.GivenTheUrlMatcherReturns(new UrlMatch(true, new List<TemplateVariableNameAndValue>(), "someDownstreamPath"))) |                 .And(x => x.GivenTheUrlMatcherReturns(new OkResponse<UrlMatch>(new UrlMatch(true)))) | ||||||
|                 .And(x => x.GivenTheUpstreamHttpMethodIs("Get")) |                 .And(x => x.GivenTheUpstreamHttpMethodIs("Get")) | ||||||
|                 .When(x => x.WhenICallTheFinder()) |                 .When(x => x.WhenICallTheFinder()) | ||||||
|                 .Then( |                 .Then( | ||||||
| @@ -58,25 +54,14 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder | |||||||
|         public void should_return_correct_route_for_http_verb() |         public void should_return_correct_route_for_http_verb() | ||||||
|         { |         { | ||||||
|             this.Given(x => x.GivenThereIsAnUpstreamUrlPath("someUpstreamPath")) |             this.Given(x => x.GivenThereIsAnUpstreamUrlPath("someUpstreamPath")) | ||||||
|                 .And(x => x.GivenTheConfigurationIs(new Library.Infrastructure.Configuration.Configuration |                 .And(x => x.GivenTheTemplateVariableAndNameFinderReturns(new OkResponse<List<TemplateVariableNameAndValue>>(new List<TemplateVariableNameAndValue>()))) | ||||||
|                 { |                 .And(x => x.GivenTheConfigurationIs(new List<ReRoute> | ||||||
|                     ReRoutes = new List<ReRoute> |  | ||||||
|                     { |                     { | ||||||
|                         new ReRoute() |                         new ReRoute("someDownstreamPath", "someUpstreamPath", "Get", string.Empty), | ||||||
|                         { |                         new ReRoute("someDownstreamPathForAPost", "someUpstreamPath", "Post", string.Empty) | ||||||
|                             UpstreamTemplate = "someUpstreamPath", |  | ||||||
|                             DownstreamTemplate = "someDownstreamPath", |  | ||||||
|                             UpstreamHttpMethod = "Get" |  | ||||||
|                         }, |  | ||||||
|                          new ReRoute() |  | ||||||
|                         { |  | ||||||
|                             UpstreamTemplate = "someUpstreamPath", |  | ||||||
|                             DownstreamTemplate = "someDownstreamPathForAPost", |  | ||||||
|                             UpstreamHttpMethod = "Post" |  | ||||||
|                         } |  | ||||||
|                     } |                     } | ||||||
|                 })) |                 )) | ||||||
|                 .And(x => x.GivenTheUrlMatcherReturns(new UrlMatch(true, new List<TemplateVariableNameAndValue>(), "someDownstreamPathForAPost"))) |                 .And(x => x.GivenTheUrlMatcherReturns(new OkResponse<UrlMatch>(new UrlMatch(true)))) | ||||||
|                 .And(x => x.GivenTheUpstreamHttpMethodIs("Post")) |                 .And(x => x.GivenTheUpstreamHttpMethodIs("Post")) | ||||||
|                 .When(x => x.WhenICallTheFinder()) |                 .When(x => x.WhenICallTheFinder()) | ||||||
|                 .Then( |                 .Then( | ||||||
| @@ -88,19 +73,12 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder | |||||||
|         public void should_not_return_route() |         public void should_not_return_route() | ||||||
|         { |         { | ||||||
|             this.Given(x => x.GivenThereIsAnUpstreamUrlPath("somePath")) |             this.Given(x => x.GivenThereIsAnUpstreamUrlPath("somePath")) | ||||||
|                  .And(x => x.GivenTheConfigurationIs(new Library.Infrastructure.Configuration.Configuration |                  .And(x => x.GivenTheConfigurationIs(new List<ReRoute> | ||||||
|                  { |  | ||||||
|                      ReRoutes = new List<ReRoute> |  | ||||||
|                      { |                      { | ||||||
|                         new ReRoute() |                         new ReRoute("somPath", "somePath", "Get", "somePath") | ||||||
|                         { |  | ||||||
|                             UpstreamTemplate = "somePath", |  | ||||||
|                             DownstreamTemplate = "somPath", |  | ||||||
|                             UpstreamHttpMethod = "Get" |  | ||||||
|                         } |  | ||||||
|                      } |                      } | ||||||
|                  })) |                  )) | ||||||
|                  .And(x => x.GivenTheUrlMatcherReturns(new UrlMatch(false, new List<TemplateVariableNameAndValue>(), null))) |                  .And(x => x.GivenTheUrlMatcherReturns(new OkResponse<UrlMatch>(new UrlMatch(false)))) | ||||||
|                  .And(x => x.GivenTheUpstreamHttpMethodIs("Get")) |                  .And(x => x.GivenTheUpstreamHttpMethodIs("Get")) | ||||||
|                  .When(x => x.WhenICallTheFinder()) |                  .When(x => x.WhenICallTheFinder()) | ||||||
|                  .Then( |                  .Then( | ||||||
| @@ -109,6 +87,13 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder | |||||||
|                  .BDDfy(); |                  .BDDfy(); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  |         private void GivenTheTemplateVariableAndNameFinderReturns(Response<List<TemplateVariableNameAndValue>> response) | ||||||
|  |         { | ||||||
|  |             _finder | ||||||
|  |                 .Setup(x => x.Find(It.IsAny<string>(), It.IsAny<string>())) | ||||||
|  |                 .Returns(response); | ||||||
|  |         } | ||||||
|  |  | ||||||
|         private void GivenTheUpstreamHttpMethodIs(string upstreamHttpMethod) |         private void GivenTheUpstreamHttpMethodIs(string upstreamHttpMethod) | ||||||
|         { |         { | ||||||
|             _upstreamHttpMethod = upstreamHttpMethod; |             _upstreamHttpMethod = upstreamHttpMethod; | ||||||
| @@ -122,10 +107,10 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder | |||||||
|         private void ThenTheUrlMatcherIsCalledCorrectly() |         private void ThenTheUrlMatcherIsCalledCorrectly() | ||||||
|         { |         { | ||||||
|             _mockMatcher |             _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<UrlMatch> match) | ||||||
|         { |         { | ||||||
|             _match = match; |             _match = match; | ||||||
|             _mockMatcher |             _mockMatcher | ||||||
| @@ -133,12 +118,12 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder | |||||||
|                 .Returns(_match); |                 .Returns(_match); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         private void GivenTheConfigurationIs(Library.Infrastructure.Configuration.Configuration configuration) |         private void GivenTheConfigurationIs(List<ReRoute> reRoutesConfig) | ||||||
|         { |         { | ||||||
|             _configuration = configuration; |             _reRoutesConfig = reRoutesConfig; | ||||||
|             _mockConfig |             _mockConfig | ||||||
|                 .Setup(x => x.Value) |                 .Setup(x => x.ReRoutes) | ||||||
|                 .Returns(_configuration); |                 .Returns(_reRoutesConfig); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         private void GivenThereIsAnUpstreamUrlPath(string upstreamUrlPath) |         private void GivenThereIsAnUpstreamUrlPath(string upstreamUrlPath) | ||||||
|   | |||||||
| @@ -6,6 +6,7 @@ using System.Net.Http; | |||||||
| using Microsoft.AspNetCore.Http; | using Microsoft.AspNetCore.Http; | ||||||
| using Microsoft.AspNetCore.Http.Internal; | using Microsoft.AspNetCore.Http.Internal; | ||||||
| using Ocelot.Library.Infrastructure.RequestBuilder; | using Ocelot.Library.Infrastructure.RequestBuilder; | ||||||
|  | using Ocelot.Library.Infrastructure.Responses; | ||||||
| using Shouldly; | using Shouldly; | ||||||
| using TestStack.BDDfy; | using TestStack.BDDfy; | ||||||
| using Xunit; | using Xunit; | ||||||
| @@ -22,7 +23,7 @@ namespace Ocelot.UnitTests.RequestBuilder | |||||||
|         private string _query; |         private string _query; | ||||||
|         private string _contentType; |         private string _contentType; | ||||||
|         private readonly IRequestBuilder _requestBuilder; |         private readonly IRequestBuilder _requestBuilder; | ||||||
|         private Request _result; |         private Response<Request> _result; | ||||||
|  |  | ||||||
|         public RequestBuilderTests() |         public RequestBuilderTests() | ||||||
|         { |         { | ||||||
| @@ -131,7 +132,7 @@ namespace Ocelot.UnitTests.RequestBuilder | |||||||
|  |  | ||||||
|         private void ThenTheCorrectQueryStringIsUsed(string expected) |         private void ThenTheCorrectQueryStringIsUsed(string expected) | ||||||
|         { |         { | ||||||
|             _result.HttpRequestMessage.RequestUri.Query.ShouldBe(expected); |             _result.Data.HttpRequestMessage.RequestUri.Query.ShouldBe(expected); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         private void GivenTheQueryStringIs(string query) |         private void GivenTheQueryStringIs(string query) | ||||||
| @@ -141,7 +142,7 @@ namespace Ocelot.UnitTests.RequestBuilder | |||||||
|  |  | ||||||
|         private void ThenTheCorrectCookiesAreUsed(IRequestCookieCollection expected) |         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<Cookie>().ToDictionary(cook => cook.Name, cook => cook.Value); |             var resultDictionary = resultCookies.Cast<Cookie>().ToDictionary(cook => cook.Name, cook => cook.Value); | ||||||
|  |  | ||||||
|             foreach (var expectedCookie in expected) |             foreach (var expectedCookie in expected) | ||||||
| @@ -162,7 +163,7 @@ namespace Ocelot.UnitTests.RequestBuilder | |||||||
|  |  | ||||||
|             foreach (var expectedHeader in expectedHeaders) |             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) |             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] |                 && x.Value.First() == expectedHeader.Value[0] | ||||||
|                 ); |                 ); | ||||||
|             } |             } | ||||||
| @@ -207,17 +208,17 @@ namespace Ocelot.UnitTests.RequestBuilder | |||||||
|  |  | ||||||
|         private void ThenTheCorrectDownstreamUrlIsUsed(string expected) |         private void ThenTheCorrectDownstreamUrlIsUsed(string expected) | ||||||
|         { |         { | ||||||
|             _result.HttpRequestMessage.RequestUri.AbsoluteUri.ShouldBe(expected); |             _result.Data.HttpRequestMessage.RequestUri.AbsoluteUri.ShouldBe(expected); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         private void ThenTheCorrectHttpMethodIsUsed(HttpMethod 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) |         private void ThenTheCorrectContentIsUsed(HttpContent expected) | ||||||
|         { |         { | ||||||
|             _result.HttpRequestMessage.Content.ReadAsStringAsync().Result.ShouldBe(expected.ReadAsStringAsync().Result); |             _result.Data.HttpRequestMessage.Content.ReadAsStringAsync().Result.ShouldBe(expected.ReadAsStringAsync().Result); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
|   | |||||||
							
								
								
									
										156
									
								
								test/Ocelot.UnitTests/UrlMatcher/RegExUrlMatcherTests.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										156
									
								
								test/Ocelot.UnitTests/UrlMatcher/RegExUrlMatcherTests.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -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<UrlMatch> _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(); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | }  | ||||||
| @@ -1,5 +1,6 @@ | |||||||
| using System.Collections.Generic; | using System.Collections.Generic; | ||||||
| using System.Linq; | using System.Linq; | ||||||
|  | using Ocelot.Library.Infrastructure.Responses; | ||||||
| using Ocelot.Library.Infrastructure.UrlMatcher; | using Ocelot.Library.Infrastructure.UrlMatcher; | ||||||
| using Shouldly; | using Shouldly; | ||||||
| using TestStack.BDDfy; | using TestStack.BDDfy; | ||||||
| @@ -9,33 +10,14 @@ namespace Ocelot.UnitTests.UrlMatcher | |||||||
| { | { | ||||||
|     public class UrlPathToUrlTemplateMatcherTests  |     public class UrlPathToUrlTemplateMatcherTests  | ||||||
|     { |     { | ||||||
|         private readonly IUrlPathToUrlTemplateMatcher _urlMatcher; |         private readonly ITemplateVariableNameAndValueFinder _finder; | ||||||
|         private string _downstreamUrlPath; |         private string _downstreamUrlPath; | ||||||
|         private string _downstreamPathTemplate; |         private string _downstreamPathTemplate; | ||||||
|         private UrlMatch _result; |         private Response<List<TemplateVariableNameAndValue>> _result; | ||||||
|  | 
 | ||||||
|         public UrlPathToUrlTemplateMatcherTests() |         public UrlPathToUrlTemplateMatcherTests() | ||||||
|         { |         { | ||||||
|             _urlMatcher = new UrlPathToUrlTemplateMatcher(); |             _finder = new TemplateVariableNameAndValueFinder(); | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         [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(); |  | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         [Fact] |         [Fact] | ||||||
| @@ -43,10 +25,8 @@ namespace Ocelot.UnitTests.UrlMatcher | |||||||
|         { |         { | ||||||
|             this.Given(x => x.GivenIHaveAUpstreamPath("")) |             this.Given(x => x.GivenIHaveAUpstreamPath("")) | ||||||
|                 .And(x => x.GivenIHaveAnUpstreamUrlTemplate("")) |                 .And(x => x.GivenIHaveAnUpstreamUrlTemplate("")) | ||||||
|                 .When(x => x.WhenIMatchThePaths()) |                 .When(x => x.WhenIFindTheUrlVariableNamesAndValues()) | ||||||
|                 .And(x => x.ThenTheResultIsTrue()) |  | ||||||
|                 .And(x => x.ThenTheTemplatesVariablesAre(new List<TemplateVariableNameAndValue>())) |                 .And(x => x.ThenTheTemplatesVariablesAre(new List<TemplateVariableNameAndValue>())) | ||||||
|                 .And(x => x.ThenTheDownstreamUrlTemplateIs("")) |  | ||||||
|                 .BDDfy(); |                 .BDDfy(); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
| @@ -55,10 +35,8 @@ namespace Ocelot.UnitTests.UrlMatcher | |||||||
|         { |         { | ||||||
|             this.Given(x => x.GivenIHaveAUpstreamPath("api")) |             this.Given(x => x.GivenIHaveAUpstreamPath("api")) | ||||||
|                  .Given(x => x.GivenIHaveAnUpstreamUrlTemplate("api")) |                  .Given(x => x.GivenIHaveAnUpstreamUrlTemplate("api")) | ||||||
|                  .When(x => x.WhenIMatchThePaths()) |                  .When(x => x.WhenIFindTheUrlVariableNamesAndValues()) | ||||||
|                  .Then(x => x.ThenTheResultIsTrue()) |  | ||||||
|                  .And(x => x.ThenTheTemplatesVariablesAre(new List<TemplateVariableNameAndValue>())) |                  .And(x => x.ThenTheTemplatesVariablesAre(new List<TemplateVariableNameAndValue>())) | ||||||
|                  .And(x => x.ThenTheDownstreamUrlTemplateIs("api")) |  | ||||||
|                  .BDDfy(); |                  .BDDfy(); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
| @@ -67,10 +45,8 @@ namespace Ocelot.UnitTests.UrlMatcher | |||||||
|         { |         { | ||||||
|             this.Given(x => x.GivenIHaveAUpstreamPath("api/")) |             this.Given(x => x.GivenIHaveAUpstreamPath("api/")) | ||||||
|                  .Given(x => x.GivenIHaveAnUpstreamUrlTemplate("api/")) |                  .Given(x => x.GivenIHaveAnUpstreamUrlTemplate("api/")) | ||||||
|                  .When(x => x.WhenIMatchThePaths()) |                  .When(x => x.WhenIFindTheUrlVariableNamesAndValues()) | ||||||
|                  .Then(x => x.ThenTheResultIsTrue()) |  | ||||||
|                  .And(x => x.ThenTheTemplatesVariablesAre(new List<TemplateVariableNameAndValue>())) |                  .And(x => x.ThenTheTemplatesVariablesAre(new List<TemplateVariableNameAndValue>())) | ||||||
|                  .And(x => x.ThenTheDownstreamUrlTemplateIs("api/")) |  | ||||||
|                  .BDDfy(); |                  .BDDfy(); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
| @@ -79,10 +55,8 @@ namespace Ocelot.UnitTests.UrlMatcher | |||||||
|         { |         { | ||||||
|             this.Given(x => x.GivenIHaveAUpstreamPath("api/product/products/")) |             this.Given(x => x.GivenIHaveAUpstreamPath("api/product/products/")) | ||||||
|               .Given(x => x.GivenIHaveAnUpstreamUrlTemplate("api/product/products/")) |               .Given(x => x.GivenIHaveAnUpstreamUrlTemplate("api/product/products/")) | ||||||
|               .When(x => x.WhenIMatchThePaths()) |               .When(x => x.WhenIFindTheUrlVariableNamesAndValues()) | ||||||
|               .Then(x => x.ThenTheResultIsTrue()) |  | ||||||
|               .And(x => x.ThenTheTemplatesVariablesAre(new List<TemplateVariableNameAndValue>())) |               .And(x => x.ThenTheTemplatesVariablesAre(new List<TemplateVariableNameAndValue>())) | ||||||
|               .And(x => x.ThenTheDownstreamUrlTemplateIs("api/product/products/")) |  | ||||||
|               .BDDfy(); |               .BDDfy(); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
| @@ -96,10 +70,8 @@ namespace Ocelot.UnitTests.UrlMatcher | |||||||
| 
 | 
 | ||||||
|             this.Given(x => x.GivenIHaveAUpstreamPath("api/product/products/1")) |             this.Given(x => x.GivenIHaveAUpstreamPath("api/product/products/1")) | ||||||
|                .Given(x => x.GivenIHaveAnUpstreamUrlTemplate("api/product/products/{productId}")) |                .Given(x => x.GivenIHaveAnUpstreamUrlTemplate("api/product/products/{productId}")) | ||||||
|                .When(x => x.WhenIMatchThePaths()) |                .When(x => x.WhenIFindTheUrlVariableNamesAndValues()) | ||||||
|                .Then(x => x.ThenTheResultIsTrue()) |  | ||||||
|                .And(x => x.ThenTheTemplatesVariablesAre(expectedTemplates)) |                .And(x => x.ThenTheTemplatesVariablesAre(expectedTemplates)) | ||||||
|                .And(x => x.ThenTheDownstreamUrlTemplateIs("api/product/products/{productId}")) |  | ||||||
|                .BDDfy(); |                .BDDfy(); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
| @@ -114,10 +86,8 @@ namespace Ocelot.UnitTests.UrlMatcher | |||||||
| 
 | 
 | ||||||
|             this.Given(x => x.GivenIHaveAUpstreamPath("api/product/products/1/2")) |             this.Given(x => x.GivenIHaveAUpstreamPath("api/product/products/1/2")) | ||||||
|                  .Given(x => x.GivenIHaveAnUpstreamUrlTemplate("api/product/products/{productId}/{categoryId}")) |                  .Given(x => x.GivenIHaveAnUpstreamUrlTemplate("api/product/products/{productId}/{categoryId}")) | ||||||
|                  .When(x => x.WhenIMatchThePaths()) |                  .When(x => x.WhenIFindTheUrlVariableNamesAndValues()) | ||||||
|                  .Then(x => x.ThenTheResultIsTrue()) |  | ||||||
|                  .And(x => x.ThenTheTemplatesVariablesAre(expectedTemplates)) |                  .And(x => x.ThenTheTemplatesVariablesAre(expectedTemplates)) | ||||||
|                  .And(x => x.ThenTheDownstreamUrlTemplateIs("api/product/products/{productId}/{categoryId}")) |  | ||||||
|                  .BDDfy(); |                  .BDDfy(); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
| @@ -132,10 +102,8 @@ namespace Ocelot.UnitTests.UrlMatcher | |||||||
| 
 | 
 | ||||||
|             this.Given(x => x.GivenIHaveAUpstreamPath("api/product/products/1/categories/2")) |             this.Given(x => x.GivenIHaveAUpstreamPath("api/product/products/1/categories/2")) | ||||||
|                 .And(x => x.GivenIHaveAnUpstreamUrlTemplate("api/product/products/{productId}/categories/{categoryId}")) |                 .And(x => x.GivenIHaveAnUpstreamUrlTemplate("api/product/products/{productId}/categories/{categoryId}")) | ||||||
|                 .When(x => x.WhenIMatchThePaths()) |                 .When(x => x.WhenIFindTheUrlVariableNamesAndValues()) | ||||||
|                 .Then(x => x.ThenTheResultIsTrue()) |  | ||||||
|                 .And(x => x.ThenTheTemplatesVariablesAre(expectedTemplates)) |                 .And(x => x.ThenTheTemplatesVariablesAre(expectedTemplates)) | ||||||
|                 .And(x => x.ThenTheDownstreamUrlTemplateIs("api/product/products/{productId}/categories/{categoryId}")) |  | ||||||
|                 .BDDfy(); |                 .BDDfy(); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
| @@ -151,10 +119,8 @@ namespace Ocelot.UnitTests.UrlMatcher | |||||||
| 
 | 
 | ||||||
|             this.Given(x => x.GivenIHaveAUpstreamPath("api/product/products/1/categories/2/variant/123")) |             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}")) |                 .And(x => x.GivenIHaveAnUpstreamUrlTemplate("api/product/products/{productId}/categories/{categoryId}/variant/{variantId}")) | ||||||
|                 .When(x => x.WhenIMatchThePaths()) |                 .When(x => x.WhenIFindTheUrlVariableNamesAndValues()) | ||||||
|                 .Then(x => x.ThenTheResultIsTrue()) |  | ||||||
|                 .And(x => x.ThenTheTemplatesVariablesAre(expectedTemplates)) |                 .And(x => x.ThenTheTemplatesVariablesAre(expectedTemplates)) | ||||||
|                 .And(x => x.ThenTheDownstreamUrlTemplateIs("api/product/products/{productId}/categories/{categoryId}/variant/{variantId}")) |  | ||||||
|                 .BDDfy(); |                 .BDDfy(); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
| @@ -169,10 +135,8 @@ namespace Ocelot.UnitTests.UrlMatcher | |||||||
| 
 | 
 | ||||||
|             this.Given(x => x.GivenIHaveAUpstreamPath("api/product/products/1/categories/2/variant/")) |             this.Given(x => x.GivenIHaveAUpstreamPath("api/product/products/1/categories/2/variant/")) | ||||||
|                  .And(x => x.GivenIHaveAnUpstreamUrlTemplate("api/product/products/{productId}/categories/{categoryId}/variant/")) |                  .And(x => x.GivenIHaveAnUpstreamUrlTemplate("api/product/products/{productId}/categories/{categoryId}/variant/")) | ||||||
|                  .When(x => x.WhenIMatchThePaths()) |                  .When(x => x.WhenIFindTheUrlVariableNamesAndValues()) | ||||||
|                  .Then(x => x.ThenTheResultIsTrue()) |  | ||||||
|                  .And(x => x.ThenTheTemplatesVariablesAre(expectedTemplates)) |                  .And(x => x.ThenTheTemplatesVariablesAre(expectedTemplates)) | ||||||
|                  .And(x => x.ThenTheDownstreamUrlTemplateIs("api/product/products/{productId}/categories/{categoryId}/variant/")) |  | ||||||
|                  .BDDfy(); |                  .BDDfy(); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
| @@ -180,16 +144,12 @@ namespace Ocelot.UnitTests.UrlMatcher | |||||||
|         { |         { | ||||||
|             foreach (var expectedResult in expectedResults) |             foreach (var expectedResult in expectedResults) | ||||||
|             { |             { | ||||||
|                 var result = _result.TemplateVariableNameAndValues |                 var result = _result.Data | ||||||
|                     .First(t => t.TemplateVariableName == expectedResult.TemplateVariableName); |                     .First(t => t.TemplateVariableName == expectedResult.TemplateVariableName); | ||||||
|                 result.TemplateVariableValue.ShouldBe(expectedResult.TemplateVariableValue); |                 result.TemplateVariableValue.ShouldBe(expectedResult.TemplateVariableValue); | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         private void ThenTheDownstreamUrlTemplateIs(string expectedDownstreamUrlTemplate) |  | ||||||
|         { |  | ||||||
|             _result.DownstreamUrlTemplate.ShouldBe(expectedDownstreamUrlTemplate); |  | ||||||
|         } |  | ||||||
|         private void GivenIHaveAUpstreamPath(string downstreamPath) |         private void GivenIHaveAUpstreamPath(string downstreamPath) | ||||||
|         { |         { | ||||||
|             _downstreamUrlPath = downstreamPath; |             _downstreamUrlPath = downstreamPath; | ||||||
| @@ -200,19 +160,9 @@ namespace Ocelot.UnitTests.UrlMatcher | |||||||
|             _downstreamPathTemplate = downstreamUrlTemplate; |             _downstreamPathTemplate = downstreamUrlTemplate; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         private void WhenIMatchThePaths() |         private void WhenIFindTheUrlVariableNamesAndValues() | ||||||
|         { |         { | ||||||
|             _result = _urlMatcher.Match(_downstreamUrlPath, _downstreamPathTemplate); |             _result = _finder.Find(_downstreamUrlPath, _downstreamPathTemplate); | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         private void ThenTheResultIsTrue() |  | ||||||
|         { |  | ||||||
|             _result.Match.ShouldBeTrue(); |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         private void ThenTheResultIsFalse() |  | ||||||
|         { |  | ||||||
|             _result.Match.ShouldBeFalse(); |  | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| }  | }  | ||||||
| @@ -1,5 +1,6 @@ | |||||||
| using System.Collections.Generic; | using System.Collections.Generic; | ||||||
| using Ocelot.Library.Infrastructure.DownstreamRouteFinder; | using Ocelot.Library.Infrastructure.DownstreamRouteFinder; | ||||||
|  | using Ocelot.Library.Infrastructure.Responses; | ||||||
| using Ocelot.Library.Infrastructure.UrlMatcher; | using Ocelot.Library.Infrastructure.UrlMatcher; | ||||||
| using Ocelot.Library.Infrastructure.UrlTemplateReplacer; | using Ocelot.Library.Infrastructure.UrlTemplateReplacer; | ||||||
| using Shouldly; | using Shouldly; | ||||||
| @@ -11,7 +12,7 @@ namespace Ocelot.UnitTests.UrlTemplateReplacer | |||||||
|     public class UpstreamUrlPathTemplateVariableReplacerTests |     public class UpstreamUrlPathTemplateVariableReplacerTests | ||||||
|     { |     { | ||||||
|         private DownstreamRoute _downstreamRoute; |         private DownstreamRoute _downstreamRoute; | ||||||
|         private string _result; |         private Response<string> _result; | ||||||
|         private readonly IDownstreamUrlTemplateVariableReplacer _downstreamUrlPathReplacer; |         private readonly IDownstreamUrlTemplateVariableReplacer _downstreamUrlPathReplacer; | ||||||
|  |  | ||||||
|         public UpstreamUrlPathTemplateVariableReplacerTests() |         public UpstreamUrlPathTemplateVariableReplacerTests() | ||||||
| @@ -135,7 +136,7 @@ namespace Ocelot.UnitTests.UrlTemplateReplacer | |||||||
|  |  | ||||||
|         private void ThenTheDownstreamUrlPathIsReturned(string expected) |         private void ThenTheDownstreamUrlPathIsReturned(string expected) | ||||||
|         { |         { | ||||||
|             _result.ShouldBe(expected); |             _result.Data.ShouldBe(expected); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|     } |     } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 TomPallister
					TomPallister