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