mirror of
				https://github.com/nsnail/Ocelot.git
				synced 2025-10-31 10:19:26 +08:00 
			
		
		
		
	method to match urls and template urls
This commit is contained in:
		| @@ -1,10 +0,0 @@ | ||||
| using Ocelot.Library.Infrastructure.Responses; | ||||
|  | ||||
| namespace Ocelot.Library.Infrastructure.Router | ||||
| { | ||||
|     public interface IRouterService | ||||
|     { | ||||
|         Response AddRoute(string apiKey, string upstreamApiBaseUrl); | ||||
|         Response<Route> GetRoute(string apiKey); | ||||
|     } | ||||
| } | ||||
| @@ -1,41 +0,0 @@ | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
| using Ocelot.Library.Infrastructure.Responses; | ||||
|  | ||||
| namespace Ocelot.Library.Infrastructure.Router | ||||
| { | ||||
|     public class InMemoryRouterService : IRouterService | ||||
|     { | ||||
|         private readonly Dictionary<string, string> _routes; | ||||
|         public InMemoryRouterService() | ||||
|         { | ||||
|             _routes = new Dictionary<string,string>(); | ||||
|         } | ||||
|         public Response AddRoute(string apiKey, string upstreamApiBaseUrl) | ||||
|         { | ||||
|             if(_routes.ContainsKey(apiKey)) | ||||
|             { | ||||
|                 return new ErrorResponse(new List<Error>(){new RouteKeyAlreadyExists("This key has already been used")}); | ||||
|             } | ||||
|  | ||||
|             _routes.Add(apiKey, upstreamApiBaseUrl); | ||||
|  | ||||
|             return new OkResponse(); | ||||
|         } | ||||
|  | ||||
|         public Response<Route> GetRoute(string apiKey) | ||||
|         { | ||||
|             Console.WriteLine("looking for {0}", apiKey); | ||||
|             string upstreamApiBaseUrl = null; | ||||
|  | ||||
|             if(_routes.TryGetValue(apiKey, out upstreamApiBaseUrl)) | ||||
|             { | ||||
|                 return new OkResponse<Route>(new Route(apiKey, upstreamApiBaseUrl)); | ||||
|             } | ||||
|  | ||||
|             Console.WriteLine("Couldnt find it"); | ||||
|      | ||||
|             return new ErrorResponse<Route>(new List<Error>(){new RouteKeyDoesNotExist("This key does not exist")}); | ||||
|         }  | ||||
|     }  | ||||
| } | ||||
| @@ -1,14 +0,0 @@ | ||||
| namespace Ocelot.Library.Infrastructure.Router | ||||
| { | ||||
|     public class Route | ||||
|     { | ||||
|         public Route(string apiKey, string upstreamRoute) | ||||
|         { | ||||
|             ApiKey = apiKey; | ||||
|             UpstreamRoute = upstreamRoute; | ||||
|         } | ||||
|  | ||||
|         public string ApiKey {get;private set;} | ||||
|         public string UpstreamRoute {get;private set;} | ||||
|     } | ||||
| } | ||||
| @@ -1,12 +0,0 @@ | ||||
| using Ocelot.Library.Infrastructure.Responses; | ||||
|  | ||||
| namespace Ocelot.Library.Infrastructure.Router | ||||
| { | ||||
|     public class RouteKeyAlreadyExists : Error | ||||
|     { | ||||
|         public RouteKeyAlreadyExists(string message)  | ||||
|             : base(message) | ||||
|         { | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -1,12 +0,0 @@ | ||||
| using Ocelot.Library.Infrastructure.Responses; | ||||
|  | ||||
| namespace Ocelot.Library.Infrastructure.Router | ||||
| { | ||||
|     public class RouteKeyDoesNotExist : Error | ||||
|     { | ||||
|         public RouteKeyDoesNotExist(string message)  | ||||
|             : base(message) | ||||
|         { | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,10 @@ | ||||
| using Ocelot.Library.Infrastructure.Responses; | ||||
|  | ||||
| namespace Ocelot.Library.Infrastructure.Router.UpstreamRouter | ||||
| { | ||||
|     public interface IUpstreamRouter | ||||
|     { | ||||
|         Response AddRoute(string downstreamUrl, string upstreamUrl); | ||||
|         Response<Route> GetRoute(string downstreamUrl); | ||||
|     } | ||||
| }  | ||||
| @@ -0,0 +1,38 @@ | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
| using Ocelot.Library.Infrastructure.Responses; | ||||
|  | ||||
| namespace Ocelot.Library.Infrastructure.Router.UpstreamRouter | ||||
| { | ||||
|     public class InMemoryUpstreamRouter : IUpstreamRouter | ||||
|     {  | ||||
|         private readonly Dictionary<string, string> _routes; | ||||
|         public InMemoryUpstreamRouter() | ||||
|         { | ||||
|             _routes = new Dictionary<string,string>(); | ||||
|         } | ||||
|         public Response AddRoute(string downstreamUrl, string upstreamUrl) | ||||
|         { | ||||
|             if(_routes.ContainsKey(downstreamUrl))  | ||||
|             { | ||||
|                 return new ErrorResponse(new List<Error>(){new RouteKeyAlreadyExists()}); | ||||
|             } | ||||
|  | ||||
|             _routes.Add(downstreamUrl, upstreamUrl); | ||||
|  | ||||
|             return new OkResponse(); | ||||
|         } | ||||
|  | ||||
|         public Response<Route> GetRoute(string downstreamUrl) | ||||
|         { | ||||
|             string upstreamUrl = null; | ||||
|  | ||||
|             if(_routes.TryGetValue(downstreamUrl, out upstreamUrl)) | ||||
|             { | ||||
|                 return new OkResponse<Route>(new Route(downstreamUrl, upstreamUrl)); | ||||
|             } | ||||
|      | ||||
|             return new ErrorResponse<Route>(new List<Error>(){new RouteKeyDoesNotExist()}); | ||||
|         }  | ||||
|     }  | ||||
| } | ||||
| @@ -0,0 +1,14 @@ | ||||
| namespace Ocelot.Library.Infrastructure.Router.UpstreamRouter | ||||
| { | ||||
|     public class Route | ||||
|     { | ||||
|         public Route(string downstreamUrl, string upstreamUrl) | ||||
|         { | ||||
|             DownstreamUrl = downstreamUrl; | ||||
|             UpstreamUrl = upstreamUrl; | ||||
|         } | ||||
|  | ||||
|         public string DownstreamUrl {get;private set;} | ||||
|         public string UpstreamUrl {get;private set;} | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,12 @@ | ||||
| using Ocelot.Library.Infrastructure.Responses; | ||||
|  | ||||
| namespace Ocelot.Library.Infrastructure.Router.UpstreamRouter | ||||
| { | ||||
|     public class RouteKeyAlreadyExists : Error | ||||
|     { | ||||
|         public RouteKeyAlreadyExists()  | ||||
|             : base("This key has already been used") | ||||
|         { | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,12 @@ | ||||
| using Ocelot.Library.Infrastructure.Responses; | ||||
|  | ||||
| namespace Ocelot.Library.Infrastructure.Router.UpstreamRouter | ||||
| { | ||||
|     public class RouteKeyDoesNotExist : Error | ||||
|     { | ||||
|         public RouteKeyDoesNotExist()  | ||||
|             : base("This key does not exist") | ||||
|         { | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,12 @@ | ||||
| using Ocelot.Library.Infrastructure.Responses; | ||||
|  | ||||
| namespace Ocelot.Library.Infrastructure.Router.UrlPathRouter | ||||
| { | ||||
|     public class DownstreamUrlPathTemplateAlreadyExists : Error | ||||
|     { | ||||
|         public DownstreamUrlPathTemplateAlreadyExists()  | ||||
|             : base("This key has already been used") | ||||
|         { | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,12 @@ | ||||
| using Ocelot.Library.Infrastructure.Responses; | ||||
|  | ||||
| namespace Ocelot.Library.Infrastructure.Router.UrlPathRouter | ||||
| { | ||||
|     public class DownstreamUrlPathTemplateDoesNotExist : Error | ||||
|     { | ||||
|         public DownstreamUrlPathTemplateDoesNotExist()  | ||||
|             : base("This key does not exist") | ||||
|         { | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,10 @@ | ||||
| using Ocelot.Library.Infrastructure.Responses; | ||||
|  | ||||
| namespace Ocelot.Library.Infrastructure.Router.UrlPathRouter | ||||
| { | ||||
|     public interface IUrlPathRouter | ||||
|     { | ||||
|         Response AddRoute(string downstreamUrlPathTemplate, string upstreamUrlPathTemplate); | ||||
|         Response<UrlPath> GetRoute(string downstreamUrlPathTemplate); | ||||
|     } | ||||
| }   | ||||
| @@ -0,0 +1,38 @@ | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
| using Ocelot.Library.Infrastructure.Responses; | ||||
|  | ||||
| namespace Ocelot.Library.Infrastructure.Router.UrlPathRouter | ||||
| { | ||||
|     public class InMemoryUrlPathRouter : IUrlPathRouter | ||||
|     {  | ||||
|         private readonly Dictionary<string, string> _routes; | ||||
|         public InMemoryUrlPathRouter() | ||||
|         { | ||||
|             _routes = new Dictionary<string,string>(); | ||||
|         } | ||||
|         public Response AddRoute(string downstreamUrlPathTemplate, string upstreamUrlPathTemplate) | ||||
|         { | ||||
|             if(_routes.ContainsKey(downstreamUrlPathTemplate)) | ||||
|             { | ||||
|                 return new ErrorResponse(new List<Error>(){new DownstreamUrlPathTemplateAlreadyExists()}); | ||||
|             } | ||||
|  | ||||
|             _routes.Add(downstreamUrlPathTemplate, upstreamUrlPathTemplate); | ||||
|  | ||||
|             return new OkResponse(); | ||||
|         } | ||||
|  | ||||
|         public Response<UrlPath> GetRoute(string downstreamUrlPathTemplate) | ||||
|         { | ||||
|             string upstreamUrlPathTemplate = null; | ||||
|  | ||||
|             if(_routes.TryGetValue(downstreamUrlPathTemplate, out upstreamUrlPathTemplate)) | ||||
|             { | ||||
|                 return new OkResponse<UrlPath>(new UrlPath(downstreamUrlPathTemplate, upstreamUrlPathTemplate)); | ||||
|             } | ||||
|  | ||||
|             return new ErrorResponse<UrlPath>(new List<Error>(){new DownstreamUrlPathTemplateDoesNotExist()}); | ||||
|         }  | ||||
|     }  | ||||
| } | ||||
| @@ -0,0 +1,14 @@ | ||||
| namespace Ocelot.Library.Infrastructure.Router.UrlPathRouter | ||||
| { | ||||
|     public class UrlPath | ||||
|     { | ||||
|         public UrlPath(string downstreamUrlPathTemplate, string upstreamUrlPathTemplate) | ||||
|         { | ||||
|             DownstreamUrlPathTemplate = downstreamUrlPathTemplate; | ||||
|             UpstreamUrlPathTemplate = upstreamUrlPathTemplate; | ||||
|         } | ||||
|  | ||||
|         public string DownstreamUrlPathTemplate {get;private set;} | ||||
|         public string UpstreamUrlPathTemplate {get;private set;} | ||||
|     } | ||||
| } | ||||
							
								
								
									
										234
									
								
								test/Ocelot.AcceptanceTests/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										234
									
								
								test/Ocelot.AcceptanceTests/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,234 @@ | ||||
| ## Ignore Visual Studio temporary files, build results, and | ||||
| ## files generated by popular Visual Studio add-ons. | ||||
|  | ||||
| # User-specific files | ||||
| *.suo | ||||
| *.user | ||||
| *.userosscache | ||||
| *.sln.docstates | ||||
|  | ||||
| # User-specific files (MonoDevelop/Xamarin Studio) | ||||
| *.userprefs | ||||
|  | ||||
| # Build results | ||||
| [Dd]ebug/ | ||||
| [Dd]ebugPublic/ | ||||
| [Rr]elease/ | ||||
| [Rr]eleases/ | ||||
| x64/ | ||||
| x86/ | ||||
| build/ | ||||
| bld/ | ||||
| [Bb]in/ | ||||
| [Oo]bj/ | ||||
|  | ||||
| # Visual Studio 2015 cache/options directory | ||||
| .vs/ | ||||
| # Uncomment if you have tasks that create the project's static files in wwwroot | ||||
| #wwwroot/ | ||||
|  | ||||
| # MSTest test Results | ||||
| [Tt]est[Rr]esult*/ | ||||
| [Bb]uild[Ll]og.* | ||||
|  | ||||
| # NUNIT | ||||
| *.VisualState.xml | ||||
| TestResult.xml | ||||
|  | ||||
| # Build Results of an ATL Project | ||||
| [Dd]ebugPS/ | ||||
| [Rr]eleasePS/ | ||||
| dlldata.c | ||||
|  | ||||
| # DNX | ||||
| project.lock.json | ||||
| artifacts/ | ||||
|  | ||||
| *_i.c | ||||
| *_p.c | ||||
| *_i.h | ||||
| *.ilk | ||||
| *.meta | ||||
| *.obj | ||||
| *.pch | ||||
| *.pdb | ||||
| *.pgc | ||||
| *.pgd | ||||
| *.rsp | ||||
| *.sbr | ||||
| *.tlb | ||||
| *.tli | ||||
| *.tlh | ||||
| *.tmp | ||||
| *.tmp_proj | ||||
| *.log | ||||
| *.vspscc | ||||
| *.vssscc | ||||
| .builds | ||||
| *.pidb | ||||
| *.svclog | ||||
| *.scc | ||||
|  | ||||
| # Chutzpah Test files | ||||
| _Chutzpah* | ||||
|  | ||||
| # Visual C++ cache files | ||||
| ipch/ | ||||
| *.aps | ||||
| *.ncb | ||||
| *.opendb | ||||
| *.opensdf | ||||
| *.sdf | ||||
| *.cachefile | ||||
|  | ||||
| # Visual Studio profiler | ||||
| *.psess | ||||
| *.vsp | ||||
| *.vspx | ||||
| *.sap | ||||
|  | ||||
| # TFS 2012 Local Workspace | ||||
| $tf/ | ||||
|  | ||||
| # Guidance Automation Toolkit | ||||
| *.gpState | ||||
|  | ||||
| # ReSharper is a .NET coding add-in | ||||
| _ReSharper*/ | ||||
| *.[Rr]e[Ss]harper | ||||
| *.DotSettings.user | ||||
|  | ||||
| # JustCode is a .NET coding add-in | ||||
| .JustCode | ||||
|  | ||||
| # TeamCity is a build add-in | ||||
| _TeamCity* | ||||
|  | ||||
| # DotCover is a Code Coverage Tool | ||||
| *.dotCover | ||||
|  | ||||
| # NCrunch | ||||
| _NCrunch_* | ||||
| .*crunch*.local.xml | ||||
| nCrunchTemp_* | ||||
|  | ||||
| # MightyMoose | ||||
| *.mm.* | ||||
| AutoTest.Net/ | ||||
|  | ||||
| # Web workbench (sass) | ||||
| .sass-cache/ | ||||
|  | ||||
| # Installshield output folder | ||||
| [Ee]xpress/ | ||||
|  | ||||
| # DocProject is a documentation generator add-in | ||||
| DocProject/buildhelp/ | ||||
| DocProject/Help/*.HxT | ||||
| DocProject/Help/*.HxC | ||||
| DocProject/Help/*.hhc | ||||
| DocProject/Help/*.hhk | ||||
| DocProject/Help/*.hhp | ||||
| DocProject/Help/Html2 | ||||
| DocProject/Help/html | ||||
|  | ||||
| # Click-Once directory | ||||
| publish/ | ||||
|  | ||||
| # Publish Web Output | ||||
| *.[Pp]ublish.xml | ||||
| *.azurePubxml | ||||
| # TODO: Comment the next line if you want to checkin your web deploy settings | ||||
| # but database connection strings (with potential passwords) will be unencrypted | ||||
| *.pubxml | ||||
| *.publishproj | ||||
|  | ||||
| # NuGet Packages | ||||
| *.nupkg | ||||
| # The packages folder can be ignored because of Package Restore | ||||
| **/packages/* | ||||
| # except build/, which is used as an MSBuild target. | ||||
| !**/packages/build/ | ||||
| # Uncomment if necessary however generally it will be regenerated when needed | ||||
| #!**/packages/repositories.config | ||||
|  | ||||
| # Microsoft Azure Build Output | ||||
| csx/ | ||||
| *.build.csdef | ||||
|  | ||||
| # Microsoft Azure Emulator | ||||
| ecf/ | ||||
| rcf/ | ||||
|  | ||||
| # Microsoft Azure ApplicationInsights config file | ||||
| ApplicationInsights.config | ||||
|  | ||||
| # Windows Store app package directory | ||||
| AppPackages/ | ||||
| BundleArtifacts/ | ||||
|  | ||||
| # Visual Studio cache files | ||||
| # files ending in .cache can be ignored | ||||
| *.[Cc]ache | ||||
| # but keep track of directories ending in .cache | ||||
| !*.[Cc]ache/ | ||||
|  | ||||
| # Others | ||||
| ClientBin/ | ||||
| ~$* | ||||
| *~ | ||||
| *.dbmdl | ||||
| *.dbproj.schemaview | ||||
| *.pfx | ||||
| *.publishsettings | ||||
| node_modules/ | ||||
| orleans.codegen.cs | ||||
|  | ||||
| # RIA/Silverlight projects | ||||
| Generated_Code/ | ||||
|  | ||||
| # Backup & report files from converting an old project file | ||||
| # to a newer Visual Studio version. Backup files are not needed, | ||||
| # because we have git ;-) | ||||
| _UpgradeReport_Files/ | ||||
| Backup*/ | ||||
| UpgradeLog*.XML | ||||
| UpgradeLog*.htm | ||||
|  | ||||
| # SQL Server files | ||||
| *.mdf | ||||
| *.ldf | ||||
|  | ||||
| # Business Intelligence projects | ||||
| *.rdl.data | ||||
| *.bim.layout | ||||
| *.bim_*.settings | ||||
|  | ||||
| # Microsoft Fakes | ||||
| FakesAssemblies/ | ||||
|  | ||||
| # GhostDoc plugin setting file | ||||
| *.GhostDoc.xml | ||||
|  | ||||
| # Node.js Tools for Visual Studio | ||||
| .ntvs_analysis.dat | ||||
|  | ||||
| # Visual Studio 6 build log | ||||
| *.plg | ||||
|  | ||||
| # Visual Studio 6 workspace options file | ||||
| *.opt | ||||
|  | ||||
| # Visual Studio LightSwitch build output | ||||
| **/*.HTMLClient/GeneratedArtifacts | ||||
| **/*.DesktopClient/GeneratedArtifacts | ||||
| **/*.DesktopClient/ModelManifest.xml | ||||
| **/*.Server/GeneratedArtifacts | ||||
| **/*.Server/ModelManifest.xml | ||||
| _Pvt_Extensions | ||||
|  | ||||
| # Paket dependency manager | ||||
| .paket/paket.exe | ||||
|  | ||||
| # FAKE - F# Make | ||||
| .fake/ | ||||
							
								
								
									
										24
									
								
								test/Ocelot.AcceptanceTests/RouterTests.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								test/Ocelot.AcceptanceTests/RouterTests.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,24 @@ | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
| using System.IO; | ||||
| using System.Linq; | ||||
| using System.Threading.Tasks; | ||||
| using Microsoft.AspNetCore.Hosting; | ||||
| using Ocelot; | ||||
| using Xunit; | ||||
|  | ||||
| namespace Ocelot.AcceptanceTests | ||||
| { | ||||
|     public class RouterTests | ||||
|     { | ||||
|         public RouterTests() | ||||
|         { | ||||
|         } | ||||
|  | ||||
|         [Fact] | ||||
|         public void should_route_request() | ||||
|         { | ||||
|              | ||||
|         } | ||||
|     } | ||||
| } | ||||
							
								
								
									
										37
									
								
								test/Ocelot.AcceptanceTests/project.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								test/Ocelot.AcceptanceTests/project.json
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,37 @@ | ||||
| { | ||||
|     "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-*", | ||||
|         "Ocelot": "1.0.0-*", | ||||
|         "xunit": "2.1.0", | ||||
|         "dotnet-test-xunit": "2.2.0-preview2-build1029", | ||||
|         "Shouldly": "2.8.0" | ||||
|     }, | ||||
|  | ||||
|     "frameworks": { | ||||
|         "netcoreapp1.0": { | ||||
|             "imports": [ | ||||
|                 "dotnet5.6", | ||||
|                 "portable-net45+win8" | ||||
|             ] | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -1,5 +1,5 @@ | ||||
| using Ocelot.Library.Infrastructure.Responses; | ||||
| using Ocelot.Library.Infrastructure.Router; | ||||
| using Ocelot.Library.Infrastructure.Router.UpstreamRouter; | ||||
| using Shouldly; | ||||
| using Xunit; | ||||
| 
 | ||||
| @@ -9,13 +9,13 @@ namespace Ocelot.UnitTests | ||||
|     { | ||||
|         private string _upstreamApiUrl; | ||||
|         private string _apiKey; | ||||
|         private IRouterService _router; | ||||
|         private IUpstreamRouter _router; | ||||
|         private Response _response; | ||||
|         private Response<Route> _getRouteResponse; | ||||
| 
 | ||||
|         public RouterTests() | ||||
|         public RouterTests()  | ||||
|         { | ||||
|             _router = new InMemoryRouterService(); | ||||
|             _router = new InMemoryUpstreamRouter(); | ||||
|         } | ||||
| 
 | ||||
|         [Fact] | ||||
| @@ -34,7 +34,7 @@ namespace Ocelot.UnitTests | ||||
|             WhenIRetrieveTheRouteByKey(); | ||||
|             ThenTheRouteIsReturned(); | ||||
|         } | ||||
| 
 | ||||
|   | ||||
|         [Fact] | ||||
|         public void should_return_error_response_when_key_already_used() | ||||
|         { | ||||
| @@ -77,8 +77,8 @@ namespace Ocelot.UnitTests | ||||
| 
 | ||||
|         private void ThenTheRouteIsReturned() | ||||
|         { | ||||
|             _getRouteResponse.Data.ApiKey.ShouldBe(_apiKey); | ||||
|             _getRouteResponse.Data.UpstreamRoute.ShouldBe(_upstreamApiUrl); | ||||
|             _getRouteResponse.Data.DownstreamUrl.ShouldBe(_apiKey); | ||||
|             _getRouteResponse.Data.UpstreamUrl.ShouldBe(_upstreamApiUrl); | ||||
|         } | ||||
| 
 | ||||
|         private void GivenIHaveSetUpAnApiKeyAndUpstreamUrl(string apiKey, string upstreamUrl) | ||||
							
								
								
									
										133
									
								
								test/Ocelot.UnitTests/UrlMapperTests.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										133
									
								
								test/Ocelot.UnitTests/UrlMapperTests.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,133 @@ | ||||
| using System; | ||||
| using Ocelot.Library.Infrastructure.Responses; | ||||
| using Ocelot.Library.Infrastructure.Router.UpstreamRouter; | ||||
| using Shouldly; | ||||
| using Xunit; | ||||
|  | ||||
| namespace Ocelot.UnitTests | ||||
| { | ||||
|     public class UrlMapperTests | ||||
|     { | ||||
|         private UrlToUrlTemplateMatcher _urlMapper; | ||||
|  | ||||
|         public UrlMapperTests() | ||||
|         { | ||||
|             _urlMapper = new UrlToUrlTemplateMatcher(); | ||||
|         } | ||||
|  | ||||
|         [Fact] | ||||
|         public void can_match_down_stream_url_with_downstream_template_with_one_query_string_parameter() | ||||
|         { | ||||
|             var downstreamUrl = "api/product/products/?soldout=false"; | ||||
|             var downstreamTemplate = "api/product/products/"; | ||||
|             var result = _urlMapper.Match(downstreamUrl, downstreamTemplate); | ||||
|             result.ShouldBeTrue(); | ||||
|         } | ||||
|  | ||||
|           [Fact] | ||||
|         public void can_match_down_stream_url_with_downstream_template_with_one_query_string_parameter_and_one_template() | ||||
|         { | ||||
|             var downstreamUrl = "api/product/products/1/variants/?soldout=false"; | ||||
|             var downstreamTemplate = "api/product/products/{productId}/variants/"; | ||||
|             var result = _urlMapper.Match(downstreamUrl, downstreamTemplate); | ||||
|             result.ShouldBeTrue(); | ||||
|         } | ||||
|  | ||||
|         [Fact] | ||||
|         public void can_match_down_stream_url_with_downstream_template_with_one_place_holder() | ||||
|         { | ||||
|             var downstreamUrl = "api/product/products/1"; | ||||
|             var downstreamTemplate = "api/product/products/{productId}"; | ||||
|             var result = _urlMapper.Match(downstreamUrl, downstreamTemplate); | ||||
|             result.ShouldBeTrue(); | ||||
|         } | ||||
|  | ||||
|         [Fact] | ||||
|         public void can_match_down_stream_url_with_downstream_template_with_two_place_holders() | ||||
|         { | ||||
|             var downstreamUrl = "api/product/products/1/2"; | ||||
|             var downstreamTemplate = "api/product/products/{productId}/{categoryId}"; | ||||
|             var result = _urlMapper.Match(downstreamUrl, downstreamTemplate); | ||||
|             result.ShouldBeTrue(); | ||||
|         } | ||||
|  | ||||
|         [Fact] | ||||
|         public void can_match_down_stream_url_with_downstream_template_with_two_place_holders_seperated_by_something() | ||||
|         { | ||||
|             var downstreamUrl = "api/product/products/1/categories/2"; | ||||
|             var downstreamTemplate = "api/product/products/{productId}/categories/{categoryId}"; | ||||
|             var result = _urlMapper.Match(downstreamUrl, downstreamTemplate); | ||||
|             result.ShouldBeTrue(); | ||||
|         } | ||||
|  | ||||
|         [Fact] | ||||
|         public void can_match_down_stream_url_with_downstream_template_with_three_place_holders_seperated_by_something() | ||||
|         { | ||||
|             var downstreamUrl = "api/product/products/1/categories/2/variant/123"; | ||||
|             var downstreamTemplate = "api/product/products/{productId}/categories/{categoryId}/variant/{variantId}"; | ||||
|             var result = _urlMapper.Match(downstreamUrl, downstreamTemplate); | ||||
|             result.ShouldBeTrue(); | ||||
|         } | ||||
|  | ||||
|         [Fact] | ||||
|         public void can_match_down_stream_url_with_downstream_template_with_three_place_holders() | ||||
|         { | ||||
|             var downstreamUrl = "api/product/products/1/categories/2/variant/"; | ||||
|             var downstreamTemplate = "api/product/products/{productId}/categories/{categoryId}/variant/"; | ||||
|             var result = _urlMapper.Match(downstreamUrl, downstreamTemplate); | ||||
|             result.ShouldBeTrue(); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     public class UrlToUrlTemplateMatcher | ||||
|     { | ||||
|         public bool Match(string url, string urlTemplate) | ||||
|         { | ||||
|             url = url.ToLower(); | ||||
|  | ||||
|             urlTemplate = urlTemplate.ToLower(); | ||||
|  | ||||
|             int counterForUrl = 0; | ||||
|  | ||||
|             for (int counterForTemplate = 0; counterForTemplate < urlTemplate.Length; counterForTemplate++) | ||||
|             { | ||||
|                 if (CharactersDontMatch(urlTemplate[counterForTemplate], url[counterForUrl]) && ContinueScanningUrl(counterForUrl,url.Length)) | ||||
|                 { | ||||
|                     if (IsPlaceholder(urlTemplate[counterForTemplate])) | ||||
|                     { | ||||
|                         counterForTemplate = GetNextCounterPosition(urlTemplate, counterForTemplate, '}'); | ||||
|                         counterForUrl = GetNextCounterPosition(url, counterForUrl, '/'); | ||||
|                         continue; | ||||
|                     } | ||||
|                     else | ||||
|                     { | ||||
|                         return false; | ||||
|                     }  | ||||
|                 } | ||||
|                 counterForUrl++; | ||||
|             } | ||||
|             return true; | ||||
|         } | ||||
|  | ||||
|         private int GetNextCounterPosition(string urlTemplate, int counterForTemplate, char delimiter) | ||||
|         {                         | ||||
|             var closingPlaceHolderPositionOnTemplate = urlTemplate.IndexOf(delimiter, counterForTemplate); | ||||
|             return closingPlaceHolderPositionOnTemplate + 1;  | ||||
|         } | ||||
|  | ||||
|         private bool CharactersDontMatch(char characterOne, char characterTwo) | ||||
|         { | ||||
|             return characterOne != characterTwo; | ||||
|         } | ||||
|  | ||||
|         private bool ContinueScanningUrl(int counterForUrl, int urlLength) | ||||
|         { | ||||
|             return counterForUrl < urlLength; | ||||
|         } | ||||
|  | ||||
|         private bool IsPlaceholder(char character) | ||||
|         { | ||||
|             return character == '{'; | ||||
|         } | ||||
|     } | ||||
| }  | ||||
							
								
								
									
										111
									
								
								test/Ocelot.UnitTests/UrlPathRouterTests.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										111
									
								
								test/Ocelot.UnitTests/UrlPathRouterTests.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,111 @@ | ||||
| using Ocelot.Library.Infrastructure.Responses; | ||||
| using Ocelot.Library.Infrastructure.Router.UrlPathRouter; | ||||
| using Shouldly; | ||||
| using Xunit; | ||||
|  | ||||
| namespace Ocelot.UnitTests | ||||
| { | ||||
|     public class UrlPathRouterTests | ||||
|     { | ||||
|         private string _upstreamUrlPath; | ||||
|         private string _downstreamUrlPath; | ||||
|         private IUrlPathRouter _router; | ||||
|         private Response _response; | ||||
|         private Response<UrlPath> _getResponse; | ||||
|  | ||||
|         public UrlPathRouterTests()  | ||||
|         { | ||||
|             _router = new InMemoryUrlPathRouter(); | ||||
|         } | ||||
|  | ||||
|         [Fact] | ||||
|         public void can_add_url_path() | ||||
|         { | ||||
|             GivenIHaveAnUpstreamUrlPath("api/products/products/{productId}"); | ||||
|             GivenIWantToRouteRequestsToMyUpstreamUrlPath("api/products/{productId}"); | ||||
|             WhenIAddTheConfiguration(); | ||||
|             ThenTheResponseIsSuccesful(); | ||||
|         } | ||||
|  | ||||
|         [Fact] | ||||
|         public void can_get_url_path() | ||||
|         { | ||||
|             GivenIHaveSetUpADownstreamUrlPathAndAnUpstreamUrlPath("api2", "http://www.someapi.com/api2"); | ||||
|             WhenIRetrieveTheUrlPathByDownstreamUrl(); | ||||
|             ThenTheUrlPathIsReturned(); | ||||
|         } | ||||
|   | ||||
|         [Fact] | ||||
|         public void should_return_error_response_when_url_path_already_used() | ||||
|         { | ||||
|             GivenIHaveSetUpADownstreamUrlPathAndAnUpstreamUrlPath("api2", "http://www.someapi.com/api2"); | ||||
|             WhenITryToUseTheSameDownstreamUrl(); | ||||
|             ThenTheDownstreamUrlAlreadyBeenUsed(); | ||||
|         } | ||||
|  | ||||
|         [Fact] | ||||
|         public void should_return_error_response_if_key_doesnt_exist() | ||||
|         { | ||||
|             GivenIWantToRouteRequestsToMyUpstreamUrlPath("api"); | ||||
|             WhenIRetrieveTheUrlPathByDownstreamUrl(); | ||||
|             ThenTheKeyDoesNotExist(); | ||||
|         } | ||||
|  | ||||
|         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<UrlPath>>(); | ||||
|             _getResponse.Errors[0].Message.ShouldBe("This key does not exist"); | ||||
|         } | ||||
|  | ||||
|         private void WhenIRetrieveTheUrlPathByDownstreamUrl() | ||||
|         { | ||||
|             _getResponse = _router.GetRoute(_downstreamUrlPath); | ||||
|         } | ||||
|  | ||||
|         private void ThenTheUrlPathIsReturned() | ||||
|         { | ||||
|             _getResponse.Data.DownstreamUrlPathTemplate.ShouldBe(_downstreamUrlPath); | ||||
|             _getResponse.Data.UpstreamUrlPathTemplate.ShouldBe(_upstreamUrlPath); | ||||
|         } | ||||
|  | ||||
|         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 = _router.AddRoute(_downstreamUrlPath, _upstreamUrlPath); | ||||
|         } | ||||
|  | ||||
|         private void ThenTheResponseIsSuccesful() | ||||
|         { | ||||
|             _response.ShouldBeOfType<OkResponse>(); | ||||
|         } | ||||
|     } | ||||
| } | ||||
		Reference in New Issue
	
	Block a user
	 Tom Gardham-Pallister
					Tom Gardham-Pallister