mirror of
				https://github.com/nsnail/Ocelot.git
				synced 2025-10-31 22:45:28 +08:00 
			
		
		
		
	split DownstreamTemplate into DownstreamPathTemplate, DownstreamScheme, DownstreamHost and DownstreamPort in order to prepare for service discovery
This commit is contained in:
		| @@ -17,8 +17,10 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution | ||||
| 		Ocelot.nuspec = Ocelot.nuspec | ||||
| 		push-to-nuget.bat = push-to-nuget.bat | ||||
| 		README.md = README.md | ||||
| 		run-acceptance-tests.bat = run-acceptance-tests.bat | ||||
| 		run-benchmarks.bat = run-benchmarks.bat | ||||
| 		run-tests.bat = run-tests.bat | ||||
| 		run-unit-tests.bat = run-unit-tests.bat | ||||
| 	EndProjectSection | ||||
| EndProject | ||||
| Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Ocelot", "src\Ocelot\Ocelot.xproj", "{D6DF4206-0DBA-41D8-884D-C3E08290FDBB}" | ||||
|   | ||||
							
								
								
									
										11
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										11
									
								
								README.md
									
									
									
									
									
								
							| @@ -136,17 +136,20 @@ In order to set up a ReRoute you need to add one to the json array called ReRout | ||||
| the following. | ||||
|  | ||||
| 		{ | ||||
|             "DownstreamTemplate": "http://jsonplaceholder.typicode.com/posts/{postId}", | ||||
|             "DownstreamPathTemplate": "/api/posts/{postId}", | ||||
| 			"DownstreamScheme": "https", | ||||
| 			"DownstreamPort": 80, | ||||
| 			"DownstreamHost" "localhost" | ||||
|             "UpstreamTemplate": "/posts/{postId}", | ||||
|             "UpstreamHttpMethod": "Put" | ||||
|         } | ||||
|  | ||||
| The DownstreamTemplate is the URL that this request will be forwarded to. | ||||
| The DownstreamPathTemplate,Scheme, Port and Host make the URL that this request will be forwarded to. | ||||
| The UpstreamTemplate is the URL that Ocelot will use to identity which  | ||||
| DownstreamTemplate to use for a given request. Finally the UpstreamHttpMethod is used so | ||||
| DownstreamPathTemplate to use for a given request. Finally the UpstreamHttpMethod is used so | ||||
| Ocelot can distinguish between requests to the same URL and is obviously needed to work :) | ||||
| In Ocelot you can add placeholders for variables to your Templates in the form of {something}. | ||||
| The placeholder needs to be in both the DownstreamTemplate and UpstreamTemplate. If it is | ||||
| The placeholder needs to be in both the DownstreamPathTemplate and UpstreamTemplate. If it is | ||||
| Ocelot will attempt to replace the placeholder with the correct variable value from the  | ||||
| Upstream URL when the request comes in. | ||||
|  | ||||
|   | ||||
| @@ -1,11 +1,20 @@ | ||||
| { | ||||
| 	"ReRoutes": [ | ||||
| 		{ | ||||
| 			# The url we are forwarding the request to, ocelot will not add a trailing slash | ||||
| 			"DownstreamTemplate": "http://somehost.com/identityserverexample", | ||||
| 			# The path we are listening on for this re route, Ocelot will add a trailing slash to | ||||
| 			# this property. Then when a request is made Ocelot makes sure a trailing slash is added | ||||
| 			# to that so everything matches | ||||
| 			# The downstream path we are forwarding the request to, ocelot will not add a trailing slash. | ||||
| 			# Ocelot replaces any placeholders {etc} with matched values from the incoming request. | ||||
| 			"DownstreamPathTemplate": "/identityserverexample/{someid}/something", | ||||
| 			# The scheme you want Ocelot to use when making the downstream request | ||||
| 			"DownstreamScheme": "https", | ||||
| 			# The port you want Ocelot to use when making the downstream request, will default to  | ||||
| 			# scheme if nothing set | ||||
| 			"DownstreamPort": 80, | ||||
| 			# The host address of the downstream service, should not have a trailing slash or scheme | ||||
| 			# if there is a trailing slash Ocelot will remove it. | ||||
| 			"DownstreamHost" "localhost" | ||||
| 			# The path template we are listening on for this re route, Ocelot will add a trailing  | ||||
| 			# slash to this property. Then when a request is made Ocelot makes sure a trailing  | ||||
| 			# slash is added, so everything matches | ||||
| 			"UpstreamTemplate": "/identityserverexample", | ||||
| 			# The method we are listening for on this re route | ||||
| 			"UpstreamHttpMethod": "Get", | ||||
|   | ||||
| @@ -1,11 +1,12 @@ | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
| using Ocelot.Values; | ||||
|  | ||||
| namespace Ocelot.Configuration.Builder | ||||
| { | ||||
|     public class ReRouteBuilder | ||||
|     { | ||||
|         private string _downstreamTemplate; | ||||
|         private string _downstreamPathTemplate; | ||||
|         private string _upstreamTemplate; | ||||
|         private string _upstreamTemplatePattern; | ||||
|         private string _upstreamHttpMethod; | ||||
| @@ -30,6 +31,7 @@ namespace Ocelot.Configuration.Builder | ||||
|         private string _serviceDiscoveryAddress; | ||||
|         private string _downstreamScheme; | ||||
|         private string _downstreamHost; | ||||
|         private int _dsPort; | ||||
|  | ||||
|         public ReRouteBuilder() | ||||
|         { | ||||
| @@ -72,9 +74,9 @@ namespace Ocelot.Configuration.Builder | ||||
|             return this; | ||||
|         } | ||||
|  | ||||
|         public ReRouteBuilder WithDownstreamTemplate(string input) | ||||
|         public ReRouteBuilder WithDownstreamPathTemplate(string input) | ||||
|         { | ||||
|             _downstreamTemplate = input; | ||||
|             _downstreamPathTemplate = input; | ||||
|             return this; | ||||
|         } | ||||
|  | ||||
| @@ -184,11 +186,17 @@ namespace Ocelot.Configuration.Builder | ||||
|             return this; | ||||
|         } | ||||
|  | ||||
|         public ReRouteBuilder WithDownstreamPort(int port) | ||||
|         { | ||||
|             _dsPort = port; | ||||
|             return this; | ||||
|         } | ||||
|  | ||||
|         public ReRoute Build() | ||||
|         { | ||||
|             Func<string> downstreamHostFunc = () => { return _downstreamHost; }; | ||||
|             Func<HostAndPort> downstreamHostFunc = () => new HostAndPort(_downstreamHost, _dsPort); | ||||
|  | ||||
|             return new ReRoute(_downstreamTemplate, _upstreamTemplate, _upstreamHttpMethod, _upstreamTemplatePattern,  | ||||
|             return new ReRoute(new DownstreamPathTemplate(_downstreamPathTemplate), _upstreamTemplate, _upstreamHttpMethod, _upstreamTemplatePattern,  | ||||
|                 _isAuthenticated, new AuthenticationOptions(_authenticationProvider, _authenticationProviderUrl, _scopeName,  | ||||
|                 _requireHttps, _additionalScopes, _scopeSecret), _configHeaderExtractorProperties, _claimToClaims, _routeClaimRequirement,  | ||||
|                 _isAuthorised, _claimToQueries, _requestIdHeaderKey, _isCached, _fileCacheOptions, _serviceName,  | ||||
|   | ||||
| @@ -8,6 +8,7 @@ using Ocelot.Configuration.Parser; | ||||
| using Ocelot.Configuration.Validator; | ||||
| using Ocelot.Responses; | ||||
| using Ocelot.Utilities; | ||||
| using Ocelot.Values; | ||||
|  | ||||
| namespace Ocelot.Configuration.Creator | ||||
| { | ||||
| @@ -96,7 +97,7 @@ namespace Ocelot.Configuration.Creator | ||||
|                 && !string.IsNullOrEmpty(globalConfiguration?.ServiceDiscoveryProvider?.Provider); | ||||
|  | ||||
|  | ||||
|             Func<string> downstreamHostFunc = () => { return reRoute.DownstreamHost; }; | ||||
|             Func<HostAndPort> downstreamHostAndPortFunc = () => new HostAndPort(reRoute.DownstreamHost.Trim('/'), reRoute.DownstreamPort); | ||||
|  | ||||
|             if (isAuthenticated) | ||||
|             { | ||||
| @@ -109,22 +110,22 @@ namespace Ocelot.Configuration.Creator | ||||
|                 var claimsToClaims = GetAddThingsToRequest(reRoute.AddClaimsToRequest); | ||||
|                 var claimsToQueries = GetAddThingsToRequest(reRoute.AddQueriesToRequest); | ||||
|  | ||||
|                 return new ReRoute(reRoute.DownstreamTemplate, reRoute.UpstreamTemplate, | ||||
|                 return new ReRoute(new DownstreamPathTemplate(reRoute.DownstreamPathTemplate), reRoute.UpstreamTemplate, | ||||
|                     reRoute.UpstreamHttpMethod, upstreamTemplate, isAuthenticated, | ||||
|                     authOptionsForRoute, claimsToHeaders, claimsToClaims, | ||||
|                     reRoute.RouteClaimsRequirement, isAuthorised, claimsToQueries, | ||||
|                     requestIdKey, isCached, new CacheOptions(reRoute.FileCacheOptions.TtlSeconds), | ||||
|                     reRoute.ServiceName, useServiceDiscovery, globalConfiguration?.ServiceDiscoveryProvider?.Provider, | ||||
|                     globalConfiguration?.ServiceDiscoveryProvider?.Address, downstreamHostFunc, reRoute.DownstreamScheme); | ||||
|                     globalConfiguration?.ServiceDiscoveryProvider?.Address, downstreamHostAndPortFunc, reRoute.DownstreamScheme); | ||||
|             } | ||||
|  | ||||
|             return new ReRoute(reRoute.DownstreamTemplate, reRoute.UpstreamTemplate,  | ||||
|             return new ReRoute(new DownstreamPathTemplate(reRoute.DownstreamPathTemplate), reRoute.UpstreamTemplate,  | ||||
|                 reRoute.UpstreamHttpMethod, upstreamTemplate, isAuthenticated,  | ||||
|                 null, new List<ClaimToThing>(), new List<ClaimToThing>(),  | ||||
|                 reRoute.RouteClaimsRequirement, isAuthorised, new List<ClaimToThing>(), | ||||
|                     requestIdKey, isCached, new CacheOptions(reRoute.FileCacheOptions.TtlSeconds), | ||||
|                     reRoute.ServiceName, useServiceDiscovery, globalConfiguration?.ServiceDiscoveryProvider?.Provider, | ||||
|                     globalConfiguration?.ServiceDiscoveryProvider?.Address, downstreamHostFunc, reRoute.DownstreamScheme); | ||||
|                     globalConfiguration?.ServiceDiscoveryProvider?.Address, downstreamHostAndPortFunc, reRoute.DownstreamScheme); | ||||
|         } | ||||
|  | ||||
|         private string BuildUpstreamTemplate(FileReRoute reRoute) | ||||
|   | ||||
| @@ -14,7 +14,7 @@ namespace Ocelot.Configuration.File | ||||
|             FileCacheOptions = new FileCacheOptions(); | ||||
|         } | ||||
|  | ||||
|         public string DownstreamTemplate { get; set; } | ||||
|         public string DownstreamPathTemplate { get; set; } | ||||
|         public string UpstreamTemplate { get; set; } | ||||
|         public string UpstreamHttpMethod { get; set; } | ||||
|         public FileAuthenticationOptions AuthenticationOptions { get; set; } | ||||
| @@ -28,5 +28,6 @@ namespace Ocelot.Configuration.File | ||||
|         public string ServiceName { get; set; } | ||||
|         public string DownstreamScheme {get;set;} | ||||
|         public string DownstreamHost {get;set;} | ||||
|         public int DownstreamPort { get; set; } | ||||
|     } | ||||
| } | ||||
| @@ -1,17 +1,18 @@ | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
| using Ocelot.Values; | ||||
|  | ||||
| namespace Ocelot.Configuration | ||||
| { | ||||
|     public class ReRoute | ||||
|     { | ||||
|         public ReRoute(string downstreamTemplate, string upstreamTemplate, string upstreamHttpMethod, string upstreamTemplatePattern,  | ||||
|         public ReRoute(DownstreamPathTemplate downstreamPathTemplate, string upstreamTemplate, string upstreamHttpMethod, string upstreamTemplatePattern,  | ||||
|             bool isAuthenticated, AuthenticationOptions authenticationOptions, List<ClaimToThing> configurationHeaderExtractorProperties,  | ||||
|             List<ClaimToThing> claimsToClaims, Dictionary<string, string> routeClaimsRequirement, bool isAuthorised, List<ClaimToThing> claimsToQueries,  | ||||
|             string requestIdKey, bool isCached, CacheOptions fileCacheOptions, string serviceName, bool useServiceDiscovery, | ||||
|             string serviceDiscoveryProvider, string serviceDiscoveryAddress, Func<string> downstreamHost, string downstreamScheme) | ||||
|             string serviceDiscoveryProvider, string serviceDiscoveryAddress, Func<HostAndPort> downstreamHostAndPort, string downstreamScheme) | ||||
|         { | ||||
|             DownstreamTemplate = downstreamTemplate; | ||||
|             DownstreamPathTemplate = downstreamPathTemplate; | ||||
|             UpstreamTemplate = upstreamTemplate; | ||||
|             UpstreamHttpMethod = upstreamHttpMethod; | ||||
|             UpstreamTemplatePattern = upstreamTemplatePattern; | ||||
| @@ -32,11 +33,11 @@ namespace Ocelot.Configuration | ||||
|                 UseServiceDiscovery = useServiceDiscovery; | ||||
|                 ServiceDiscoveryProvider = serviceDiscoveryProvider; | ||||
|                 ServiceDiscoveryAddress = serviceDiscoveryAddress; | ||||
|                 DownstreamHost = downstreamHost; | ||||
|                 DownstreamHostAndPort = downstreamHostAndPort; | ||||
|                 DownstreamScheme = downstreamScheme; | ||||
|         } | ||||
|  | ||||
|         public string DownstreamTemplate { get; private set; } | ||||
|         public DownstreamPathTemplate DownstreamPathTemplate { get; private set; } | ||||
|         public string UpstreamTemplate { get; private set; } | ||||
|         public string UpstreamTemplatePattern { get; private set; } | ||||
|         public string UpstreamHttpMethod { get; private set; } | ||||
| @@ -54,7 +55,7 @@ namespace Ocelot.Configuration | ||||
|         public bool UseServiceDiscovery { get; private set;} | ||||
|         public string ServiceDiscoveryProvider { get; private set;} | ||||
|         public string ServiceDiscoveryAddress { get; private set;} | ||||
|         public Func<string> DownstreamHost {get;private set;} | ||||
|         public Func<HostAndPort> DownstreamHostAndPort {get;private set;} | ||||
|         public string DownstreamScheme {get;private set;} | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,11 @@ | ||||
| using Ocelot.Errors; | ||||
|  | ||||
| namespace Ocelot.Configuration.Validator | ||||
| { | ||||
|     public class DownstreamPathTemplateAlreadyUsedError : Error | ||||
|     { | ||||
|         public DownstreamPathTemplateAlreadyUsedError(string message) : base(message, OcelotErrorCode.DownstreampathTemplateAlreadyUsedError) | ||||
|         { | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,12 @@ | ||||
| using Ocelot.Errors; | ||||
|  | ||||
| namespace Ocelot.Configuration.Validator | ||||
| { | ||||
|     public class DownstreamPathTemplateContainsSchemeError : Error | ||||
|     { | ||||
|         public DownstreamPathTemplateContainsSchemeError(string message)  | ||||
|             : base(message, OcelotErrorCode.DownstreamPathTemplateContainsSchemeError) | ||||
|         { | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -1,11 +0,0 @@ | ||||
| using Ocelot.Errors; | ||||
|  | ||||
| namespace Ocelot.Configuration.Validator | ||||
| { | ||||
|     public class DownstreamTemplateAlreadyUsedError : Error | ||||
|     { | ||||
|         public DownstreamTemplateAlreadyUsedError(string message) : base(message, OcelotErrorCode.DownstreamTemplateAlreadyUsedError) | ||||
|         { | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -1,12 +0,0 @@ | ||||
| using Ocelot.Errors; | ||||
|  | ||||
| namespace Ocelot.Configuration.Validator | ||||
| { | ||||
|     public class DownstreamTemplateContainsHostError : Error | ||||
|     { | ||||
|         public DownstreamTemplateContainsHostError(string message)  | ||||
|             : base(message, OcelotErrorCode.DownstreamTemplateContainsHostError) | ||||
|         { | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -1,12 +0,0 @@ | ||||
| using Ocelot.Errors; | ||||
|  | ||||
| namespace Ocelot.Configuration.Validator | ||||
| { | ||||
|     public class DownstreamTemplateContainsSchemeError : Error | ||||
|     { | ||||
|         public DownstreamTemplateContainsSchemeError(string message)  | ||||
|             : base(message, OcelotErrorCode.DownstreamTemplateContainsSchemeError) | ||||
|         { | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -26,7 +26,7 @@ namespace Ocelot.Configuration.Validator | ||||
|                 return new OkResponse<ConfigurationValidationResult>(result); | ||||
|             } | ||||
|  | ||||
|             result = CheckForReRoutesContainingDownstreamScheme(configuration); | ||||
|             result = CheckForReRoutesContainingDownstreamSchemeInDownstreamPathTemplate(configuration); | ||||
|  | ||||
|             if (result.IsError) | ||||
|             { | ||||
| @@ -70,25 +70,25 @@ namespace Ocelot.Configuration.Validator | ||||
|             return Enum.TryParse(provider, true, out supportedProvider); | ||||
|         } | ||||
|  | ||||
|         private ConfigurationValidationResult CheckForReRoutesContainingDownstreamScheme(FileConfiguration configuration) | ||||
|         private ConfigurationValidationResult CheckForReRoutesContainingDownstreamSchemeInDownstreamPathTemplate(FileConfiguration configuration) | ||||
|         {    | ||||
|             var errors = new List<Error>(); | ||||
|  | ||||
|             foreach(var reRoute in configuration.ReRoutes) | ||||
|             { | ||||
|                 if(reRoute.DownstreamTemplate.Contains("https://") | ||||
|                 || reRoute.DownstreamTemplate.Contains("http://")) | ||||
|                 if(reRoute.DownstreamPathTemplate.Contains("https://") | ||||
|                 || reRoute.DownstreamPathTemplate.Contains("http://")) | ||||
|                 { | ||||
|                     errors.Add(new DownstreamTemplateContainsSchemeError($"{reRoute.DownstreamTemplate} contains scheme")); | ||||
|                     errors.Add(new DownstreamPathTemplateContainsSchemeError($"{reRoute.DownstreamPathTemplate} contains scheme")); | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             if(errors.Any()) | ||||
|             { | ||||
|                 return new ConfigurationValidationResult(false, errors); | ||||
|                 return new ConfigurationValidationResult(true, errors); | ||||
|             } | ||||
|  | ||||
|             return new ConfigurationValidationResult(true, errors); | ||||
|             return new ConfigurationValidationResult(false, errors); | ||||
|         } | ||||
|  | ||||
|         private ConfigurationValidationResult CheckForDupliateReRoutes(FileConfiguration configuration) | ||||
| @@ -105,7 +105,7 @@ namespace Ocelot.Configuration.Validator | ||||
|                                .Where(x => x.Skip(1).Any()); | ||||
|  | ||||
|             var errors = dupes | ||||
|                 .Select(d => new DownstreamTemplateAlreadyUsedError(string.Format("Duplicate DownstreamTemplate: {0}", d.Key.UpstreamTemplate))) | ||||
|                 .Select(d => new DownstreamPathTemplateAlreadyUsedError(string.Format("Duplicate DownstreamPath: {0}", d.Key.UpstreamTemplate))) | ||||
|                 .Cast<Error>() | ||||
|                 .ToList(); | ||||
|  | ||||
|   | ||||
| @@ -18,6 +18,7 @@ using Ocelot.Configuration.Repository; | ||||
| using Ocelot.Configuration.Validator; | ||||
| using Ocelot.DownstreamRouteFinder.Finder; | ||||
| using Ocelot.DownstreamRouteFinder.UrlMatcher; | ||||
| using Ocelot.DownstreamUrlCreator; | ||||
| using Ocelot.DownstreamUrlCreator.UrlTemplateReplacer; | ||||
| using Ocelot.Headers; | ||||
| using Ocelot.Infrastructure.Claims.Parser; | ||||
| @@ -59,6 +60,7 @@ namespace Ocelot.DependencyInjection | ||||
|             services.AddMvcCore().AddJsonFormatters(); | ||||
|             services.AddLogging(); | ||||
|             services.AddSingleton<IOcelotLoggerFactory, AspDotNetLoggerFactory>(); | ||||
|             services.AddSingleton<IUrlBuilder, UrlBuilder>(); | ||||
|             services.AddSingleton<IRemoveOutputHeaders, RemoveOutputHeaders>(); | ||||
|             services.AddSingleton<IOcelotConfigurationProvider, OcelotConfigurationProvider>(); | ||||
|             services.AddSingleton<IClaimToThingConfigurationParser, ClaimToThingConfigurationParser>(); | ||||
| @@ -69,7 +71,7 @@ namespace Ocelot.DependencyInjection | ||||
|             services.AddSingleton<IClaimsParser, ClaimsParser>(); | ||||
|             services.AddSingleton<IUrlPathToUrlTemplateMatcher, RegExUrlMatcher>(); | ||||
|             services.AddSingleton<IUrlPathPlaceholderNameAndValueFinder, UrlPathPlaceholderNameAndValueFinder>(); | ||||
|             services.AddSingleton<IDownstreamUrlPathPlaceholderReplacer, DownstreamUrlPathPlaceholderReplacer>(); | ||||
|             services.AddSingleton<IDownstreamPathPlaceholderReplacer, DownstreamTemplatePathPlaceholderReplacer>(); | ||||
|             services.AddSingleton<IDownstreamRouteFinder, DownstreamRouteFinder.Finder.DownstreamRouteFinder>(); | ||||
|             services.AddSingleton<IHttpRequester, HttpClientHttpRequester>(); | ||||
|             services.AddSingleton<IHttpResponder, HttpContextResponder>(); | ||||
|   | ||||
| @@ -44,7 +44,7 @@ namespace Ocelot.DownstreamRouteFinder.Middleware | ||||
|                 return; | ||||
|             } | ||||
|  | ||||
|             _logger.LogDebug("downstream template is {downstreamRoute.Data.ReRoute.DownstreamTemplate}", downstreamRoute.Data.ReRoute.DownstreamTemplate); | ||||
|             _logger.LogDebug("downstream template is {downstreamRoute.Data.ReRoute.DownstreamPath}", downstreamRoute.Data.ReRoute.DownstreamPathTemplate); | ||||
|  | ||||
|             SetDownstreamRouteForThisRequest(downstreamRoute.Data); | ||||
|  | ||||
|   | ||||
| @@ -0,0 +1,12 @@ | ||||
| using Ocelot.Errors; | ||||
|  | ||||
| namespace Ocelot.DownstreamUrlCreator | ||||
| { | ||||
|     public class DownstreamHostNullOrEmptyError : Error | ||||
|     { | ||||
|         public DownstreamHostNullOrEmptyError() | ||||
|             : base("downstream host was null or empty", OcelotErrorCode.DownstreamHostNullOrEmptyError) | ||||
|         { | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,12 @@ | ||||
| using Ocelot.Errors; | ||||
|  | ||||
| namespace Ocelot.DownstreamUrlCreator | ||||
| { | ||||
|     public class DownstreamPathNullOrEmptyError : Error | ||||
|     { | ||||
|         public DownstreamPathNullOrEmptyError()  | ||||
|             : base("downstream path was null or empty", OcelotErrorCode.DownstreamPathNullOrEmptyError) | ||||
|         { | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,12 @@ | ||||
| using Ocelot.Errors; | ||||
|  | ||||
| namespace Ocelot.DownstreamUrlCreator | ||||
| { | ||||
|     public class DownstreamSchemeNullOrEmptyError : Error | ||||
|     { | ||||
|         public DownstreamSchemeNullOrEmptyError() | ||||
|             : base("downstream scheme was null or empty", OcelotErrorCode.DownstreamSchemeNullOrEmptyError) | ||||
|         { | ||||
|         } | ||||
|     } | ||||
| } | ||||
							
								
								
									
										12
									
								
								src/Ocelot/DownstreamUrlCreator/IUrlBuilder.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								src/Ocelot/DownstreamUrlCreator/IUrlBuilder.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,12 @@ | ||||
| using Ocelot.Configuration; | ||||
| using Ocelot.DownstreamUrlCreator.UrlTemplateReplacer; | ||||
| using Ocelot.Responses; | ||||
| using Ocelot.Values; | ||||
|  | ||||
| namespace Ocelot.DownstreamUrlCreator | ||||
| { | ||||
|     public interface IUrlBuilder | ||||
|     { | ||||
|         Response<DownstreamUrl> Build(string downstreamPath, string downstreamScheme, HostAndPort downstreamHostAndPort); | ||||
|     } | ||||
| } | ||||
| @@ -1,6 +1,7 @@ | ||||
| using System.Threading.Tasks; | ||||
| using Microsoft.AspNetCore.Http; | ||||
| using Microsoft.Extensions.Logging; | ||||
| using Ocelot.Configuration; | ||||
| using Ocelot.DownstreamUrlCreator.UrlTemplateReplacer; | ||||
| using Ocelot.Infrastructure.RequestData; | ||||
| using Ocelot.Logging; | ||||
| @@ -11,17 +12,20 @@ namespace Ocelot.DownstreamUrlCreator.Middleware | ||||
|     public class DownstreamUrlCreatorMiddleware : OcelotMiddleware | ||||
|     { | ||||
|         private readonly RequestDelegate _next; | ||||
|         private readonly IDownstreamUrlPathPlaceholderReplacer _urlReplacer; | ||||
|         private readonly IDownstreamPathPlaceholderReplacer _replacer; | ||||
|         private readonly IOcelotLogger _logger; | ||||
|         private readonly IUrlBuilder _urlBuilder; | ||||
|  | ||||
|         public DownstreamUrlCreatorMiddleware(RequestDelegate next, | ||||
|             IOcelotLoggerFactory loggerFactory, | ||||
|             IDownstreamUrlPathPlaceholderReplacer urlReplacer, | ||||
|             IRequestScopedDataRepository requestScopedDataRepository) | ||||
|             IDownstreamPathPlaceholderReplacer replacer, | ||||
|             IRequestScopedDataRepository requestScopedDataRepository,  | ||||
|             IUrlBuilder urlBuilder) | ||||
|             :base(requestScopedDataRepository) | ||||
|         { | ||||
|             _next = next; | ||||
|             _urlReplacer = urlReplacer; | ||||
|             _replacer = replacer; | ||||
|             _urlBuilder = urlBuilder; | ||||
|             _logger = loggerFactory.CreateLogger<DownstreamUrlCreatorMiddleware>(); | ||||
|         } | ||||
|  | ||||
| @@ -29,19 +33,34 @@ namespace Ocelot.DownstreamUrlCreator.Middleware | ||||
|         { | ||||
|             _logger.LogDebug("started calling downstream url creator middleware"); | ||||
|  | ||||
|             var downstreamUrl = _urlReplacer.Replace(DownstreamRoute.ReRoute.DownstreamTemplate, DownstreamRoute.TemplatePlaceholderNameAndValues); | ||||
|             var dsPath = _replacer | ||||
|                 .Replace(DownstreamRoute.ReRoute.DownstreamPathTemplate, DownstreamRoute.TemplatePlaceholderNameAndValues); | ||||
|  | ||||
|             if (downstreamUrl.IsError) | ||||
|             if (dsPath.IsError) | ||||
|             { | ||||
|                 _logger.LogDebug("IDownstreamUrlPathPlaceholderReplacer returned an error, setting pipeline error"); | ||||
|                 _logger.LogDebug("IDownstreamPathPlaceholderReplacer returned an error, setting pipeline error"); | ||||
|  | ||||
|                 SetPipelineError(downstreamUrl.Errors); | ||||
|                 SetPipelineError(dsPath.Errors); | ||||
|                 return; | ||||
|             } | ||||
|  | ||||
|             _logger.LogDebug("downstream url is {downstreamUrl.Data.Value}", downstreamUrl.Data.Value); | ||||
|             var dsScheme = DownstreamRoute.ReRoute.DownstreamScheme; | ||||
|  | ||||
|             SetDownstreamUrlForThisRequest(downstreamUrl.Data.Value); | ||||
|             var dsHostAndPort = DownstreamRoute.ReRoute.DownstreamHostAndPort(); | ||||
|  | ||||
|             var dsUrl = _urlBuilder.Build(dsPath.Data.Value, dsScheme, dsHostAndPort); | ||||
|  | ||||
|             if (dsUrl.IsError) | ||||
|             { | ||||
|                 _logger.LogDebug("IUrlBuilder returned an error, setting pipeline error"); | ||||
|  | ||||
|                 SetPipelineError(dsUrl.Errors); | ||||
|                 return; | ||||
|             } | ||||
|  | ||||
|             _logger.LogDebug("downstream url is {downstreamUrl.Data.Value}", dsUrl.Data.Value); | ||||
|  | ||||
|             SetDownstreamUrlForThisRequest(dsUrl.Data.Value); | ||||
|  | ||||
|             _logger.LogDebug("calling next middleware"); | ||||
|  | ||||
|   | ||||
							
								
								
									
										47
									
								
								src/Ocelot/DownstreamUrlCreator/UrlBuilder.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										47
									
								
								src/Ocelot/DownstreamUrlCreator/UrlBuilder.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,47 @@ | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
| using Ocelot.Configuration; | ||||
| using Ocelot.DownstreamUrlCreator.UrlTemplateReplacer; | ||||
| using Ocelot.Errors; | ||||
| using Ocelot.Responses; | ||||
| using Ocelot.Values; | ||||
|  | ||||
| namespace Ocelot.DownstreamUrlCreator | ||||
| { | ||||
|     public class UrlBuilder : IUrlBuilder | ||||
|     { | ||||
|         public Response<DownstreamUrl> Build(string downstreamPath, string downstreamScheme, HostAndPort downstreamHostAndPort) | ||||
|         { | ||||
|             if (string.IsNullOrEmpty(downstreamPath)) | ||||
|             { | ||||
|                 return new ErrorResponse<DownstreamUrl>(new List<Error> {new DownstreamPathNullOrEmptyError()}); | ||||
|             } | ||||
|  | ||||
|             if (string.IsNullOrEmpty(downstreamScheme)) | ||||
|             { | ||||
|                 return new ErrorResponse<DownstreamUrl>(new List<Error> { new DownstreamSchemeNullOrEmptyError() }); | ||||
|             } | ||||
|  | ||||
|             if (string.IsNullOrEmpty(downstreamHostAndPort.DownstreamHost)) | ||||
|             { | ||||
|                 return new ErrorResponse<DownstreamUrl>(new List<Error> { new DownstreamHostNullOrEmptyError() }); | ||||
|             } | ||||
|  | ||||
|             var builder = new UriBuilder | ||||
|             { | ||||
|                 Host = downstreamHostAndPort.DownstreamHost, | ||||
|                 Path = downstreamPath, | ||||
|                 Scheme = downstreamScheme | ||||
|             }; | ||||
|  | ||||
|             if (downstreamHostAndPort.DownstreamPort > 0) | ||||
|             { | ||||
|                 builder.Port = downstreamHostAndPort.DownstreamPort; | ||||
|             } | ||||
|              | ||||
|             var url = builder.Uri.ToString(); | ||||
|  | ||||
|             return new OkResponse<DownstreamUrl>(new DownstreamUrl(url)); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -1,25 +1,25 @@ | ||||
| using System.Collections.Generic; | ||||
| using System.Text; | ||||
| using Ocelot.DownstreamRouteFinder; | ||||
| using Ocelot.DownstreamRouteFinder.UrlMatcher; | ||||
| using Ocelot.Responses; | ||||
| using Ocelot.Values; | ||||
|  | ||||
| namespace Ocelot.DownstreamUrlCreator.UrlTemplateReplacer | ||||
| { | ||||
|     public class DownstreamUrlPathPlaceholderReplacer : IDownstreamUrlPathPlaceholderReplacer | ||||
|     public class DownstreamTemplatePathPlaceholderReplacer : IDownstreamPathPlaceholderReplacer | ||||
|     { | ||||
|         public Response<DownstreamUrl> Replace(string downstreamTemplate, List<UrlPathPlaceholderNameAndValue> urlPathPlaceholderNameAndValues) | ||||
|         public Response<DownstreamPath> Replace(DownstreamPathTemplate downstreamPathTemplate, List<UrlPathPlaceholderNameAndValue> urlPathPlaceholderNameAndValues) | ||||
|         { | ||||
|             var upstreamUrl = new StringBuilder(); | ||||
|             var downstreamPath = new StringBuilder(); | ||||
|  | ||||
|             upstreamUrl.Append(downstreamTemplate); | ||||
|             downstreamPath.Append(downstreamPathTemplate.Value); | ||||
|  | ||||
|             foreach (var placeholderVariableAndValue in urlPathPlaceholderNameAndValues) | ||||
|             { | ||||
|                 upstreamUrl.Replace(placeholderVariableAndValue.TemplateVariableName, placeholderVariableAndValue.TemplateVariableValue); | ||||
|                 downstreamPath.Replace(placeholderVariableAndValue.TemplateVariableName, placeholderVariableAndValue.TemplateVariableValue); | ||||
|             } | ||||
|  | ||||
|             return new OkResponse<DownstreamUrl>(new DownstreamUrl(upstreamUrl.ToString())); | ||||
|             return new OkResponse<DownstreamPath>(new DownstreamPath(downstreamPath.ToString())); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -1,11 +1,12 @@ | ||||
| using System.Collections.Generic; | ||||
| using Ocelot.DownstreamRouteFinder.UrlMatcher; | ||||
| using Ocelot.Responses; | ||||
| using Ocelot.Values; | ||||
|  | ||||
| namespace Ocelot.DownstreamUrlCreator.UrlTemplateReplacer | ||||
| { | ||||
|     public interface IDownstreamUrlPathPlaceholderReplacer | ||||
|     public interface IDownstreamPathPlaceholderReplacer | ||||
|     { | ||||
|         Response<DownstreamUrl> Replace(string downstreamTemplate, List<UrlPathPlaceholderNameAndValue> urlPathPlaceholderNameAndValues);    | ||||
|         Response<DownstreamPath> Replace(DownstreamPathTemplate downstreamPathTemplate, List<UrlPathPlaceholderNameAndValue> urlPathPlaceholderNameAndValues);    | ||||
|     } | ||||
| } | ||||
| @@ -4,7 +4,7 @@ | ||||
|     { | ||||
|         UnauthenticatedError,  | ||||
|         UnknownError, | ||||
|         DownstreamTemplateAlreadyUsedError, | ||||
|         DownstreampathTemplateAlreadyUsedError, | ||||
|         UnableToFindDownstreamRouteError, | ||||
|         CannotAddDataError, | ||||
|         CannotFindDataError, | ||||
| @@ -18,7 +18,9 @@ | ||||
|         UnauthorizedError, | ||||
|         ClaimValueNotAuthorisedError, | ||||
|         UserDoesNotHaveClaimError, | ||||
|         DownstreamTemplateContainsSchemeError, | ||||
|         DownstreamTemplateContainsHostError | ||||
|         DownstreamPathTemplateContainsSchemeError, | ||||
|         DownstreamPathNullOrEmptyError, | ||||
|         DownstreamSchemeNullOrEmptyError, | ||||
|         DownstreamHostNullOrEmptyError | ||||
|     } | ||||
| } | ||||
|   | ||||
							
								
								
									
										12
									
								
								src/Ocelot/Values/DownstreamPath.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								src/Ocelot/Values/DownstreamPath.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,12 @@ | ||||
| namespace Ocelot.Values | ||||
| { | ||||
|     public class DownstreamPath | ||||
|     { | ||||
|         public DownstreamPath(string value) | ||||
|         { | ||||
|             Value = value; | ||||
|         } | ||||
|  | ||||
|         public string Value { get; private set; } | ||||
|     } | ||||
| } | ||||
							
								
								
									
										12
									
								
								src/Ocelot/Values/DownstreamPathTemplate.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								src/Ocelot/Values/DownstreamPathTemplate.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,12 @@ | ||||
| namespace Ocelot.Values | ||||
| { | ||||
|     public class DownstreamPathTemplate | ||||
|     { | ||||
|         public DownstreamPathTemplate(string value) | ||||
|         { | ||||
|             Value = value; | ||||
|         } | ||||
|  | ||||
|         public string Value { get; private set; } | ||||
|     } | ||||
| } | ||||
| @@ -1,4 +1,4 @@ | ||||
| namespace Ocelot.DownstreamUrlCreator.UrlTemplateReplacer | ||||
| namespace Ocelot.Values | ||||
| { | ||||
|     public class DownstreamUrl | ||||
|     { | ||||
| @@ -9,4 +9,4 @@ | ||||
| 
 | ||||
|         public string Value { get; private set; } | ||||
|     } | ||||
| } | ||||
| } | ||||
							
								
								
									
										14
									
								
								src/Ocelot/Values/HostAndPort.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								src/Ocelot/Values/HostAndPort.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,14 @@ | ||||
| namespace Ocelot.Values | ||||
| { | ||||
|     public class HostAndPort | ||||
|     { | ||||
|         public HostAndPort(string downstreamHost, int downstreamPort) | ||||
|         { | ||||
|             DownstreamHost = downstreamHost; | ||||
|             DownstreamPort = downstreamPort; | ||||
|         } | ||||
|  | ||||
|         public string DownstreamHost { get; private set; } | ||||
|         public int DownstreamPort { get; private set; } | ||||
|     } | ||||
| } | ||||
| @@ -23,7 +23,11 @@ namespace Ocelot.AcceptanceTests | ||||
|         private readonly Steps _steps; | ||||
|         private IWebHost _identityServerBuilder; | ||||
|         private string _identityServerRootUrl = "http://localhost:51888"; | ||||
|         private string _downstreamServiceRootUrl = "http://localhost:51876/"; | ||||
|         private string _downstreamServicePath = "/"; | ||||
|         private string _downstreamServiceHost = "localhost"; | ||||
|         private int _downstreamServicePort = 51876; | ||||
|         private string _downstreamServiceScheme = "http"; | ||||
|         private string _downstreamServiceUrl = "http://localhost:51876"; | ||||
|  | ||||
|         public AuthenticationTests() | ||||
|         { | ||||
| @@ -39,7 +43,10 @@ namespace Ocelot.AcceptanceTests | ||||
|                     { | ||||
|                         new FileReRoute | ||||
|                         { | ||||
|                             DownstreamTemplate = _downstreamServiceRootUrl, | ||||
|                             DownstreamPathTemplate = _downstreamServicePath, | ||||
|                             DownstreamPort = _downstreamServicePort, | ||||
|                             DownstreamHost = _downstreamServiceHost, | ||||
|                             DownstreamScheme = _downstreamServiceScheme, | ||||
|                             UpstreamTemplate = "/", | ||||
|                             UpstreamHttpMethod = "Post", | ||||
|                             AuthenticationOptions = new FileAuthenticationOptions | ||||
| @@ -56,7 +63,7 @@ namespace Ocelot.AcceptanceTests | ||||
|             }; | ||||
|  | ||||
|             this.Given(x => x.GivenThereIsAnIdentityServerOn(_identityServerRootUrl, "api", AccessTokenType.Jwt)) | ||||
|                 .And(x => x.GivenThereIsAServiceRunningOn(_downstreamServiceRootUrl, 201, string.Empty)) | ||||
|                 .And(x => x.GivenThereIsAServiceRunningOn(_downstreamServiceUrl, 201, string.Empty)) | ||||
|                 .And(x => _steps.GivenThereIsAConfiguration(configuration)) | ||||
|                 .And(x => _steps.GivenOcelotIsRunning()) | ||||
|                 .And(x => _steps.GivenThePostHasContent("postContent")) | ||||
| @@ -74,7 +81,10 @@ namespace Ocelot.AcceptanceTests | ||||
|                     { | ||||
|                         new FileReRoute | ||||
|                         { | ||||
|                             DownstreamTemplate = _downstreamServiceRootUrl, | ||||
|                             DownstreamPathTemplate = _downstreamServicePath, | ||||
|                             DownstreamPort = _downstreamServicePort, | ||||
|                             DownstreamHost = _downstreamServiceHost, | ||||
|                             DownstreamScheme = _downstreamServiceScheme, | ||||
|                             UpstreamTemplate = "/", | ||||
|                             UpstreamHttpMethod = "Post", | ||||
|                             AuthenticationOptions = new FileAuthenticationOptions | ||||
| @@ -91,7 +101,7 @@ namespace Ocelot.AcceptanceTests | ||||
|             }; | ||||
|  | ||||
|             this.Given(x => x.GivenThereIsAnIdentityServerOn(_identityServerRootUrl, "api", AccessTokenType.Reference)) | ||||
|                 .And(x => x.GivenThereIsAServiceRunningOn(_downstreamServiceRootUrl, 201, string.Empty)) | ||||
|                 .And(x => x.GivenThereIsAServiceRunningOn(_downstreamServiceUrl, 201, string.Empty)) | ||||
|                 .And(x => _steps.GivenThereIsAConfiguration(configuration)) | ||||
|                 .And(x => _steps.GivenOcelotIsRunning()) | ||||
|                 .And(x => _steps.GivenThePostHasContent("postContent")) | ||||
| @@ -109,7 +119,10 @@ namespace Ocelot.AcceptanceTests | ||||
|                     { | ||||
|                         new FileReRoute | ||||
|                         { | ||||
|                             DownstreamTemplate = _downstreamServiceRootUrl, | ||||
|                             DownstreamPathTemplate = _downstreamServicePath, | ||||
|                             DownstreamPort = _downstreamServicePort, | ||||
|                             DownstreamHost = _downstreamServiceHost, | ||||
|                             DownstreamScheme = _downstreamServiceScheme, | ||||
|                             UpstreamTemplate = "/", | ||||
|                             UpstreamHttpMethod = "Get", | ||||
|                             AuthenticationOptions = new FileAuthenticationOptions | ||||
| @@ -126,7 +139,7 @@ namespace Ocelot.AcceptanceTests | ||||
|             }; | ||||
|  | ||||
|             this.Given(x => x.GivenThereIsAnIdentityServerOn(_identityServerRootUrl, "api", AccessTokenType.Jwt)) | ||||
|                 .And(x => x.GivenThereIsAServiceRunningOn(_downstreamServiceRootUrl, 200, "Hello from Laura")) | ||||
|                 .And(x => x.GivenThereIsAServiceRunningOn(_downstreamServiceUrl, 200, "Hello from Laura")) | ||||
|                 .And(x => _steps.GivenIHaveAToken(_identityServerRootUrl)) | ||||
|                 .And(x => _steps.GivenThereIsAConfiguration(configuration)) | ||||
|                 .And(x => _steps.GivenOcelotIsRunning()) | ||||
| @@ -146,7 +159,10 @@ namespace Ocelot.AcceptanceTests | ||||
|                     { | ||||
|                         new FileReRoute | ||||
|                         { | ||||
|                             DownstreamTemplate = _downstreamServiceRootUrl, | ||||
|                             DownstreamPathTemplate = _downstreamServicePath, | ||||
|                             DownstreamPort = _downstreamServicePort, | ||||
|                             DownstreamHost = _downstreamServiceHost, | ||||
|                             DownstreamScheme = _downstreamServiceScheme, | ||||
|                             UpstreamTemplate = "/", | ||||
|                             UpstreamHttpMethod = "Post", | ||||
|                             AuthenticationOptions = new FileAuthenticationOptions | ||||
| @@ -163,7 +179,7 @@ namespace Ocelot.AcceptanceTests | ||||
|             }; | ||||
|  | ||||
|             this.Given(x => x.GivenThereIsAnIdentityServerOn(_identityServerRootUrl, "api", AccessTokenType.Jwt)) | ||||
|                 .And(x => x.GivenThereIsAServiceRunningOn(_downstreamServiceRootUrl, 201, string.Empty)) | ||||
|                 .And(x => x.GivenThereIsAServiceRunningOn(_downstreamServiceUrl, 201, string.Empty)) | ||||
|                 .And(x => _steps.GivenIHaveAToken(_identityServerRootUrl)) | ||||
|                 .And(x => _steps.GivenThereIsAConfiguration(configuration)) | ||||
|                 .And(x => _steps.GivenOcelotIsRunning()) | ||||
| @@ -183,7 +199,10 @@ namespace Ocelot.AcceptanceTests | ||||
|                     { | ||||
|                         new FileReRoute | ||||
|                         { | ||||
|                             DownstreamTemplate = _downstreamServiceRootUrl, | ||||
|                             DownstreamPathTemplate = _downstreamServicePath, | ||||
|                             DownstreamPort = _downstreamServicePort, | ||||
|                             DownstreamHost = _downstreamServiceHost, | ||||
|                             DownstreamScheme = _downstreamServiceScheme, | ||||
|                             UpstreamTemplate = "/", | ||||
|                             UpstreamHttpMethod = "Post", | ||||
|                             AuthenticationOptions = new FileAuthenticationOptions | ||||
| @@ -200,7 +219,7 @@ namespace Ocelot.AcceptanceTests | ||||
|             }; | ||||
|  | ||||
|             this.Given(x => x.GivenThereIsAnIdentityServerOn(_identityServerRootUrl, "api", AccessTokenType.Reference)) | ||||
|                 .And(x => x.GivenThereIsAServiceRunningOn(_downstreamServiceRootUrl, 201, string.Empty)) | ||||
|                 .And(x => x.GivenThereIsAServiceRunningOn(_downstreamServiceUrl, 201, string.Empty)) | ||||
|                 .And(x => _steps.GivenIHaveAToken(_identityServerRootUrl)) | ||||
|                 .And(x => _steps.GivenThereIsAConfiguration(configuration)) | ||||
|                 .And(x => _steps.GivenOcelotIsRunning()) | ||||
|   | ||||
| @@ -37,7 +37,10 @@ namespace Ocelot.AcceptanceTests | ||||
|                     { | ||||
|                         new FileReRoute | ||||
|                         { | ||||
|                             DownstreamTemplate = "http://localhost:51876/", | ||||
|                             DownstreamPathTemplate = "/", | ||||
|                             DownstreamPort = 51876, | ||||
|                             DownstreamScheme = "http", | ||||
|                             DownstreamHost = "localhost", | ||||
|                             UpstreamTemplate = "/", | ||||
|                             UpstreamHttpMethod = "Get", | ||||
|                             AuthenticationOptions = new FileAuthenticationOptions | ||||
| @@ -91,7 +94,10 @@ namespace Ocelot.AcceptanceTests | ||||
|                     { | ||||
|                         new FileReRoute | ||||
|                         { | ||||
|                             DownstreamTemplate = "http://localhost:51876/", | ||||
|                             DownstreamPathTemplate = "/", | ||||
|                             DownstreamPort = 51876, | ||||
|                             DownstreamScheme = "http", | ||||
|                             DownstreamHost = "localhost", | ||||
|                             UpstreamTemplate = "/", | ||||
|                             UpstreamHttpMethod = "Get", | ||||
|                             AuthenticationOptions = new FileAuthenticationOptions | ||||
|   | ||||
| @@ -31,7 +31,10 @@ namespace Ocelot.AcceptanceTests | ||||
|                     { | ||||
|                         new FileReRoute | ||||
|                         { | ||||
|                             DownstreamTemplate = "http://localhost:51879/", | ||||
|                             DownstreamPathTemplate = "/", | ||||
|                             DownstreamPort = 51879, | ||||
|                             DownstreamScheme = "http", | ||||
|                             DownstreamHost = "localhost", | ||||
|                             UpstreamTemplate = "/", | ||||
|                             UpstreamHttpMethod = "Get", | ||||
|                             FileCacheOptions = new FileCacheOptions | ||||
| @@ -64,7 +67,10 @@ namespace Ocelot.AcceptanceTests | ||||
|                     { | ||||
|                         new FileReRoute | ||||
|                         { | ||||
|                             DownstreamTemplate = "http://localhost:51879/", | ||||
|                             DownstreamPathTemplate = "/", | ||||
|                             DownstreamPort = 51879, | ||||
|                             DownstreamScheme = "http", | ||||
|                             DownstreamHost = "localhost", | ||||
|                             UpstreamTemplate = "/", | ||||
|                             UpstreamHttpMethod = "Get", | ||||
|                             FileCacheOptions = new FileCacheOptions | ||||
|   | ||||
| @@ -30,7 +30,10 @@ namespace Ocelot.AcceptanceTests | ||||
|                     { | ||||
|                         new FileReRoute | ||||
|                         { | ||||
|                             DownstreamTemplate = "http://localhost:51879/api/products/{productId}", | ||||
|                             DownstreamPathTemplate = "/api/products/{productId}", | ||||
|                             DownstreamPort = 51879, | ||||
|                             DownstreamScheme = "http", | ||||
|                             DownstreamHost = "localhost", | ||||
|                             UpstreamTemplate = "/products/{productId}", | ||||
|                             UpstreamHttpMethod = "Get" | ||||
|                         } | ||||
| @@ -54,7 +57,10 @@ namespace Ocelot.AcceptanceTests | ||||
|                     { | ||||
|                         new FileReRoute | ||||
|                         { | ||||
|                             DownstreamTemplate = "http://localhost:51879/api/products/{productId}", | ||||
|                             DownstreamPathTemplate = "/api/products/{productId}", | ||||
|                             DownstreamPort = 51879, | ||||
|                             DownstreamScheme = "http", | ||||
|                             DownstreamHost = "localhost", | ||||
|                             UpstreamTemplate = "/products/{productId}", | ||||
|                             UpstreamHttpMethod = "Get", | ||||
|                             ReRouteIsCaseSensitive = false | ||||
| @@ -79,7 +85,10 @@ namespace Ocelot.AcceptanceTests | ||||
|                     { | ||||
|                         new FileReRoute | ||||
|                         { | ||||
|                             DownstreamTemplate = "http://localhost:51879/api/products/{productId}", | ||||
|                             DownstreamPathTemplate = "/api/products/{productId}", | ||||
|                             DownstreamPort = 51879, | ||||
|                             DownstreamScheme = "http", | ||||
|                             DownstreamHost = "localhost", | ||||
|                             UpstreamTemplate = "/products/{productId}", | ||||
|                             UpstreamHttpMethod = "Get", | ||||
|                             ReRouteIsCaseSensitive = true | ||||
| @@ -104,7 +113,10 @@ namespace Ocelot.AcceptanceTests | ||||
|                     { | ||||
|                         new FileReRoute | ||||
|                         { | ||||
|                             DownstreamTemplate = "http://localhost:51879/api/products/{productId}", | ||||
|                             DownstreamPathTemplate = "/api/products/{productId}", | ||||
|                             DownstreamPort = 51879, | ||||
|                             DownstreamScheme = "http", | ||||
|                             DownstreamHost = "localhost", | ||||
|                             UpstreamTemplate = "/PRODUCTS/{productId}", | ||||
|                             UpstreamHttpMethod = "Get", | ||||
|                             ReRouteIsCaseSensitive = true | ||||
| @@ -129,7 +141,10 @@ namespace Ocelot.AcceptanceTests | ||||
|                     { | ||||
|                         new FileReRoute | ||||
|                         { | ||||
|                             DownstreamTemplate = "http://localhost:51879/api/products/{productId}", | ||||
|                             DownstreamPathTemplate = "/api/products/{productId}", | ||||
|                             DownstreamPort = 51879, | ||||
|                             DownstreamScheme = "http", | ||||
|                             DownstreamHost = "localhost", | ||||
|                             UpstreamTemplate = "/products/{productId}", | ||||
|                             UpstreamHttpMethod = "Get", | ||||
|                             ReRouteIsCaseSensitive = true | ||||
| @@ -154,7 +169,10 @@ namespace Ocelot.AcceptanceTests | ||||
|                     { | ||||
|                         new FileReRoute | ||||
|                         { | ||||
|                             DownstreamTemplate = "http://localhost:51879/api/products/{productId}", | ||||
|                             DownstreamPathTemplate = "/api/products/{productId}", | ||||
|                             DownstreamPort = 51879, | ||||
|                             DownstreamScheme = "http", | ||||
|                             DownstreamHost = "localhost", | ||||
|                             UpstreamTemplate = "/PRODUCTS/{productId}", | ||||
|                             UpstreamHttpMethod = "Get", | ||||
|                             ReRouteIsCaseSensitive = true | ||||
|   | ||||
| @@ -51,7 +51,10 @@ namespace Ocelot.AcceptanceTests | ||||
|                     { | ||||
|                         new FileReRoute | ||||
|                         { | ||||
|                             DownstreamTemplate = "http://localhost:52876/", | ||||
|                             DownstreamPathTemplate = "/", | ||||
|                             DownstreamPort = 52876, | ||||
|                             DownstreamScheme = "http", | ||||
|                             DownstreamHost = "localhost", | ||||
|                             UpstreamTemplate = "/", | ||||
|                             UpstreamHttpMethod = "Get", | ||||
|                             AuthenticationOptions = new FileAuthenticationOptions | ||||
|   | ||||
| @@ -51,7 +51,10 @@ namespace Ocelot.AcceptanceTests | ||||
|                     { | ||||
|                         new FileReRoute | ||||
|                         { | ||||
|                             DownstreamTemplate = "http://localhost:57876/", | ||||
|                             DownstreamPathTemplate = "/", | ||||
|                             DownstreamPort = 57876, | ||||
|                             DownstreamScheme = "http", | ||||
|                             DownstreamHost = "localhost", | ||||
|                             UpstreamTemplate = "/", | ||||
|                             UpstreamHttpMethod = "Get", | ||||
|                             AuthenticationOptions = new FileAuthenticationOptions | ||||
|   | ||||
| @@ -45,7 +45,10 @@ namespace Ocelot.AcceptanceTests | ||||
|                     { | ||||
|                         new FileReRoute | ||||
|                         { | ||||
|                             DownstreamTemplate = "http://localhost:41879/", | ||||
|                             DownstreamPathTemplate = "/", | ||||
|                             DownstreamPort = 41879, | ||||
|                             DownstreamScheme = "http", | ||||
|                             DownstreamHost = "localhost", | ||||
|                             UpstreamTemplate = "/", | ||||
|                             UpstreamHttpMethod = "Get", | ||||
|                         } | ||||
| @@ -79,7 +82,10 @@ namespace Ocelot.AcceptanceTests | ||||
|                     { | ||||
|                         new FileReRoute | ||||
|                         { | ||||
|                             DownstreamTemplate = "http://localhost:41879/", | ||||
|                             DownstreamPathTemplate = "/", | ||||
|                             DownstreamPort = 41879, | ||||
|                             DownstreamScheme = "http", | ||||
|                             DownstreamHost = "localhost", | ||||
|                             UpstreamTemplate = "/", | ||||
|                             UpstreamHttpMethod = "Get", | ||||
|                         } | ||||
| @@ -113,7 +119,10 @@ namespace Ocelot.AcceptanceTests | ||||
|                     { | ||||
|                         new FileReRoute | ||||
|                         { | ||||
|                             DownstreamTemplate = "http://localhost:41879/", | ||||
|                             DownstreamPathTemplate = "41879/", | ||||
|                             DownstreamPort = 41879, | ||||
|                             DownstreamScheme = "http", | ||||
|                             DownstreamHost = "localhost", | ||||
|                             UpstreamTemplate = "/", | ||||
|                             UpstreamHttpMethod = "Get", | ||||
|                         } | ||||
| @@ -147,7 +156,10 @@ namespace Ocelot.AcceptanceTests | ||||
|                     { | ||||
|                         new FileReRoute | ||||
|                         { | ||||
|                             DownstreamTemplate = "http://localhost:41879/", | ||||
|                             DownstreamPathTemplate = "/", | ||||
|                             DownstreamPort = 41879, | ||||
|                             DownstreamScheme = "http", | ||||
|                             DownstreamHost = "localhost", | ||||
|                             UpstreamTemplate = "/", | ||||
|                             UpstreamHttpMethod = "Get", | ||||
|                         } | ||||
| @@ -181,7 +193,10 @@ namespace Ocelot.AcceptanceTests | ||||
|                     { | ||||
|                         new FileReRoute | ||||
|                         { | ||||
|                             DownstreamTemplate = "http://localhost:41879/", | ||||
|                             DownstreamPathTemplate = "/", | ||||
|                             DownstreamPort = 41879, | ||||
|                             DownstreamScheme = "http", | ||||
|                             DownstreamHost = "localhost", | ||||
|                             UpstreamTemplate = "/", | ||||
|                             UpstreamHttpMethod = "Get", | ||||
|                         } | ||||
| @@ -215,7 +230,10 @@ namespace Ocelot.AcceptanceTests | ||||
|                     { | ||||
|                         new FileReRoute | ||||
|                         { | ||||
|                             DownstreamTemplate = "http://localhost:41879/", | ||||
|                             DownstreamPathTemplate = "/", | ||||
|                             DownstreamPort = 41879, | ||||
|                             DownstreamScheme = "http", | ||||
|                             DownstreamHost = "localhost", | ||||
|                             UpstreamTemplate = "/", | ||||
|                             UpstreamHttpMethod = "Get", | ||||
|                         } | ||||
|   | ||||
| @@ -33,7 +33,10 @@ namespace Ocelot.AcceptanceTests | ||||
|                     { | ||||
|                         new FileReRoute | ||||
|                         { | ||||
|                             DownstreamTemplate = "http://localhost:51879/", | ||||
|                             DownstreamPathTemplate = "/", | ||||
|                             DownstreamPort = 51879, | ||||
|                             DownstreamScheme = "http", | ||||
|                             DownstreamHost = "localhost", | ||||
|                             UpstreamTemplate = "/", | ||||
|                             UpstreamHttpMethod = "Get", | ||||
|                             RequestIdKey = _steps.RequestIdKey | ||||
| @@ -58,7 +61,10 @@ namespace Ocelot.AcceptanceTests | ||||
|                     { | ||||
|                         new FileReRoute | ||||
|                         { | ||||
|                             DownstreamTemplate = "http://localhost:51879/", | ||||
|                             DownstreamPathTemplate = "/", | ||||
|                             DownstreamPort = 51879, | ||||
|                             DownstreamScheme = "http", | ||||
|                             DownstreamHost = "localhost", | ||||
|                             UpstreamTemplate = "/", | ||||
|                             UpstreamHttpMethod = "Get", | ||||
|                             RequestIdKey = _steps.RequestIdKey | ||||
| @@ -85,7 +91,10 @@ namespace Ocelot.AcceptanceTests | ||||
|                     { | ||||
|                         new FileReRoute | ||||
|                         { | ||||
|                             DownstreamTemplate = "http://localhost:51879/", | ||||
|                             DownstreamPathTemplate = "/", | ||||
|                             DownstreamPort = 51879, | ||||
|                             DownstreamScheme = "http", | ||||
|                             DownstreamHost = "localhost", | ||||
|                             UpstreamTemplate = "/", | ||||
|                             UpstreamHttpMethod = "Get", | ||||
|                         } | ||||
|   | ||||
| @@ -29,7 +29,7 @@ namespace Ocelot.AcceptanceTests | ||||
|                     { | ||||
|                         new FileReRoute | ||||
|                         { | ||||
|                             DownstreamTemplate = "http://localhost:53876/", | ||||
|                             DownstreamPathTemplate = "http://localhost:53876/", | ||||
|                             UpstreamTemplate = "/", | ||||
|                             UpstreamHttpMethod = "Get" | ||||
|                         } | ||||
|   | ||||
| @@ -40,7 +40,10 @@ namespace Ocelot.AcceptanceTests | ||||
|                     { | ||||
|                         new FileReRoute | ||||
|                         { | ||||
|                             DownstreamTemplate = "http://localhost:51879/", | ||||
|                             DownstreamPathTemplate = "/", | ||||
|                             DownstreamScheme = "http", | ||||
|                             DownstreamHost = "localhost", | ||||
|                             DownstreamPort = 51879, | ||||
|                             UpstreamTemplate = "/", | ||||
|                             UpstreamHttpMethod = "Get", | ||||
|                         } | ||||
| @@ -56,6 +59,62 @@ namespace Ocelot.AcceptanceTests | ||||
|                 .BDDfy(); | ||||
|         } | ||||
|  | ||||
|         [Fact] | ||||
|         public void should_return_response_200_when_path_missing_forward_slash_as_first_char() | ||||
|         { | ||||
|             var configuration = new FileConfiguration | ||||
|             { | ||||
|                 ReRoutes = new List<FileReRoute> | ||||
|                     { | ||||
|                         new FileReRoute | ||||
|                         { | ||||
|                             DownstreamPathTemplate = "api/products", | ||||
|                             DownstreamScheme = "http", | ||||
|                             DownstreamHost = "localhost", | ||||
|                             DownstreamPort = 51879, | ||||
|                             UpstreamTemplate = "/", | ||||
|                             UpstreamHttpMethod = "Get", | ||||
|                         } | ||||
|                     } | ||||
|             }; | ||||
|  | ||||
|             this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:51879/api/products", 200, "Hello from Laura")) | ||||
|                 .And(x => _steps.GivenThereIsAConfiguration(configuration)) | ||||
|                 .And(x => _steps.GivenOcelotIsRunning()) | ||||
|                 .When(x => _steps.WhenIGetUrlOnTheApiGateway("/")) | ||||
|                 .Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.OK)) | ||||
|                 .And(x => _steps.ThenTheResponseBodyShouldBe("Hello from Laura")) | ||||
|                 .BDDfy(); | ||||
|         } | ||||
|  | ||||
|         [Fact] | ||||
|         public void should_return_response_200_when_host_has_trailing_slash() | ||||
|         { | ||||
|             var configuration = new FileConfiguration | ||||
|             { | ||||
|                 ReRoutes = new List<FileReRoute> | ||||
|                     { | ||||
|                         new FileReRoute | ||||
|                         { | ||||
|                             DownstreamPathTemplate = "/api/products", | ||||
|                             DownstreamScheme = "http", | ||||
|                             DownstreamHost = "localhost/", | ||||
|                             DownstreamPort = 51879, | ||||
|                             UpstreamTemplate = "/", | ||||
|                             UpstreamHttpMethod = "Get", | ||||
|                         } | ||||
|                     } | ||||
|             }; | ||||
|  | ||||
|             this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:51879/api/products", 200, "Hello from Laura")) | ||||
|                 .And(x => _steps.GivenThereIsAConfiguration(configuration)) | ||||
|                 .And(x => _steps.GivenOcelotIsRunning()) | ||||
|                 .When(x => _steps.WhenIGetUrlOnTheApiGateway("/")) | ||||
|                 .Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.OK)) | ||||
|                 .And(x => _steps.ThenTheResponseBodyShouldBe("Hello from Laura")) | ||||
|                 .BDDfy(); | ||||
|         } | ||||
|  | ||||
|         [Fact] | ||||
|         public void should_not_care_about_no_trailing() | ||||
|         { | ||||
| @@ -65,7 +124,10 @@ namespace Ocelot.AcceptanceTests | ||||
|                     { | ||||
|                         new FileReRoute | ||||
|                         { | ||||
|                             DownstreamTemplate = "http://localhost:51879/products", | ||||
|                             DownstreamPathTemplate = "/products", | ||||
|                             DownstreamScheme = "http", | ||||
|                             DownstreamHost = "localhost", | ||||
|                             DownstreamPort = 51879, | ||||
|                             UpstreamTemplate = "/products/", | ||||
|                             UpstreamHttpMethod = "Get", | ||||
|                         } | ||||
| @@ -90,7 +152,10 @@ namespace Ocelot.AcceptanceTests | ||||
|                     { | ||||
|                         new FileReRoute | ||||
|                         { | ||||
|                             DownstreamTemplate = "http://localhost:51879/products", | ||||
|                             DownstreamPathTemplate = "/products", | ||||
|                             DownstreamScheme = "http", | ||||
|                             DownstreamHost = "localhost", | ||||
|                             DownstreamPort = 51879, | ||||
|                             UpstreamTemplate = "/products", | ||||
|                             UpstreamHttpMethod = "Get", | ||||
|                         } | ||||
| @@ -115,7 +180,10 @@ namespace Ocelot.AcceptanceTests | ||||
|                     { | ||||
|                         new FileReRoute | ||||
|                         { | ||||
|                             DownstreamTemplate = "http://localhost:51879/products", | ||||
|                             DownstreamPathTemplate = "/products", | ||||
|                             DownstreamScheme = "http", | ||||
|                             DownstreamHost = "localhost", | ||||
|                             DownstreamPort = 51879, | ||||
|                             UpstreamTemplate = "/products/{productId}", | ||||
|                             UpstreamHttpMethod = "Get", | ||||
|                         } | ||||
| @@ -139,7 +207,10 @@ namespace Ocelot.AcceptanceTests | ||||
|                     { | ||||
|                         new FileReRoute | ||||
|                         { | ||||
|                             DownstreamTemplate = "http://localhost:51879/api/products/{productId}", | ||||
|                             DownstreamPathTemplate = "/api/products/{productId}", | ||||
|                             DownstreamScheme = "http", | ||||
|                             DownstreamHost = "localhost", | ||||
|                             DownstreamPort = 51879, | ||||
|                             UpstreamTemplate = "/products/{productId}", | ||||
|                             UpstreamHttpMethod = "Get" | ||||
|                         } | ||||
| @@ -164,7 +235,10 @@ namespace Ocelot.AcceptanceTests | ||||
|                     { | ||||
|                         new FileReRoute | ||||
|                         { | ||||
|                             DownstreamTemplate = "http://localhost:51879/", | ||||
|                             DownstreamPathTemplate = "/", | ||||
|                             DownstreamHost = "localhost", | ||||
|                             DownstreamPort = 51879, | ||||
|                             DownstreamScheme = "http", | ||||
|                             UpstreamTemplate = "/", | ||||
|                             UpstreamHttpMethod = "Post" | ||||
|                         } | ||||
| @@ -189,8 +263,11 @@ namespace Ocelot.AcceptanceTests | ||||
|                     { | ||||
|                         new FileReRoute | ||||
|                         { | ||||
|                             DownstreamTemplate = "http://localhost:51879/newThing", | ||||
|                             DownstreamPathTemplate = "/newThing", | ||||
|                             UpstreamTemplate = "/newThing", | ||||
|                             DownstreamScheme = "http", | ||||
|                             DownstreamHost = "localhost", | ||||
|                             DownstreamPort = 51879, | ||||
|                             UpstreamHttpMethod = "Get", | ||||
|                         } | ||||
|                     } | ||||
|   | ||||
| @@ -1 +1 @@ | ||||
| {"ReRoutes":[{"DownstreamTemplate":"http://localhost:41879/","UpstreamTemplate":"/","UpstreamHttpMethod":"Get","AuthenticationOptions":{"Provider":null,"ProviderRootUrl":null,"ScopeName":null,"RequireHttps":false,"AdditionalScopes":[],"ScopeSecret":null},"AddHeadersToRequest":{},"AddClaimsToRequest":{},"RouteClaimsRequirement":{},"AddQueriesToRequest":{},"RequestIdKey":null,"FileCacheOptions":{"TtlSeconds":0},"ReRouteIsCaseSensitive":false}],"GlobalConfiguration":{"RequestIdKey":null}} | ||||
| {"ReRoutes":[{"DownstreamPathTemplate":"/","UpstreamTemplate":"/","UpstreamHttpMethod":"Get","AuthenticationOptions":{"Provider":null,"ProviderRootUrl":null,"ScopeName":null,"RequireHttps":false,"AdditionalScopes":[],"ScopeSecret":null},"AddHeadersToRequest":{},"AddClaimsToRequest":{},"RouteClaimsRequirement":{},"AddQueriesToRequest":{},"RequestIdKey":null,"FileCacheOptions":{"TtlSeconds":0},"ReRouteIsCaseSensitive":false,"ServiceName":null,"DownstreamScheme":"http","DownstreamHost":"localhost","DownstreamPort":41879}],"GlobalConfiguration":{"RequestIdKey":null,"ServiceDiscoveryProvider":{"Provider":null,"Address":null}}} | ||||
| @@ -10,7 +10,6 @@ namespace Ocelot.ManualTest | ||||
|             var host = new WebHostBuilder() | ||||
|                 .UseKestrel() | ||||
|                 .UseContentRoot(Directory.GetCurrentDirectory()) | ||||
|                 .UseIISIntegration() | ||||
|                 .UseStartup<Startup>() | ||||
|                 .Build(); | ||||
|  | ||||
|   | ||||
| @@ -1,7 +1,10 @@ | ||||
| { | ||||
|     "ReRoutes": [ | ||||
|         { | ||||
|             "DownstreamTemplate": "http://localhost:52876/", | ||||
|             "DownstreamPathTemplate": "/", | ||||
|             "DownstreamScheme": "http", | ||||
|             "DownstreamHost": "localhost", | ||||
|             "DownstreamPort": 52876, | ||||
|             "UpstreamTemplate": "/identityserverexample", | ||||
|             "UpstreamHttpMethod": "Get", | ||||
|             "AuthenticationOptions": { | ||||
| @@ -38,108 +41,165 @@ | ||||
|             "RequestIdKey": "OcRequestId" | ||||
|         }, | ||||
|         { | ||||
|             "DownstreamTemplate": "http://jsonplaceholder.typicode.com/posts", | ||||
|             "DownstreamPathTemplate": "/posts", | ||||
|             "DownstreamScheme": "http", | ||||
|             "DownstreamHost": "jsonplaceholder.typicode.com", | ||||
|             "DownstreamPort": 80, | ||||
|             "UpstreamTemplate": "/posts", | ||||
|             "UpstreamHttpMethod": "Get", | ||||
|             "FileCacheOptions": { "TtlSeconds": 15 } | ||||
|         }, | ||||
|         { | ||||
|             "DownstreamTemplate": "http://jsonplaceholder.typicode.com/posts/{postId}", | ||||
|             "DownstreamPathTemplate": "/posts/{postId}", | ||||
|             "DownstreamScheme": "http", | ||||
|             "DownstreamHost": "jsonplaceholder.typicode.com", | ||||
|             "DownstreamPort": 80, | ||||
|             "UpstreamTemplate": "/posts/{postId}", | ||||
|             "UpstreamHttpMethod": "Get" | ||||
|         }, | ||||
|         { | ||||
|             "DownstreamTemplate": "http://jsonplaceholder.typicode.com/posts/{postId}/comments", | ||||
|             "DownstreamPathTemplate": "/posts/{postId}/comments", | ||||
|             "DownstreamScheme": "http", | ||||
|             "DownstreamHost": "jsonplaceholder.typicode.com", | ||||
|             "DownstreamPort": 80, | ||||
|             "UpstreamTemplate": "/posts/{postId}/comments", | ||||
|             "UpstreamHttpMethod": "Get" | ||||
|         }, | ||||
|         { | ||||
|             "DownstreamTemplate": "http://jsonplaceholder.typicode.com/comments", | ||||
|             "DownstreamPathTemplate": "/comments", | ||||
|             "DownstreamScheme": "http", | ||||
|             "DownstreamHost": "jsonplaceholder.typicode.com", | ||||
|             "DownstreamPort": 80, | ||||
|             "UpstreamTemplate": "/comments", | ||||
|             "UpstreamHttpMethod": "Get" | ||||
|         }, | ||||
|         { | ||||
|             "DownstreamTemplate": "http://jsonplaceholder.typicode.com/posts", | ||||
|             "DownstreamPathTemplate": "/posts", | ||||
|             "DownstreamScheme": "http", | ||||
|             "DownstreamHost": "jsonplaceholder.typicode.com", | ||||
|             "DownstreamPort": 80, | ||||
|             "UpstreamTemplate": "/posts", | ||||
|             "UpstreamHttpMethod": "Post" | ||||
|         }, | ||||
|         { | ||||
|             "DownstreamTemplate": "http://jsonplaceholder.typicode.com/posts/{postId}", | ||||
|             "DownstreamPathTemplate": "/posts/{postId}", | ||||
|             "DownstreamScheme": "http", | ||||
|             "DownstreamHost": "jsonplaceholder.typicode.com", | ||||
|             "DownstreamPort": 80, | ||||
|             "UpstreamTemplate": "/posts/{postId}", | ||||
|             "UpstreamHttpMethod": "Put" | ||||
|         }, | ||||
|         { | ||||
|             "DownstreamTemplate": "http://jsonplaceholder.typicode.com/posts/{postId}", | ||||
|             "DownstreamPathTemplate": "/posts/{postId}", | ||||
|             "DownstreamScheme": "http", | ||||
|             "DownstreamHost": "jsonplaceholder.typicode.com", | ||||
|             "DownstreamPort": 80, | ||||
|             "UpstreamTemplate": "/posts/{postId}", | ||||
|             "UpstreamHttpMethod": "Patch" | ||||
|         }, | ||||
|         { | ||||
|             "DownstreamTemplate": "http://jsonplaceholder.typicode.com/posts/{postId}", | ||||
|             "DownstreamPathTemplate": "/posts/{postId}", | ||||
|             "DownstreamScheme": "http", | ||||
|             "DownstreamHost": "jsonplaceholder.typicode.com", | ||||
|             "DownstreamPort": 80, | ||||
|             "UpstreamTemplate": "/posts/{postId}", | ||||
|             "UpstreamHttpMethod": "Delete" | ||||
|         }, | ||||
|         { | ||||
|             "DownstreamTemplate": "http://products20161126090340.azurewebsites.net/api/products", | ||||
|             "DownstreamPathTemplate": "/api/products", | ||||
|             "DownstreamScheme": "http", | ||||
|             "DownstreamHost": "jsonplaceholder.typicode.com", | ||||
|             "DownstreamPort": 80, | ||||
|             "UpstreamTemplate": "/products", | ||||
|             "UpstreamHttpMethod": "Get", | ||||
|             "FileCacheOptions": { "TtlSeconds": 15 } | ||||
|         }, | ||||
|         { | ||||
|             "DownstreamTemplate": "http://products20161126090340.azurewebsites.net/api/products/{productId}", | ||||
|             "DownstreamPathTemplate": "/api/products/{productId}", | ||||
|             "DownstreamScheme": "http", | ||||
|             "DownstreamHost": "jsonplaceholder.typicode.com", | ||||
|             "DownstreamPort": 80, | ||||
|             "UpstreamTemplate": "/products/{productId}", | ||||
|             "UpstreamHttpMethod": "Get", | ||||
|             "FileCacheOptions": { "TtlSeconds": 15 } | ||||
|         }, | ||||
|         { | ||||
|             "DownstreamTemplate": "http://products20161126090340.azurewebsites.net/api/products", | ||||
|             "DownstreamPathTemplate": "/api/products", | ||||
|             "DownstreamScheme": "http", | ||||
|             "DownstreamHost": "products20161126090340.azurewebsites.net", | ||||
|             "DownstreamPort": 80, | ||||
|             "UpstreamTemplate": "/products", | ||||
|             "UpstreamHttpMethod": "Post", | ||||
|             "FileCacheOptions": { "TtlSeconds": 15 } | ||||
|         }, | ||||
|         { | ||||
|             "DownstreamTemplate": "http://products20161126090340.azurewebsites.net/api/products/{productId}", | ||||
|             "DownstreamPathTemplate": "/api/products/{productId}", | ||||
|             "DownstreamScheme": "http", | ||||
|             "DownstreamHost": "products20161126090340.azurewebsites.net", | ||||
|             "DownstreamPort": 80, | ||||
|             "UpstreamTemplate": "/products/{productId}", | ||||
|             "UpstreamHttpMethod": "Put", | ||||
|             "FileCacheOptions": { "TtlSeconds": 15 } | ||||
|         }, | ||||
|         { | ||||
|             "DownstreamTemplate": "http://products20161126090340.azurewebsites.net/api/products/{productId}", | ||||
|             "DownstreamPathTemplate": "/api/products/{productId}", | ||||
|             "DownstreamScheme": "http", | ||||
|             "DownstreamHost": "products20161126090340.azurewebsites.net", | ||||
|             "DownstreamPort": 80, | ||||
|             "UpstreamTemplate": "/products/{productId}", | ||||
|             "UpstreamHttpMethod": "Delete", | ||||
|             "FileCacheOptions": { "TtlSeconds": 15 } | ||||
|         }, | ||||
|         { | ||||
|             "DownstreamTemplate": "http://customers20161126090811.azurewebsites.net/api/customers", | ||||
|             "DownstreamPathTemplate": "/api/customers", | ||||
|             "DownstreamScheme": "http", | ||||
|             "DownstreamHost": "customers20161126090811.azurewebsites.net", | ||||
|             "DownstreamPort": 80, | ||||
|             "UpstreamTemplate": "/customers", | ||||
|             "UpstreamHttpMethod": "Get", | ||||
|             "FileCacheOptions": { "TtlSeconds": 15 } | ||||
|         }, | ||||
|         { | ||||
|             "DownstreamTemplate": "http://customers20161126090811.azurewebsites.net/api/customers/{customerId}", | ||||
|             "DownstreamPathTemplate": "/api/customers/{customerId}", | ||||
|             "DownstreamScheme": "http", | ||||
|             "DownstreamHost": "customers20161126090811.azurewebsites.net", | ||||
|             "DownstreamPort": 80, | ||||
|             "UpstreamTemplate": "/customers/{customerId}", | ||||
|             "UpstreamHttpMethod": "Get", | ||||
|             "FileCacheOptions": { "TtlSeconds": 15 } | ||||
|         }, | ||||
|         { | ||||
|             "DownstreamTemplate": "http://customers20161126090811.azurewebsites.net/api/customers", | ||||
|             "DownstreamPathTemplate": "/api/customers", | ||||
|             "DownstreamScheme": "http", | ||||
|             "DownstreamHost": "customers20161126090811.azurewebsites.net", | ||||
|             "DownstreamPort": 80, | ||||
|             "UpstreamTemplate": "/customers", | ||||
|             "UpstreamHttpMethod": "Post", | ||||
|             "FileCacheOptions": { "TtlSeconds": 15 } | ||||
|         }, | ||||
|         { | ||||
|             "DownstreamTemplate": "http://customers20161126090811.azurewebsites.net/api/customers/{customerId}", | ||||
|             "DownstreamPathTemplate": "/api/customers/{customerId}", | ||||
|             "DownstreamScheme": "http", | ||||
|             "DownstreamHost": "customers20161126090811.azurewebsites.net", | ||||
|             "DownstreamPort": 80, | ||||
|             "UpstreamTemplate": "/customers/{customerId}", | ||||
|             "UpstreamHttpMethod": "Put", | ||||
|             "FileCacheOptions": { "TtlSeconds": 15 } | ||||
|         }, | ||||
|         { | ||||
|             "DownstreamTemplate": "http://customers20161126090811.azurewebsites.net/api/customers/{customerId}", | ||||
|             "DownstreamPathTemplate": "/api/customers/{customerId}", | ||||
|             "DownstreamScheme": "http", | ||||
|             "DownstreamHost": "customers20161126090811.azurewebsites.net", | ||||
|             "DownstreamPort": 80, | ||||
|             "UpstreamTemplate": "/customers/{customerId}", | ||||
|             "UpstreamHttpMethod": "Delete", | ||||
|             "FileCacheOptions": { "TtlSeconds": 15 } | ||||
|         }, | ||||
|         { | ||||
|             "DownstreamTemplate": "http://jsonplaceholder.typicode.com/posts", | ||||
|             "DownstreamPathTemplate": "/posts", | ||||
|             "DownstreamScheme": "http", | ||||
|             "DownstreamHost": "jsonplaceholder.typicode.com", | ||||
|             "DownstreamPort": 80, | ||||
|             "UpstreamTemplate": "/posts/", | ||||
|             "UpstreamHttpMethod": "Get", | ||||
|             "FileCacheOptions": { "TtlSeconds": 15 } | ||||
|   | ||||
| @@ -67,7 +67,7 @@ namespace Ocelot.UnitTests.Claims | ||||
|         { | ||||
|             var downstreamRoute = new DownstreamRoute(new List<UrlPathPlaceholderNameAndValue>(), | ||||
|                 new ReRouteBuilder() | ||||
|                     .WithDownstreamTemplate("any old string") | ||||
|                     .WithDownstreamPathTemplate("any old string") | ||||
|                     .WithClaimsToClaims(new List<ClaimToThing> | ||||
|                     { | ||||
|                         new ClaimToThing("sub", "UserType", "|", 0) | ||||
|   | ||||
| @@ -10,8 +10,8 @@ namespace Ocelot.UnitTests.Configuration | ||||
| { | ||||
|     public class ConfigurationValidationTests | ||||
|     { | ||||
|         private FileConfiguration _fileConfiguration; | ||||
|         private readonly IConfigurationValidator _configurationValidator; | ||||
|         private FileConfiguration _fileConfiguration; | ||||
|         private Response<ConfigurationValidationResult> _result; | ||||
|  | ||||
|         public ConfigurationValidationTests() | ||||
| @@ -22,32 +22,13 @@ namespace Ocelot.UnitTests.Configuration | ||||
|         [Fact] | ||||
|         public void configuration_is_invalid_if_scheme_in_downstream_template() | ||||
|         { | ||||
|                 this.Given(x => x.GivenAConfiguration(new FileConfiguration() | ||||
|             this.Given(x => x.GivenAConfiguration(new FileConfiguration | ||||
|             { | ||||
|                 ReRoutes = new List<FileReRoute> | ||||
|                 { | ||||
|                     new FileReRoute | ||||
|                     { | ||||
|                         DownstreamTemplate = "http://www.bbc.co.uk/api/products/{productId}", | ||||
|                         UpstreamTemplate = "http://asdf.com" | ||||
|                     } | ||||
|                 } | ||||
|             })) | ||||
|                 .When(x => x.WhenIValidateTheConfiguration()) | ||||
|                 .Then(x => x.ThenTheResultIsNotValid()) | ||||
|                 .BDDfy(); | ||||
|         } | ||||
|  | ||||
|            [Fact] | ||||
|         public void configuration_is_invalid_if_host_in_downstream_template() | ||||
|         { | ||||
|                 this.Given(x => x.GivenAConfiguration(new FileConfiguration() | ||||
|             { | ||||
|                 ReRoutes = new List<FileReRoute> | ||||
|                 { | ||||
|                     new FileReRoute | ||||
|                     { | ||||
|                         DownstreamTemplate = "www.bbc.co.uk/api/products/{productId}", | ||||
|                         DownstreamPathTemplate = "http://www.bbc.co.uk/api/products/{productId}", | ||||
|                         UpstreamTemplate = "http://asdf.com" | ||||
|                     } | ||||
|                 } | ||||
| @@ -60,13 +41,13 @@ namespace Ocelot.UnitTests.Configuration | ||||
|         [Fact] | ||||
|         public void configuration_is_valid_with_one_reroute() | ||||
|         { | ||||
|             this.Given(x => x.GivenAConfiguration(new FileConfiguration() | ||||
|             this.Given(x => x.GivenAConfiguration(new FileConfiguration | ||||
|             { | ||||
|                 ReRoutes = new List<FileReRoute> | ||||
|                 { | ||||
|                     new FileReRoute | ||||
|                     { | ||||
|                         DownstreamTemplate = "/api/products/", | ||||
|                         DownstreamPathTemplate = "/api/products/", | ||||
|                         UpstreamTemplate = "http://asdf.com" | ||||
|                     } | ||||
|                 } | ||||
| @@ -79,13 +60,13 @@ namespace Ocelot.UnitTests.Configuration | ||||
|         [Fact] | ||||
|         public void configuration_is_valid_with_valid_authentication_provider() | ||||
|         { | ||||
|             this.Given(x => x.GivenAConfiguration(new FileConfiguration() | ||||
|             this.Given(x => x.GivenAConfiguration(new FileConfiguration | ||||
|             { | ||||
|                 ReRoutes = new List<FileReRoute> | ||||
|                 { | ||||
|                     new FileReRoute | ||||
|                     { | ||||
|                         DownstreamTemplate = "/api/products/", | ||||
|                         DownstreamPathTemplate = "/api/products/", | ||||
|                         UpstreamTemplate = "http://asdf.com", | ||||
|                         AuthenticationOptions = new FileAuthenticationOptions | ||||
|                         { | ||||
| @@ -102,13 +83,13 @@ namespace Ocelot.UnitTests.Configuration | ||||
|         [Fact] | ||||
|         public void configuration_is_invalid_with_invalid_authentication_provider() | ||||
|         { | ||||
|             this.Given(x => x.GivenAConfiguration(new FileConfiguration() | ||||
|             this.Given(x => x.GivenAConfiguration(new FileConfiguration | ||||
|             { | ||||
|                 ReRoutes = new List<FileReRoute> | ||||
|                 { | ||||
|                     new FileReRoute | ||||
|                     { | ||||
|                         DownstreamTemplate = "/api/products/", | ||||
|                         DownstreamPathTemplate = "/api/products/", | ||||
|                         UpstreamTemplate = "http://asdf.com", | ||||
|                         AuthenticationOptions = new FileAuthenticationOptions | ||||
|                         { | ||||
| @@ -126,25 +107,25 @@ namespace Ocelot.UnitTests.Configuration | ||||
|         [Fact] | ||||
|         public void configuration_is_not_valid_with_duplicate_reroutes() | ||||
|         { | ||||
|             this.Given(x => x.GivenAConfiguration(new FileConfiguration() | ||||
|             this.Given(x => x.GivenAConfiguration(new FileConfiguration | ||||
|             { | ||||
|                 ReRoutes = new List<FileReRoute> | ||||
|                 { | ||||
|                     new FileReRoute | ||||
|                     { | ||||
|                         DownstreamTemplate = "/api/products/", | ||||
|                         DownstreamPathTemplate = "/api/products/", | ||||
|                         UpstreamTemplate = "http://asdf.com" | ||||
|                     }, | ||||
|                     new FileReRoute | ||||
|                     { | ||||
|                         DownstreamTemplate = "http://www.bbc.co.uk", | ||||
|                         DownstreamPathTemplate = "http://www.bbc.co.uk", | ||||
|                         UpstreamTemplate = "http://asdf.com" | ||||
|                     } | ||||
|                 } | ||||
|             })) | ||||
|                 .When(x => x.WhenIValidateTheConfiguration()) | ||||
|                 .Then(x => x.ThenTheResultIsNotValid()) | ||||
|                 .And(x => x.ThenTheErrorIs<DownstreamTemplateAlreadyUsedError>()) | ||||
|                 .And(x => x.ThenTheErrorIs<DownstreamPathTemplateAlreadyUsedError>()) | ||||
|                 .BDDfy(); | ||||
|         } | ||||
|  | ||||
| @@ -173,4 +154,4 @@ namespace Ocelot.UnitTests.Configuration | ||||
|             _result.Data.Errors[0].ShouldBeOfType<T>(); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| } | ||||
| @@ -46,7 +46,7 @@ namespace Ocelot.UnitTests.Configuration | ||||
|                                     { | ||||
|                                         DownstreamHost = "127.0.0.1", | ||||
|                                         UpstreamTemplate = "/api/products/{productId}", | ||||
|                                         DownstreamTemplate = "/products/{productId}", | ||||
|                                         DownstreamPathTemplate = "/products/{productId}", | ||||
|                                         UpstreamHttpMethod = "Get", | ||||
|                                     } | ||||
|                                 }, | ||||
| @@ -57,7 +57,7 @@ namespace Ocelot.UnitTests.Configuration | ||||
|                                 { | ||||
|                                     new ReRouteBuilder() | ||||
|                                         .WithDownstreamHost("127.0.0.1") | ||||
|                                         .WithDownstreamTemplate("/products/{productId}") | ||||
|                                         .WithDownstreamPathTemplate("/products/{productId}") | ||||
|                                         .WithUpstreamTemplate("/api/products/{productId}") | ||||
|                                         .WithUpstreamHttpMethod("Get") | ||||
|                                         .WithUpstreamTemplatePattern("(?i)/api/products/.*/$") | ||||
| @@ -76,7 +76,7 @@ namespace Ocelot.UnitTests.Configuration | ||||
|                                                 { | ||||
|                                                     DownstreamScheme = "https", | ||||
|                                                     UpstreamTemplate = "/api/products/{productId}", | ||||
|                                                     DownstreamTemplate = "/products/{productId}", | ||||
|                                                     DownstreamPathTemplate = "/products/{productId}", | ||||
|                                                     UpstreamHttpMethod = "Get", | ||||
|                                                 } | ||||
|                                             }, | ||||
| @@ -87,7 +87,7 @@ namespace Ocelot.UnitTests.Configuration | ||||
|                                             { | ||||
|                                                 new ReRouteBuilder() | ||||
|                                                     .WithDownstreamScheme("https") | ||||
|                                                     .WithDownstreamTemplate("/products/{productId}") | ||||
|                                                     .WithDownstreamPathTemplate("/products/{productId}") | ||||
|                                                     .WithUpstreamTemplate("/api/products/{productId}") | ||||
|                                                     .WithUpstreamHttpMethod("Get") | ||||
|                                                     .WithUpstreamTemplatePattern("(?i)/api/products/.*/$") | ||||
| @@ -106,7 +106,7 @@ namespace Ocelot.UnitTests.Configuration | ||||
|                                 new FileReRoute | ||||
|                                 { | ||||
|                                     UpstreamTemplate = "/api/products/{productId}", | ||||
|                                     DownstreamTemplate = "/products/{productId}", | ||||
|                                     DownstreamPathTemplate = "/products/{productId}", | ||||
|                                     UpstreamHttpMethod = "Get", | ||||
|                                     ReRouteIsCaseSensitive = false, | ||||
|                                     ServiceName = "ProductService" | ||||
| @@ -126,7 +126,7 @@ namespace Ocelot.UnitTests.Configuration | ||||
|                             .Then(x => x.ThenTheReRoutesAre(new List<ReRoute> | ||||
|                             { | ||||
|                                 new ReRouteBuilder() | ||||
|                                     .WithDownstreamTemplate("/products/{productId}") | ||||
|                                     .WithDownstreamPathTemplate("/products/{productId}") | ||||
|                                     .WithUpstreamTemplate("/api/products/{productId}") | ||||
|                                     .WithUpstreamHttpMethod("Get") | ||||
|                                     .WithUpstreamTemplatePattern("(?i)/api/products/.*/$") | ||||
| @@ -149,7 +149,7 @@ namespace Ocelot.UnitTests.Configuration | ||||
|                                 new FileReRoute | ||||
|                                 { | ||||
|                                     UpstreamTemplate = "/api/products/{productId}", | ||||
|                                     DownstreamTemplate = "/products/{productId}", | ||||
|                                     DownstreamPathTemplate = "/products/{productId}", | ||||
|                                     UpstreamHttpMethod = "Get", | ||||
|                                     ReRouteIsCaseSensitive = false, | ||||
|                                 } | ||||
| @@ -160,7 +160,7 @@ namespace Ocelot.UnitTests.Configuration | ||||
|                             .Then(x => x.ThenTheReRoutesAre(new List<ReRoute> | ||||
|                             { | ||||
|                                 new ReRouteBuilder() | ||||
|                                     .WithDownstreamTemplate("/products/{productId}") | ||||
|                                     .WithDownstreamPathTemplate("/products/{productId}") | ||||
|                                     .WithUpstreamTemplate("/api/products/{productId}") | ||||
|                                     .WithUpstreamHttpMethod("Get") | ||||
|                                     .WithUpstreamTemplatePattern("(?i)/api/products/.*/$") | ||||
| @@ -182,7 +182,7 @@ namespace Ocelot.UnitTests.Configuration | ||||
|                     new FileReRoute | ||||
|                     { | ||||
|                         UpstreamTemplate = "/api/products/{productId}", | ||||
|                         DownstreamTemplate = "/products/{productId}", | ||||
|                         DownstreamPathTemplate = "/products/{productId}", | ||||
|                         UpstreamHttpMethod = "Get", | ||||
|                         ReRouteIsCaseSensitive = false | ||||
|                     } | ||||
| @@ -193,7 +193,7 @@ namespace Ocelot.UnitTests.Configuration | ||||
|                 .Then(x => x.ThenTheReRoutesAre(new List<ReRoute> | ||||
|                 { | ||||
|                     new ReRouteBuilder() | ||||
|                         .WithDownstreamTemplate("/products/{productId}") | ||||
|                         .WithDownstreamPathTemplate("/products/{productId}") | ||||
|                         .WithUpstreamTemplate("/api/products/{productId}") | ||||
|                         .WithUpstreamHttpMethod("Get") | ||||
|                         .WithUpstreamTemplatePattern("(?i)/api/products/.*/$") | ||||
| @@ -212,7 +212,7 @@ namespace Ocelot.UnitTests.Configuration | ||||
|                     new FileReRoute | ||||
|                     { | ||||
|                         UpstreamTemplate = "/api/products/{productId}", | ||||
|                         DownstreamTemplate = "/products/{productId}", | ||||
|                         DownstreamPathTemplate = "/products/{productId}", | ||||
|                         UpstreamHttpMethod = "Get" | ||||
|                     } | ||||
|                 } | ||||
| @@ -222,7 +222,7 @@ namespace Ocelot.UnitTests.Configuration | ||||
|                 .Then(x => x.ThenTheReRoutesAre(new List<ReRoute> | ||||
|                 { | ||||
|                     new ReRouteBuilder() | ||||
|                         .WithDownstreamTemplate("/products/{productId}") | ||||
|                         .WithDownstreamPathTemplate("/products/{productId}") | ||||
|                         .WithUpstreamTemplate("/api/products/{productId}") | ||||
|                         .WithUpstreamHttpMethod("Get") | ||||
|                         .WithUpstreamTemplatePattern("(?i)/api/products/.*/$") | ||||
| @@ -241,7 +241,7 @@ namespace Ocelot.UnitTests.Configuration | ||||
|                     new FileReRoute | ||||
|                     { | ||||
|                         UpstreamTemplate = "/api/products/{productId}", | ||||
|                         DownstreamTemplate = "/products/{productId}", | ||||
|                         DownstreamPathTemplate = "/products/{productId}", | ||||
|                         UpstreamHttpMethod = "Get", | ||||
|                         ReRouteIsCaseSensitive = true | ||||
|                     } | ||||
| @@ -252,7 +252,7 @@ namespace Ocelot.UnitTests.Configuration | ||||
|               .Then(x => x.ThenTheReRoutesAre(new List<ReRoute> | ||||
|               { | ||||
|                     new ReRouteBuilder() | ||||
|                         .WithDownstreamTemplate("/products/{productId}") | ||||
|                         .WithDownstreamPathTemplate("/products/{productId}") | ||||
|                         .WithUpstreamTemplate("/api/products/{productId}") | ||||
|                         .WithUpstreamHttpMethod("Get") | ||||
|                         .WithUpstreamTemplatePattern("/api/products/.*/$") | ||||
| @@ -271,7 +271,7 @@ namespace Ocelot.UnitTests.Configuration | ||||
|                     new FileReRoute | ||||
|                     { | ||||
|                         UpstreamTemplate = "/api/products/{productId}", | ||||
|                         DownstreamTemplate = "/products/{productId}", | ||||
|                         DownstreamPathTemplate = "/products/{productId}", | ||||
|                         UpstreamHttpMethod = "Get", | ||||
|                         ReRouteIsCaseSensitive = true | ||||
|                     } | ||||
| @@ -286,7 +286,7 @@ namespace Ocelot.UnitTests.Configuration | ||||
|                 .Then(x => x.ThenTheReRoutesAre(new List<ReRoute> | ||||
|                 { | ||||
|                     new ReRouteBuilder() | ||||
|                         .WithDownstreamTemplate("/products/{productId}") | ||||
|                         .WithDownstreamPathTemplate("/products/{productId}") | ||||
|                         .WithUpstreamTemplate("/api/products/{productId}") | ||||
|                         .WithUpstreamHttpMethod("Get") | ||||
|                         .WithUpstreamTemplatePattern("/api/products/.*/$") | ||||
| @@ -306,7 +306,7 @@ namespace Ocelot.UnitTests.Configuration | ||||
|                     new FileReRoute | ||||
|                     { | ||||
|                         UpstreamTemplate = "/api/products/{productId}", | ||||
|                         DownstreamTemplate = "/products/{productId}", | ||||
|                         DownstreamPathTemplate = "/products/{productId}", | ||||
|                         UpstreamHttpMethod = "Get", | ||||
|                         ReRouteIsCaseSensitive = true | ||||
|                     } | ||||
| @@ -317,7 +317,7 @@ namespace Ocelot.UnitTests.Configuration | ||||
|                 .Then(x => x.ThenTheReRoutesAre(new List<ReRoute> | ||||
|                 { | ||||
|                     new ReRouteBuilder() | ||||
|                         .WithDownstreamTemplate("/products/{productId}") | ||||
|                         .WithDownstreamPathTemplate("/products/{productId}") | ||||
|                         .WithUpstreamTemplate("/api/products/{productId}") | ||||
|                         .WithUpstreamHttpMethod("Get") | ||||
|                         .WithUpstreamTemplatePattern("/api/products/.*/$") | ||||
| @@ -332,7 +332,7 @@ namespace Ocelot.UnitTests.Configuration | ||||
|             var expected = new List<ReRoute> | ||||
|             { | ||||
|                 new ReRouteBuilder() | ||||
|                     .WithDownstreamTemplate("/products/{productId}") | ||||
|                     .WithDownstreamPathTemplate("/products/{productId}") | ||||
|                     .WithUpstreamTemplate("/api/products/{productId}") | ||||
|                     .WithUpstreamHttpMethod("Get") | ||||
|                     .WithUpstreamTemplatePattern("/api/products/.*/$") | ||||
| @@ -355,7 +355,7 @@ namespace Ocelot.UnitTests.Configuration | ||||
|                     new FileReRoute | ||||
|                     { | ||||
|                         UpstreamTemplate = "/api/products/{productId}", | ||||
|                         DownstreamTemplate = "/products/{productId}", | ||||
|                         DownstreamPathTemplate = "/products/{productId}", | ||||
|                         UpstreamHttpMethod = "Get", | ||||
|                         ReRouteIsCaseSensitive = true, | ||||
|                         AuthenticationOptions = new FileAuthenticationOptions | ||||
| @@ -395,7 +395,7 @@ namespace Ocelot.UnitTests.Configuration | ||||
|             var expected = new List<ReRoute> | ||||
|             { | ||||
|                 new ReRouteBuilder() | ||||
|                     .WithDownstreamTemplate("/products/{productId}") | ||||
|                     .WithDownstreamPathTemplate("/products/{productId}") | ||||
|                     .WithUpstreamTemplate("/api/products/{productId}") | ||||
|                     .WithUpstreamHttpMethod("Get") | ||||
|                     .WithUpstreamTemplatePattern("/api/products/.*/$") | ||||
| @@ -414,7 +414,7 @@ namespace Ocelot.UnitTests.Configuration | ||||
|                     new FileReRoute | ||||
|                     { | ||||
|                         UpstreamTemplate = "/api/products/{productId}", | ||||
|                         DownstreamTemplate = "/products/{productId}", | ||||
|                         DownstreamPathTemplate = "/products/{productId}", | ||||
|                         UpstreamHttpMethod = "Get", | ||||
|                         ReRouteIsCaseSensitive = true, | ||||
|                         AuthenticationOptions = new FileAuthenticationOptions | ||||
| @@ -446,7 +446,7 @@ namespace Ocelot.UnitTests.Configuration | ||||
|                     new FileReRoute | ||||
|                     { | ||||
|                         UpstreamTemplate = "/api/products/{productId}/variants/{variantId}", | ||||
|                         DownstreamTemplate = "/products/{productId}", | ||||
|                         DownstreamPathTemplate = "/products/{productId}", | ||||
|                         UpstreamHttpMethod = "Get", | ||||
|                         ReRouteIsCaseSensitive = true | ||||
|                     } | ||||
| @@ -457,7 +457,7 @@ namespace Ocelot.UnitTests.Configuration | ||||
|                 .Then(x => x.ThenTheReRoutesAre(new List<ReRoute> | ||||
|                 { | ||||
|                     new ReRouteBuilder() | ||||
|                         .WithDownstreamTemplate("/products/{productId}") | ||||
|                         .WithDownstreamPathTemplate("/products/{productId}") | ||||
|                         .WithUpstreamTemplate("/api/products/{productId}/variants/{variantId}") | ||||
|                         .WithUpstreamHttpMethod("Get") | ||||
|                         .WithUpstreamTemplatePattern("/api/products/.*/variants/.*/$") | ||||
| @@ -476,7 +476,7 @@ namespace Ocelot.UnitTests.Configuration | ||||
|                     new FileReRoute | ||||
|                     { | ||||
|                         UpstreamTemplate = "/api/products/{productId}/variants/{variantId}/", | ||||
|                         DownstreamTemplate = "/products/{productId}", | ||||
|                         DownstreamPathTemplate = "/products/{productId}", | ||||
|                         UpstreamHttpMethod = "Get", | ||||
|                         ReRouteIsCaseSensitive = true | ||||
|                     } | ||||
| @@ -487,7 +487,7 @@ namespace Ocelot.UnitTests.Configuration | ||||
|                 .Then(x => x.ThenTheReRoutesAre(new List<ReRoute> | ||||
|                 { | ||||
|                     new ReRouteBuilder() | ||||
|                         .WithDownstreamTemplate("/products/{productId}") | ||||
|                         .WithDownstreamPathTemplate("/products/{productId}") | ||||
|                         .WithUpstreamTemplate("/api/products/{productId}/variants/{variantId}/") | ||||
|                         .WithUpstreamHttpMethod("Get") | ||||
|                         .WithUpstreamTemplatePattern("/api/products/.*/variants/.*/$") | ||||
| @@ -506,7 +506,7 @@ namespace Ocelot.UnitTests.Configuration | ||||
|                     new FileReRoute | ||||
|                     { | ||||
|                         UpstreamTemplate = "/", | ||||
|                         DownstreamTemplate = "/api/products/", | ||||
|                         DownstreamPathTemplate = "/api/products/", | ||||
|                         UpstreamHttpMethod = "Get", | ||||
|                         ReRouteIsCaseSensitive = true | ||||
|                     } | ||||
| @@ -517,7 +517,7 @@ namespace Ocelot.UnitTests.Configuration | ||||
|                 .Then(x => x.ThenTheReRoutesAre(new List<ReRoute> | ||||
|                 { | ||||
|                     new ReRouteBuilder() | ||||
|                         .WithDownstreamTemplate("/api/products/") | ||||
|                         .WithDownstreamPathTemplate("/api/products/") | ||||
|                         .WithUpstreamTemplate("/") | ||||
|                         .WithUpstreamHttpMethod("Get") | ||||
|                         .WithUpstreamTemplatePattern("/$") | ||||
| @@ -553,7 +553,7 @@ namespace Ocelot.UnitTests.Configuration | ||||
|                 var result = _config.Data.ReRoutes[i]; | ||||
|                 var expected = expectedReRoutes[i]; | ||||
|  | ||||
|                 result.DownstreamTemplate.ShouldBe(expected.DownstreamTemplate); | ||||
|                 result.DownstreamPathTemplate.Value.ShouldBe(expected.DownstreamPathTemplate.Value); | ||||
|                 result.UpstreamHttpMethod.ShouldBe(expected.UpstreamHttpMethod); | ||||
|                 result.UpstreamTemplate.ShouldBe(expected.UpstreamTemplate); | ||||
|                 result.UpstreamTemplatePattern.ShouldBe(expected.UpstreamTemplatePattern); | ||||
|   | ||||
| @@ -44,7 +44,7 @@ namespace Ocelot.UnitTests.Configuration | ||||
|  | ||||
|         private void ThenTheConfigurationIsReturned() | ||||
|         { | ||||
|             _getResult.Data.ReRoutes[0].DownstreamTemplate.ShouldBe("initial"); | ||||
|             _getResult.Data.ReRoutes[0].DownstreamPathTemplate.Value.ShouldBe("initial"); | ||||
|         } | ||||
|  | ||||
|         private void WhenIGetTheConfiguration() | ||||
| @@ -75,16 +75,16 @@ namespace Ocelot.UnitTests.Configuration | ||||
|  | ||||
|         class FakeConfig : IOcelotConfiguration | ||||
|         { | ||||
|             private readonly string _downstreamTemplate; | ||||
|             private readonly string _downstreamTemplatePath; | ||||
|  | ||||
|             public FakeConfig(string downstreamTemplate) | ||||
|             public FakeConfig(string downstreamTemplatePath) | ||||
|             { | ||||
|                 _downstreamTemplate = downstreamTemplate; | ||||
|                 _downstreamTemplatePath = downstreamTemplatePath; | ||||
|             } | ||||
|  | ||||
|             public List<ReRoute> ReRoutes => new List<ReRoute> | ||||
|             { | ||||
|                 new ReRouteBuilder().WithDownstreamTemplate(_downstreamTemplate).Build() | ||||
|                 new ReRouteBuilder().WithDownstreamPathTemplate(_downstreamTemplatePath).Build() | ||||
|             }; | ||||
|         } | ||||
|     } | ||||
|   | ||||
| @@ -61,7 +61,7 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder | ||||
|         [Fact] | ||||
|         public void should_call_scoped_data_repository_correctly() | ||||
|         { | ||||
|             this.Given(x => x.GivenTheDownStreamRouteFinderReturns(new DownstreamRoute(new List<UrlPathPlaceholderNameAndValue>(), new ReRouteBuilder().WithDownstreamTemplate("any old string").Build()))) | ||||
|             this.Given(x => x.GivenTheDownStreamRouteFinderReturns(new DownstreamRoute(new List<UrlPathPlaceholderNameAndValue>(), new ReRouteBuilder().WithDownstreamPathTemplate("any old string").Build()))) | ||||
|                 .When(x => x.WhenICallTheMiddleware()) | ||||
|                 .Then(x => x.ThenTheScopedDataRepositoryIsCalledCorrectly()) | ||||
|                 .BDDfy(); | ||||
|   | ||||
| @@ -44,7 +44,7 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder | ||||
|                 .And(x => x.GivenTheConfigurationIs(new List<ReRoute> | ||||
|                 { | ||||
|                     new ReRouteBuilder() | ||||
|                         .WithDownstreamTemplate("someDownstreamPath") | ||||
|                         .WithDownstreamPathTemplate("someDownstreamPath") | ||||
|                         .WithUpstreamTemplate("someUpstreamPath") | ||||
|                         .WithUpstreamHttpMethod("Get") | ||||
|                         .WithUpstreamTemplatePattern("someUpstreamPath") | ||||
| @@ -57,7 +57,7 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder | ||||
|                 .Then( | ||||
|                     x => x.ThenTheFollowingIsReturned(new DownstreamRoute(new List<UrlPathPlaceholderNameAndValue>(), | ||||
|                         new ReRouteBuilder() | ||||
|                             .WithDownstreamTemplate("someDownstreamPath") | ||||
|                             .WithDownstreamPathTemplate("someDownstreamPath") | ||||
|                             .Build() | ||||
|                         ))) | ||||
|                 .And(x => x.ThenTheUrlMatcherIsCalledCorrectly()) | ||||
| @@ -75,13 +75,13 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder | ||||
|                 .And(x => x.GivenTheConfigurationIs(new List<ReRoute> | ||||
|                 { | ||||
|                     new ReRouteBuilder() | ||||
|                         .WithDownstreamTemplate("someDownstreamPath") | ||||
|                         .WithDownstreamPathTemplate("someDownstreamPath") | ||||
|                         .WithUpstreamTemplate("someUpstreamPath") | ||||
|                         .WithUpstreamHttpMethod("Get") | ||||
|                         .WithUpstreamTemplatePattern("") | ||||
|                         .Build(), | ||||
|                     new ReRouteBuilder() | ||||
|                         .WithDownstreamTemplate("someDownstreamPathForAPost") | ||||
|                         .WithDownstreamPathTemplate("someDownstreamPathForAPost") | ||||
|                         .WithUpstreamTemplate("someUpstreamPath") | ||||
|                         .WithUpstreamHttpMethod("Post") | ||||
|                         .WithUpstreamTemplatePattern("") | ||||
| @@ -94,7 +94,7 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder | ||||
|                 .Then( | ||||
|                     x => x.ThenTheFollowingIsReturned(new DownstreamRoute(new List<UrlPathPlaceholderNameAndValue>(), | ||||
|                         new ReRouteBuilder() | ||||
|                             .WithDownstreamTemplate("someDownstreamPathForAPost") | ||||
|                             .WithDownstreamPathTemplate("someDownstreamPathForAPost") | ||||
|                             .Build() | ||||
|                         ))) | ||||
|                 .BDDfy(); | ||||
| @@ -107,7 +107,7 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder | ||||
|                  .And(x => x.GivenTheConfigurationIs(new List<ReRoute> | ||||
|                      { | ||||
|                         new ReRouteBuilder() | ||||
|                         .WithDownstreamTemplate("somPath") | ||||
|                         .WithDownstreamPathTemplate("somPath") | ||||
|                         .WithUpstreamTemplate("somePath") | ||||
|                         .WithUpstreamHttpMethod("Get") | ||||
|                         .WithUpstreamTemplatePattern("somePath") | ||||
| @@ -174,7 +174,7 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder | ||||
|  | ||||
|         private void ThenTheFollowingIsReturned(DownstreamRoute expected) | ||||
|         { | ||||
|             _result.Data.ReRoute.DownstreamTemplate.ShouldBe(expected.ReRoute.DownstreamTemplate); | ||||
|             _result.Data.ReRoute.DownstreamPathTemplate.Value.ShouldBe(expected.ReRoute.DownstreamPathTemplate.Value); | ||||
|  | ||||
|             for (int i = 0; i < _result.Data.TemplatePlaceholderNameAndValues.Count; i++) | ||||
|             { | ||||
|   | ||||
| @@ -7,15 +7,18 @@ using Microsoft.AspNetCore.TestHost; | ||||
| using Microsoft.Extensions.DependencyInjection; | ||||
| using Microsoft.Extensions.Logging; | ||||
| using Moq; | ||||
| using Ocelot.Configuration; | ||||
| using Ocelot.Configuration.Builder; | ||||
| using Ocelot.DownstreamRouteFinder; | ||||
| using Ocelot.DownstreamRouteFinder.Middleware; | ||||
| using Ocelot.DownstreamRouteFinder.UrlMatcher; | ||||
| using Ocelot.DownstreamUrlCreator; | ||||
| using Ocelot.DownstreamUrlCreator.Middleware; | ||||
| using Ocelot.DownstreamUrlCreator.UrlTemplateReplacer; | ||||
| using Ocelot.Infrastructure.RequestData; | ||||
| using Ocelot.Logging; | ||||
| using Ocelot.Responses; | ||||
| using Ocelot.Values; | ||||
| using TestStack.BDDfy; | ||||
| using Xunit; | ||||
|  | ||||
| @@ -23,21 +26,23 @@ namespace Ocelot.UnitTests.DownstreamUrlCreator | ||||
| { | ||||
|     public class DownstreamUrlCreatorMiddlewareTests : IDisposable | ||||
|     { | ||||
|         private readonly Mock<IDownstreamUrlPathPlaceholderReplacer> _downstreamUrlTemplateVariableReplacer; | ||||
|         private readonly Mock<IDownstreamPathPlaceholderReplacer> _downstreamUrlTemplateVariableReplacer; | ||||
|         private readonly Mock<IRequestScopedDataRepository> _scopedRepository; | ||||
|         private readonly Mock<IUrlBuilder> _urlBuilder; | ||||
|         private readonly string _url; | ||||
|         private readonly TestServer _server; | ||||
|         private readonly HttpClient _client; | ||||
|         private Response<DownstreamRoute> _downstreamRoute; | ||||
|         private HttpResponseMessage _result; | ||||
|         private OkResponse<DownstreamPath> _downstreamPath; | ||||
|         private OkResponse<DownstreamUrl> _downstreamUrl; | ||||
|  | ||||
|         public DownstreamUrlCreatorMiddlewareTests() | ||||
|         { | ||||
|             _url = "http://localhost:51879"; | ||||
|             _downstreamUrlTemplateVariableReplacer = new Mock<IDownstreamUrlPathPlaceholderReplacer>(); | ||||
|             _downstreamUrlTemplateVariableReplacer = new Mock<IDownstreamPathPlaceholderReplacer>(); | ||||
|             _scopedRepository = new Mock<IRequestScopedDataRepository>(); | ||||
|  | ||||
|             _urlBuilder = new Mock<IUrlBuilder>(); | ||||
|             var builder = new WebHostBuilder() | ||||
|               .ConfigureServices(x => | ||||
|               { | ||||
| @@ -45,6 +50,7 @@ namespace Ocelot.UnitTests.DownstreamUrlCreator | ||||
|                   x.AddLogging(); | ||||
|                   x.AddSingleton(_downstreamUrlTemplateVariableReplacer.Object); | ||||
|                   x.AddSingleton(_scopedRepository.Object); | ||||
|                   x.AddSingleton(_urlBuilder.Object); | ||||
|               }) | ||||
|               .UseUrls(_url) | ||||
|               .UseKestrel() | ||||
| @@ -61,21 +67,30 @@ namespace Ocelot.UnitTests.DownstreamUrlCreator | ||||
|         } | ||||
|  | ||||
|         [Fact] | ||||
|         public void should_call_scoped_data_repository_correctly() | ||||
|         public void should_call_dependencies_correctly() | ||||
|         { | ||||
|             this.Given(x => x.GivenTheDownStreamRouteIs(new DownstreamRoute(new List<UrlPathPlaceholderNameAndValue>(), new ReRouteBuilder().WithDownstreamTemplate("any old string").Build()))) | ||||
|                 .And(x => x.TheUrlReplacerReturns("any old string")) | ||||
|             this.Given(x => x.GivenTheDownStreamRouteIs(new DownstreamRoute(new List<UrlPathPlaceholderNameAndValue>(), new ReRouteBuilder().WithDownstreamPathTemplate("any old string").Build()))) | ||||
|                 .And(x => x.TheUrlReplacerReturns("/api/products/1")) | ||||
|                 .And(x => x.TheUrlBuilderReturns("http://www.bbc.co.uk/api/products/1")) | ||||
|                 .When(x => x.WhenICallTheMiddleware()) | ||||
|                 .Then(x => x.ThenTheScopedDataRepositoryIsCalledCorrectly()) | ||||
|                 .BDDfy(); | ||||
|         } | ||||
|  | ||||
|         private void TheUrlBuilderReturns(string dsUrl) | ||||
|         { | ||||
|             _downstreamUrl = new OkResponse<DownstreamUrl>(new DownstreamUrl(dsUrl)); | ||||
|             _urlBuilder | ||||
|                 .Setup(x => x.Build(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<HostAndPort>())) | ||||
|                 .Returns(_downstreamUrl); | ||||
|         } | ||||
|  | ||||
|         private void TheUrlReplacerReturns(string downstreamUrl) | ||||
|         { | ||||
|             _downstreamUrl = new OkResponse<DownstreamUrl>(new DownstreamUrl(downstreamUrl)); | ||||
|             _downstreamPath = new OkResponse<DownstreamPath>(new DownstreamPath(downstreamUrl)); | ||||
|             _downstreamUrlTemplateVariableReplacer | ||||
|                 .Setup(x => x.Replace(It.IsAny<string>(), It.IsAny<List<UrlPathPlaceholderNameAndValue>>())) | ||||
|                 .Returns(_downstreamUrl); | ||||
|                 .Setup(x => x.Replace(It.IsAny<DownstreamPathTemplate>(), It.IsAny<List<UrlPathPlaceholderNameAndValue>>())) | ||||
|                 .Returns(_downstreamPath); | ||||
|         } | ||||
|  | ||||
|         private void ThenTheScopedDataRepositoryIsCalledCorrectly() | ||||
|   | ||||
							
								
								
									
										124
									
								
								test/Ocelot.UnitTests/DownstreamUrlCreator/UrlBuilderTests.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										124
									
								
								test/Ocelot.UnitTests/DownstreamUrlCreator/UrlBuilderTests.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,124 @@ | ||||
| using System; | ||||
| using Ocelot.Configuration; | ||||
| using Ocelot.DownstreamUrlCreator; | ||||
| using Ocelot.DownstreamUrlCreator.UrlTemplateReplacer; | ||||
| using Ocelot.Responses; | ||||
| using Ocelot.Values; | ||||
| using Shouldly; | ||||
| using TestStack.BDDfy; | ||||
| using Xunit; | ||||
|  | ||||
| namespace Ocelot.UnitTests.DownstreamUrlCreator | ||||
| { | ||||
|     public class UrlBuilderTests | ||||
|     { | ||||
|         private readonly IUrlBuilder _urlBuilder; | ||||
|         private string _dsPath; | ||||
|         private string _dsScheme; | ||||
|         private string _dsHost; | ||||
|         private int _dsPort; | ||||
|  | ||||
|         private Response<DownstreamUrl> _result; | ||||
|  | ||||
|         public UrlBuilderTests() | ||||
|         { | ||||
|             _urlBuilder = new UrlBuilder(); | ||||
|         } | ||||
|  | ||||
|         [Fact] | ||||
|         public void should_return_error_when_downstream_path_is_null() | ||||
|         { | ||||
|             this.Given(x => x.GivenADownstreamPath(null)) | ||||
|                 .When(x => x.WhenIBuildTheUrl()) | ||||
|                 .Then(x => x.ThenThereIsAnErrorOfType<DownstreamPathNullOrEmptyError>()) | ||||
|                 .BDDfy(); | ||||
|         } | ||||
|  | ||||
|         [Fact] | ||||
|         public void should_return_error_when_downstream_scheme_is_null() | ||||
|         { | ||||
|             this.Given(x => x.GivenADownstreamScheme(null)) | ||||
|                 .And(x => x.GivenADownstreamPath("test")) | ||||
|                 .When(x => x.WhenIBuildTheUrl()) | ||||
|                 .Then(x => x.ThenThereIsAnErrorOfType<DownstreamSchemeNullOrEmptyError>()) | ||||
|                 .BDDfy(); | ||||
|         } | ||||
|  | ||||
|         [Fact] | ||||
|         public void should_return_error_when_downstream_host_is_null() | ||||
|         { | ||||
|             this.Given(x => x.GivenADownstreamScheme(null)) | ||||
|                 .And(x => x.GivenADownstreamPath("test")) | ||||
|                 .And(x => x.GivenADownstreamScheme("test")) | ||||
|                 .When(x => x.WhenIBuildTheUrl()) | ||||
|                 .Then(x => x.ThenThereIsAnErrorOfType<DownstreamHostNullOrEmptyError>()) | ||||
|                 .BDDfy(); | ||||
|         } | ||||
|  | ||||
|         [Fact] | ||||
|         public void should_not_use_port_if_zero() | ||||
|         { | ||||
|             this.Given(x => x.GivenADownstreamPath("/api/products/1")) | ||||
|            .And(x => x.GivenADownstreamScheme("http")) | ||||
|            .And(x => x.GivenADownstreamHost("127.0.0.1")) | ||||
|            .And(x => x.GivenADownstreamPort(0)) | ||||
|            .When(x => x.WhenIBuildTheUrl()) | ||||
|            .Then(x => x.ThenTheUrlIsReturned("http://127.0.0.1/api/products/1")) | ||||
|            .And(x => x.ThenTheUrlIsWellFormed()) | ||||
|            .BDDfy(); | ||||
|         } | ||||
|  | ||||
|         [Fact] | ||||
|         public void should_build_well_formed_uri() | ||||
|         { | ||||
|             this.Given(x => x.GivenADownstreamPath("/api/products/1")) | ||||
|                 .And(x => x.GivenADownstreamScheme("http")) | ||||
|                 .And(x => x.GivenADownstreamHost("127.0.0.1")) | ||||
|                 .And(x => x.GivenADownstreamPort(5000)) | ||||
|                 .When(x => x.WhenIBuildTheUrl()) | ||||
|                 .Then(x => x.ThenTheUrlIsReturned("http://127.0.0.1:5000/api/products/1")) | ||||
|                 .And(x => x.ThenTheUrlIsWellFormed()) | ||||
|                 .BDDfy(); | ||||
|         } | ||||
|  | ||||
|         private void ThenThereIsAnErrorOfType<T>() | ||||
|         { | ||||
|             _result.Errors[0].ShouldBeOfType<T>(); | ||||
|         } | ||||
|  | ||||
|         private void GivenADownstreamPath(string dsPath) | ||||
|         { | ||||
|             _dsPath = dsPath; | ||||
|         } | ||||
|  | ||||
|         private void GivenADownstreamScheme(string dsScheme) | ||||
|         { | ||||
|             _dsScheme = dsScheme; | ||||
|         } | ||||
|  | ||||
|         private void GivenADownstreamHost(string dsHost) | ||||
|         { | ||||
|             _dsHost = dsHost; | ||||
|         } | ||||
|  | ||||
|         private void GivenADownstreamPort(int dsPort) | ||||
|         { | ||||
|             _dsPort = dsPort; | ||||
|         } | ||||
|  | ||||
|         private void WhenIBuildTheUrl() | ||||
|         { | ||||
|             _result = _urlBuilder.Build(_dsPath, _dsScheme, new HostAndPort(_dsHost, _dsPort)); | ||||
|         } | ||||
|  | ||||
|         private void ThenTheUrlIsReturned(string expected) | ||||
|         { | ||||
|             _result.Data.Value.ShouldBe(expected); | ||||
|         } | ||||
|  | ||||
|         private void ThenTheUrlIsWellFormed() | ||||
|         { | ||||
|             Uri.IsWellFormedUriString(_result.Data.Value, UriKind.Absolute).ShouldBeTrue(); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -4,6 +4,7 @@ using Ocelot.DownstreamRouteFinder; | ||||
| using Ocelot.DownstreamRouteFinder.UrlMatcher; | ||||
| using Ocelot.DownstreamUrlCreator.UrlTemplateReplacer; | ||||
| using Ocelot.Responses; | ||||
| using Ocelot.Values; | ||||
| using Shouldly; | ||||
| using TestStack.BDDfy; | ||||
| using Xunit; | ||||
| @@ -13,12 +14,12 @@ namespace Ocelot.UnitTests.DownstreamUrlCreator.UrlTemplateReplacer | ||||
|     public class UpstreamUrlPathTemplateVariableReplacerTests | ||||
|     { | ||||
|         private DownstreamRoute _downstreamRoute; | ||||
|         private Response<DownstreamUrl> _result; | ||||
|         private readonly IDownstreamUrlPathPlaceholderReplacer _downstreamUrlPathReplacer; | ||||
|         private Response<DownstreamPath> _result; | ||||
|         private readonly IDownstreamPathPlaceholderReplacer _downstreamPathReplacer; | ||||
|  | ||||
|         public UpstreamUrlPathTemplateVariableReplacerTests() | ||||
|         { | ||||
|             _downstreamUrlPathReplacer = new DownstreamUrlPathPlaceholderReplacer(); | ||||
|             _downstreamPathReplacer = new DownstreamTemplatePathPlaceholderReplacer(); | ||||
|         } | ||||
|  | ||||
|         [Fact] | ||||
| @@ -33,7 +34,7 @@ namespace Ocelot.UnitTests.DownstreamUrlCreator.UrlTemplateReplacer | ||||
|         [Fact] | ||||
|         public void can_replace_no_template_variables_with_slash() | ||||
|         { | ||||
|             this.Given(x => x.GivenThereIsAUrlMatch(new DownstreamRoute(new List<UrlPathPlaceholderNameAndValue>(), new ReRouteBuilder().WithDownstreamTemplate("/").Build()))) | ||||
|             this.Given(x => x.GivenThereIsAUrlMatch(new DownstreamRoute(new List<UrlPathPlaceholderNameAndValue>(), new ReRouteBuilder().WithDownstreamPathTemplate("/").Build()))) | ||||
|                 .When(x => x.WhenIReplaceTheTemplateVariables()) | ||||
|                 .Then(x => x.ThenTheDownstreamUrlPathIsReturned("/")) | ||||
|                 .BDDfy(); | ||||
| @@ -42,7 +43,7 @@ namespace Ocelot.UnitTests.DownstreamUrlCreator.UrlTemplateReplacer | ||||
|         [Fact] | ||||
|         public void can_replace_url_no_slash() | ||||
|         { | ||||
|             this.Given(x => x.GivenThereIsAUrlMatch(new DownstreamRoute(new List<UrlPathPlaceholderNameAndValue>(), new ReRouteBuilder().WithDownstreamTemplate("api").Build()))) | ||||
|             this.Given(x => x.GivenThereIsAUrlMatch(new DownstreamRoute(new List<UrlPathPlaceholderNameAndValue>(), new ReRouteBuilder().WithDownstreamPathTemplate("api").Build()))) | ||||
|                 .When(x => x.WhenIReplaceTheTemplateVariables()) | ||||
|                 .Then(x => x.ThenTheDownstreamUrlPathIsReturned("api")) | ||||
|                 .BDDfy(); | ||||
| @@ -51,7 +52,7 @@ namespace Ocelot.UnitTests.DownstreamUrlCreator.UrlTemplateReplacer | ||||
|         [Fact] | ||||
|         public void can_replace_url_one_slash() | ||||
|         { | ||||
|             this.Given(x => x.GivenThereIsAUrlMatch(new DownstreamRoute(new List<UrlPathPlaceholderNameAndValue>(), new ReRouteBuilder().WithDownstreamTemplate("api/").Build()))) | ||||
|             this.Given(x => x.GivenThereIsAUrlMatch(new DownstreamRoute(new List<UrlPathPlaceholderNameAndValue>(), new ReRouteBuilder().WithDownstreamPathTemplate("api/").Build()))) | ||||
|                 .When(x => x.WhenIReplaceTheTemplateVariables()) | ||||
|                 .Then(x => x.ThenTheDownstreamUrlPathIsReturned("api/")) | ||||
|                 .BDDfy(); | ||||
| @@ -60,7 +61,7 @@ namespace Ocelot.UnitTests.DownstreamUrlCreator.UrlTemplateReplacer | ||||
|         [Fact] | ||||
|         public void can_replace_url_multiple_slash() | ||||
|         { | ||||
|             this.Given(x => x.GivenThereIsAUrlMatch(new DownstreamRoute(new List<UrlPathPlaceholderNameAndValue>(), new ReRouteBuilder().WithDownstreamTemplate("api/product/products/").Build()))) | ||||
|             this.Given(x => x.GivenThereIsAUrlMatch(new DownstreamRoute(new List<UrlPathPlaceholderNameAndValue>(), new ReRouteBuilder().WithDownstreamPathTemplate("api/product/products/").Build()))) | ||||
|                 .When(x => x.WhenIReplaceTheTemplateVariables()) | ||||
|                 .Then(x => x.ThenTheDownstreamUrlPathIsReturned("api/product/products/")) | ||||
|                 .BDDfy(); | ||||
| @@ -74,7 +75,7 @@ namespace Ocelot.UnitTests.DownstreamUrlCreator.UrlTemplateReplacer | ||||
|                 new UrlPathPlaceholderNameAndValue("{productId}", "1") | ||||
|             }; | ||||
|  | ||||
|             this.Given(x => x.GivenThereIsAUrlMatch(new DownstreamRoute(templateVariables, new ReRouteBuilder().WithDownstreamTemplate("productservice/products/{productId}/").Build()))) | ||||
|             this.Given(x => x.GivenThereIsAUrlMatch(new DownstreamRoute(templateVariables, new ReRouteBuilder().WithDownstreamPathTemplate("productservice/products/{productId}/").Build()))) | ||||
|              .When(x => x.WhenIReplaceTheTemplateVariables()) | ||||
|              .Then(x => x.ThenTheDownstreamUrlPathIsReturned("productservice/products/1/")) | ||||
|              .BDDfy(); | ||||
| @@ -88,7 +89,7 @@ namespace Ocelot.UnitTests.DownstreamUrlCreator.UrlTemplateReplacer | ||||
|                 new UrlPathPlaceholderNameAndValue("{productId}", "1") | ||||
|             }; | ||||
|  | ||||
|             this.Given(x => x.GivenThereIsAUrlMatch(new DownstreamRoute(templateVariables, new ReRouteBuilder().WithDownstreamTemplate("productservice/products/{productId}/variants").Build()))) | ||||
|             this.Given(x => x.GivenThereIsAUrlMatch(new DownstreamRoute(templateVariables, new ReRouteBuilder().WithDownstreamPathTemplate("productservice/products/{productId}/variants").Build()))) | ||||
|              .When(x => x.WhenIReplaceTheTemplateVariables()) | ||||
|              .Then(x => x.ThenTheDownstreamUrlPathIsReturned("productservice/products/1/variants")) | ||||
|              .BDDfy(); | ||||
| @@ -103,7 +104,7 @@ namespace Ocelot.UnitTests.DownstreamUrlCreator.UrlTemplateReplacer | ||||
|                 new UrlPathPlaceholderNameAndValue("{variantId}", "12") | ||||
|             }; | ||||
|  | ||||
|             this.Given(x => x.GivenThereIsAUrlMatch(new DownstreamRoute(templateVariables, new ReRouteBuilder().WithDownstreamTemplate("productservice/products/{productId}/variants/{variantId}").Build()))) | ||||
|             this.Given(x => x.GivenThereIsAUrlMatch(new DownstreamRoute(templateVariables, new ReRouteBuilder().WithDownstreamPathTemplate("productservice/products/{productId}/variants/{variantId}").Build()))) | ||||
|              .When(x => x.WhenIReplaceTheTemplateVariables()) | ||||
|              .Then(x => x.ThenTheDownstreamUrlPathIsReturned("productservice/products/1/variants/12")) | ||||
|              .BDDfy(); | ||||
| @@ -119,7 +120,7 @@ namespace Ocelot.UnitTests.DownstreamUrlCreator.UrlTemplateReplacer | ||||
|                 new UrlPathPlaceholderNameAndValue("{categoryId}", "34") | ||||
|             }; | ||||
|  | ||||
|             this.Given(x => x.GivenThereIsAUrlMatch(new DownstreamRoute(templateVariables, new ReRouteBuilder().WithDownstreamTemplate("productservice/category/{categoryId}/products/{productId}/variants/{variantId}").Build()))) | ||||
|             this.Given(x => x.GivenThereIsAUrlMatch(new DownstreamRoute(templateVariables, new ReRouteBuilder().WithDownstreamPathTemplate("productservice/category/{categoryId}/products/{productId}/variants/{variantId}").Build()))) | ||||
|              .When(x => x.WhenIReplaceTheTemplateVariables()) | ||||
|              .Then(x => x.ThenTheDownstreamUrlPathIsReturned("productservice/category/34/products/1/variants/12")) | ||||
|              .BDDfy(); | ||||
| @@ -132,7 +133,7 @@ namespace Ocelot.UnitTests.DownstreamUrlCreator.UrlTemplateReplacer | ||||
|  | ||||
|         private void WhenIReplaceTheTemplateVariables() | ||||
|         { | ||||
|             _result = _downstreamUrlPathReplacer.Replace(_downstreamRoute.ReRoute.DownstreamTemplate, _downstreamRoute.TemplatePlaceholderNameAndValues); | ||||
|             _result = _downstreamPathReplacer.Replace(_downstreamRoute.ReRoute.DownstreamPathTemplate, _downstreamRoute.TemplatePlaceholderNameAndValues); | ||||
|         } | ||||
|  | ||||
|         private void ThenTheDownstreamUrlPathIsReturned(string expected) | ||||
|   | ||||
| @@ -67,7 +67,7 @@ namespace Ocelot.UnitTests.Headers | ||||
|         { | ||||
|             var downstreamRoute = new DownstreamRoute(new List<UrlPathPlaceholderNameAndValue>(), | ||||
|                 new ReRouteBuilder() | ||||
|                     .WithDownstreamTemplate("any old string") | ||||
|                     .WithDownstreamPathTemplate("any old string") | ||||
|                     .WithClaimsToHeaders(new List<ClaimToThing> | ||||
|                     { | ||||
|                         new ClaimToThing("UserId", "Subject", "", 0) | ||||
|   | ||||
| @@ -65,7 +65,7 @@ namespace Ocelot.UnitTests.QueryStrings | ||||
|         { | ||||
|             var downstreamRoute = new DownstreamRoute(new List<UrlPathPlaceholderNameAndValue>(), | ||||
|                 new ReRouteBuilder() | ||||
|                     .WithDownstreamTemplate("any old string") | ||||
|                     .WithDownstreamPathTemplate("any old string") | ||||
|                     .WithClaimsToQueries(new List<ClaimToThing> | ||||
|                     { | ||||
|                         new ClaimToThing("UserId", "Subject", "", 0) | ||||
|   | ||||
| @@ -71,7 +71,7 @@ namespace Ocelot.UnitTests.RequestId | ||||
|         { | ||||
|             var downstreamRoute = new DownstreamRoute(new List<UrlPathPlaceholderNameAndValue>(), | ||||
|                 new ReRouteBuilder() | ||||
|                 .WithDownstreamTemplate("any old string") | ||||
|                 .WithDownstreamPathTemplate("any old string") | ||||
|                 .WithRequestIdKey("LSRequestId").Build()); | ||||
|  | ||||
|             var requestId = Guid.NewGuid().ToString(); | ||||
| @@ -88,7 +88,7 @@ namespace Ocelot.UnitTests.RequestId | ||||
|         { | ||||
|             var downstreamRoute = new DownstreamRoute(new List<UrlPathPlaceholderNameAndValue>(), | ||||
|                 new ReRouteBuilder() | ||||
|                 .WithDownstreamTemplate("any old string") | ||||
|                 .WithDownstreamPathTemplate("any old string") | ||||
|                 .WithRequestIdKey("LSRequestId").Build()); | ||||
|  | ||||
|             this.Given(x => x.GivenTheDownStreamRouteIs(downstreamRoute)) | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 TomPallister
					TomPallister