Merge pull request #18 from TomPallister/split-downstream-template-into-parts

Split downstream template into parts
This commit is contained in:
Tom Pallister 2017-01-21 10:21:46 +00:00 committed by GitHub
commit 3f71bd55d5
58 changed files with 1042 additions and 219 deletions

View File

@ -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}"

View File

@ -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.

View File

@ -7,6 +7,6 @@ build_script:
test_script:
- run-tests.bat
after_test:
- push-to-nuget.bat %appveyor_build_version%-rc1 %nugetApiKey%
- push-to-nuget.bat %appveyor_build_version% %nugetApiKey%
cache:
- '%USERPROFILE%\.nuget\packages'

View File

@ -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",

8
run-acceptance-tests.bat Executable file
View File

@ -0,0 +1,8 @@
echo Running Ocelot.AcceptanceTests
cd test/Ocelot.AcceptanceTests/
dotnet restore
dotnet test
cd ../../
echo Restoring Ocelot.ManualTest
dotnet restore test/Ocelot.ManualTest/

View File

@ -1,17 +1,2 @@
echo -------------------------
echo Restoring Ocelot
dotnet restore src/Ocelot
echo Restoring Ocelot.ManualTest
dotnet restore test/Ocelot.ManualTest/
echo Running Ocelot.UnitTests
dotnet restore test/Ocelot.UnitTests/
dotnet test test/Ocelot.UnitTests/
echo Running Ocelot.AcceptanceTests
cd test/Ocelot.AcceptanceTests/
dotnet restore
dotnet test
cd ../../
./run-unit-tests.bat
./run-acceptance-tests.bat

8
run-unit-tests.bat Executable file
View File

@ -0,0 +1,8 @@
echo -------------------------
echo Restoring Ocelot
dotnet restore src/Ocelot
echo Running Ocelot.UnitTests
dotnet restore test/Ocelot.UnitTests/
dotnet test test/Ocelot.UnitTests/

View File

@ -1,10 +1,12 @@
using System.Collections.Generic;
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;
@ -23,15 +25,58 @@ namespace Ocelot.Configuration.Builder
private string _requestIdHeaderKey;
private bool _isCached;
private CacheOptions _fileCacheOptions;
private bool _useServiceDiscovery;
private string _serviceName;
private string _serviceDiscoveryProvider;
private string _serviceDiscoveryAddress;
private string _downstreamScheme;
private string _downstreamHost;
private int _dsPort;
public ReRouteBuilder()
{
_additionalScopes = new List<string>();
}
public ReRouteBuilder WithDownstreamTemplate(string input)
public ReRouteBuilder WithDownstreamScheme(string downstreamScheme)
{
_downstreamTemplate = input;
_downstreamScheme = downstreamScheme;
return this;
}
public ReRouteBuilder WithDownstreamHost(string downstreamHost)
{
_downstreamHost = downstreamHost;
return this;
}
public ReRouteBuilder WithServiceDiscoveryAddress(string serviceDiscoveryAddress)
{
_serviceDiscoveryAddress = serviceDiscoveryAddress;
return this;
}
public ReRouteBuilder WithServiceDiscoveryProvider(string serviceDiscoveryProvider)
{
_serviceDiscoveryProvider = serviceDiscoveryProvider;
return this;
}
public ReRouteBuilder WithServiceName(string serviceName)
{
_serviceName = serviceName;
return this;
}
public ReRouteBuilder WithUseServiceDiscovery(bool useServiceDiscovery)
{
_useServiceDiscovery = useServiceDiscovery;
return this;
}
public ReRouteBuilder WithDownstreamPathTemplate(string input)
{
_downstreamPathTemplate = input;
return this;
}
@ -141,12 +186,21 @@ namespace Ocelot.Configuration.Builder
return this;
}
public ReRouteBuilder WithDownstreamPort(int port)
{
_dsPort = port;
return this;
}
public ReRoute Build()
{
return new ReRoute(_downstreamTemplate, _upstreamTemplate, _upstreamHttpMethod, _upstreamTemplatePattern,
Func<HostAndPort> downstreamHostFunc = () => new HostAndPort(_downstreamHost, _dsPort);
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);
_isAuthorised, _claimToQueries, _requestIdHeaderKey, _isCached, _fileCacheOptions, _serviceName,
_useServiceDiscovery, _serviceDiscoveryAddress, _serviceDiscoveryProvider, downstreamHostFunc, _downstreamScheme);
}
}
}

View File

@ -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
{
@ -91,6 +92,13 @@ namespace Ocelot.Configuration.Creator
? globalConfiguration.RequestIdKey
: reRoute.RequestIdKey;
var useServiceDiscovery = !string.IsNullOrEmpty(reRoute.ServiceName)
&& !string.IsNullOrEmpty(globalConfiguration?.ServiceDiscoveryProvider?.Address)
&& !string.IsNullOrEmpty(globalConfiguration?.ServiceDiscoveryProvider?.Provider);
Func<HostAndPort> downstreamHostAndPortFunc = () => new HostAndPort(reRoute.DownstreamHost.Trim('/'), reRoute.DownstreamPort);
if (isAuthenticated)
{
var authOptionsForRoute = new AuthenticationOptions(reRoute.AuthenticationOptions.Provider,
@ -102,18 +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));
requestIdKey, isCached, new CacheOptions(reRoute.FileCacheOptions.TtlSeconds),
reRoute.ServiceName, useServiceDiscovery, globalConfiguration?.ServiceDiscoveryProvider?.Provider,
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));
requestIdKey, isCached, new CacheOptions(reRoute.FileCacheOptions.TtlSeconds),
reRoute.ServiceName, useServiceDiscovery, globalConfiguration?.ServiceDiscoveryProvider?.Provider,
globalConfiguration?.ServiceDiscoveryProvider?.Address, downstreamHostAndPortFunc, reRoute.DownstreamScheme);
}
private string BuildUpstreamTemplate(FileReRoute reRoute)

View File

@ -2,6 +2,11 @@
{
public class FileGlobalConfiguration
{
public FileGlobalConfiguration()
{
ServiceDiscoveryProvider = new FileServiceDiscoveryProvider();
}
public string RequestIdKey { get; set; }
public FileServiceDiscoveryProvider ServiceDiscoveryProvider {get;set;}
}
}

View File

@ -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; }
@ -25,5 +25,9 @@ namespace Ocelot.Configuration.File
public string RequestIdKey { get; set; }
public FileCacheOptions FileCacheOptions { get; set; }
public bool ReRouteIsCaseSensitive { get; set; }
public string ServiceName { get; set; }
public string DownstreamScheme {get;set;}
public string DownstreamHost {get;set;}
public int DownstreamPort { get; set; }
}
}

View File

@ -0,0 +1,8 @@
namespace Ocelot.Configuration.File
{
public class FileServiceDiscoveryProvider
{
public string Provider {get;set;}
public string Address {get;set;}
}
}

View File

@ -1,15 +1,18 @@
using System.Collections.Generic;
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 requestIdKey, bool isCached, CacheOptions fileCacheOptions, string serviceName, bool useServiceDiscovery,
string serviceDiscoveryProvider, string serviceDiscoveryAddress, Func<HostAndPort> downstreamHostAndPort, string downstreamScheme)
{
DownstreamTemplate = downstreamTemplate;
DownstreamPathTemplate = downstreamPathTemplate;
UpstreamTemplate = upstreamTemplate;
UpstreamHttpMethod = upstreamHttpMethod;
UpstreamTemplatePattern = upstreamTemplatePattern;
@ -26,9 +29,15 @@ namespace Ocelot.Configuration
?? new List<ClaimToThing>();
ClaimsToHeaders = configurationHeaderExtractorProperties
?? new List<ClaimToThing>();
ServiceName = serviceName;
UseServiceDiscovery = useServiceDiscovery;
ServiceDiscoveryProvider = serviceDiscoveryProvider;
ServiceDiscoveryAddress = serviceDiscoveryAddress;
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; }
@ -42,5 +51,11 @@ namespace Ocelot.Configuration
public string RequestIdKey { get; private set; }
public bool IsCached { get; private set; }
public CacheOptions FileCacheOptions { get; private set; }
public string ServiceName { get; private set;}
public bool UseServiceDiscovery { get; private set;}
public string ServiceDiscoveryProvider { get; private set;}
public string ServiceDiscoveryAddress { get; private set;}
public Func<HostAndPort> DownstreamHostAndPort {get;private set;}
public string DownstreamScheme {get;private set;}
}
}

View File

@ -0,0 +1,11 @@
using Ocelot.Errors;
namespace Ocelot.Configuration.Validator
{
public class DownstreamPathTemplateAlreadyUsedError : Error
{
public DownstreamPathTemplateAlreadyUsedError(string message) : base(message, OcelotErrorCode.DownstreampathTemplateAlreadyUsedError)
{
}
}
}

View File

@ -0,0 +1,12 @@
using Ocelot.Errors;
namespace Ocelot.Configuration.Validator
{
public class DownstreamPathTemplateContainsSchemeError : Error
{
public DownstreamPathTemplateContainsSchemeError(string message)
: base(message, OcelotErrorCode.DownstreamPathTemplateContainsSchemeError)
{
}
}
}

View File

@ -1,11 +0,0 @@
using Ocelot.Errors;
namespace Ocelot.Configuration.Validator
{
public class DownstreamTemplateAlreadyUsedError : Error
{
public DownstreamTemplateAlreadyUsedError(string message) : base(message, OcelotErrorCode.DownstreamTemplateAlreadyUsedError)
{
}
}
}

View File

@ -26,6 +26,13 @@ namespace Ocelot.Configuration.Validator
return new OkResponse<ConfigurationValidationResult>(result);
}
result = CheckForReRoutesContainingDownstreamSchemeInDownstreamPathTemplate(configuration);
if (result.IsError)
{
return new OkResponse<ConfigurationValidationResult>(result);
}
return new OkResponse<ConfigurationValidationResult>(result);
}
@ -63,6 +70,27 @@ namespace Ocelot.Configuration.Validator
return Enum.TryParse(provider, true, out supportedProvider);
}
private ConfigurationValidationResult CheckForReRoutesContainingDownstreamSchemeInDownstreamPathTemplate(FileConfiguration configuration)
{
var errors = new List<Error>();
foreach(var reRoute in configuration.ReRoutes)
{
if(reRoute.DownstreamPathTemplate.Contains("https://")
|| reRoute.DownstreamPathTemplate.Contains("http://"))
{
errors.Add(new DownstreamPathTemplateContainsSchemeError($"{reRoute.DownstreamPathTemplate} contains scheme"));
}
}
if(errors.Any())
{
return new ConfigurationValidationResult(true, errors);
}
return new ConfigurationValidationResult(false, errors);
}
private ConfigurationValidationResult CheckForDupliateReRoutes(FileConfiguration configuration)
{
var hasDupes = configuration.ReRoutes
@ -77,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();

View File

@ -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>();

View File

@ -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);

View File

@ -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)
{
}
}
}

View File

@ -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)
{
}
}
}

View File

@ -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)
{
}
}
}

View 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);
}
}

View File

@ -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");

View 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));
}
}
}

View File

@ -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()));
}
}
}

View File

@ -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);
}
}

View File

@ -4,7 +4,7 @@
{
UnauthenticatedError,
UnknownError,
DownstreamTemplateAlreadyUsedError,
DownstreampathTemplateAlreadyUsedError,
UnableToFindDownstreamRouteError,
CannotAddDataError,
CannotFindDataError,
@ -17,6 +17,10 @@
InstructionNotForClaimsError,
UnauthorizedError,
ClaimValueNotAuthorisedError,
UserDoesNotHaveClaimError
UserDoesNotHaveClaimError,
DownstreamPathTemplateContainsSchemeError,
DownstreamPathNullOrEmptyError,
DownstreamSchemeNullOrEmptyError,
DownstreamHostNullOrEmptyError
}
}

View File

@ -0,0 +1,12 @@
namespace Ocelot.Values
{
public class DownstreamPath
{
public DownstreamPath(string value)
{
Value = value;
}
public string Value { get; private set; }
}
}

View File

@ -0,0 +1,12 @@
namespace Ocelot.Values
{
public class DownstreamPathTemplate
{
public DownstreamPathTemplate(string value)
{
Value = value;
}
public string Value { get; private set; }
}
}

View File

@ -1,4 +1,4 @@
namespace Ocelot.DownstreamUrlCreator.UrlTemplateReplacer
namespace Ocelot.Values
{
public class DownstreamUrl
{

View 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; }
}
}

View File

@ -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())

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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",
}

View File

@ -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",
}

View File

@ -29,7 +29,7 @@ namespace Ocelot.AcceptanceTests
{
new FileReRoute
{
DownstreamTemplate = "http://localhost:53876/",
DownstreamPathTemplate = "http://localhost:53876/",
UpstreamTemplate = "/",
UpstreamHttpMethod = "Get"
}

View File

@ -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",
}
}

View File

@ -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}}}

View File

@ -10,7 +10,6 @@ namespace Ocelot.ManualTest
var host = new WebHostBuilder()
.UseKestrel()
.UseContentRoot(Directory.GetCurrentDirectory())
.UseIISIntegration()
.UseStartup<Startup>()
.Build();

View File

@ -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 }

View File

@ -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)

View File

@ -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()
@ -20,15 +20,34 @@ namespace Ocelot.UnitTests.Configuration
}
[Fact]
public void configuration_is_valid_with_one_reroute()
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",
DownstreamPathTemplate = "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_valid_with_one_reroute()
{
this.Given(x => x.GivenAConfiguration(new FileConfiguration
{
ReRoutes = new List<FileReRoute>
{
new FileReRoute
{
DownstreamPathTemplate = "/api/products/",
UpstreamTemplate = "http://asdf.com"
}
}
@ -41,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 = "http://www.bbc.co.uk",
DownstreamPathTemplate = "/api/products/",
UpstreamTemplate = "http://asdf.com",
AuthenticationOptions = new FileAuthenticationOptions
{
@ -64,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 = "http://www.bbc.co.uk",
DownstreamPathTemplate = "/api/products/",
UpstreamTemplate = "http://asdf.com",
AuthenticationOptions = new FileAuthenticationOptions
{
@ -88,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 = "http://www.bbc.co.uk",
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();
}

View File

@ -35,6 +35,143 @@ namespace Ocelot.UnitTests.Configuration
_fileConfig.Object, _validator.Object, _configParser.Object, _logger.Object);
}
[Fact]
public void should_use_downstream_host()
{
this.Given(x => x.GivenTheConfigIs(new FileConfiguration
{
ReRoutes = new List<FileReRoute>
{
new FileReRoute
{
DownstreamHost = "127.0.0.1",
UpstreamTemplate = "/api/products/{productId}",
DownstreamPathTemplate = "/products/{productId}",
UpstreamHttpMethod = "Get",
}
},
}))
.And(x => x.GivenTheConfigIsValid())
.When(x => x.WhenICreateTheConfig())
.Then(x => x.ThenTheReRoutesAre(new List<ReRoute>
{
new ReRouteBuilder()
.WithDownstreamHost("127.0.0.1")
.WithDownstreamPathTemplate("/products/{productId}")
.WithUpstreamTemplate("/api/products/{productId}")
.WithUpstreamHttpMethod("Get")
.WithUpstreamTemplatePattern("(?i)/api/products/.*/$")
.Build()
}))
.BDDfy();
}
public void should_use_downstream_scheme()
{
this.Given(x => x.GivenTheConfigIs(new FileConfiguration
{
ReRoutes = new List<FileReRoute>
{
new FileReRoute
{
DownstreamScheme = "https",
UpstreamTemplate = "/api/products/{productId}",
DownstreamPathTemplate = "/products/{productId}",
UpstreamHttpMethod = "Get",
}
},
}))
.And(x => x.GivenTheConfigIsValid())
.When(x => x.WhenICreateTheConfig())
.Then(x => x.ThenTheReRoutesAre(new List<ReRoute>
{
new ReRouteBuilder()
.WithDownstreamScheme("https")
.WithDownstreamPathTemplate("/products/{productId}")
.WithUpstreamTemplate("/api/products/{productId}")
.WithUpstreamHttpMethod("Get")
.WithUpstreamTemplatePattern("(?i)/api/products/.*/$")
.Build()
}))
.BDDfy();
}
[Fact]
public void should_use_service_discovery_for_downstream_service_host()
{
this.Given(x => x.GivenTheConfigIs(new FileConfiguration
{
ReRoutes = new List<FileReRoute>
{
new FileReRoute
{
UpstreamTemplate = "/api/products/{productId}",
DownstreamPathTemplate = "/products/{productId}",
UpstreamHttpMethod = "Get",
ReRouteIsCaseSensitive = false,
ServiceName = "ProductService"
}
},
GlobalConfiguration = new FileGlobalConfiguration
{
ServiceDiscoveryProvider = new FileServiceDiscoveryProvider
{
Provider = "consul",
Address = "127.0.0.1"
}
}
}))
.And(x => x.GivenTheConfigIsValid())
.When(x => x.WhenICreateTheConfig())
.Then(x => x.ThenTheReRoutesAre(new List<ReRoute>
{
new ReRouteBuilder()
.WithDownstreamPathTemplate("/products/{productId}")
.WithUpstreamTemplate("/api/products/{productId}")
.WithUpstreamHttpMethod("Get")
.WithUpstreamTemplatePattern("(?i)/api/products/.*/$")
.WithServiceName("ProductService")
.WithUseServiceDiscovery(true)
.WithServiceDiscoveryProvider("consul")
.WithServiceDiscoveryAddress("127.0.01")
.Build()
}))
.BDDfy();
}
[Fact]
public void should_not_use_service_discovery_for_downstream_host_url_when_no_service_name()
{
this.Given(x => x.GivenTheConfigIs(new FileConfiguration
{
ReRoutes = new List<FileReRoute>
{
new FileReRoute
{
UpstreamTemplate = "/api/products/{productId}",
DownstreamPathTemplate = "/products/{productId}",
UpstreamHttpMethod = "Get",
ReRouteIsCaseSensitive = false,
}
}
}))
.And(x => x.GivenTheConfigIsValid())
.When(x => x.WhenICreateTheConfig())
.Then(x => x.ThenTheReRoutesAre(new List<ReRoute>
{
new ReRouteBuilder()
.WithDownstreamPathTemplate("/products/{productId}")
.WithUpstreamTemplate("/api/products/{productId}")
.WithUpstreamHttpMethod("Get")
.WithUpstreamTemplatePattern("(?i)/api/products/.*/$")
.WithUseServiceDiscovery(false)
.WithServiceDiscoveryProvider(null)
.WithServiceDiscoveryAddress(null)
.Build()
}))
.BDDfy();
}
[Fact]
public void should_use_reroute_case_sensitivity_value()
{
@ -45,7 +182,7 @@ namespace Ocelot.UnitTests.Configuration
new FileReRoute
{
UpstreamTemplate = "/api/products/{productId}",
DownstreamTemplate = "/products/{productId}",
DownstreamPathTemplate = "/products/{productId}",
UpstreamHttpMethod = "Get",
ReRouteIsCaseSensitive = false
}
@ -56,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/.*/$")
@ -75,7 +212,7 @@ namespace Ocelot.UnitTests.Configuration
new FileReRoute
{
UpstreamTemplate = "/api/products/{productId}",
DownstreamTemplate = "/products/{productId}",
DownstreamPathTemplate = "/products/{productId}",
UpstreamHttpMethod = "Get"
}
}
@ -85,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/.*/$")
@ -104,7 +241,7 @@ namespace Ocelot.UnitTests.Configuration
new FileReRoute
{
UpstreamTemplate = "/api/products/{productId}",
DownstreamTemplate = "/products/{productId}",
DownstreamPathTemplate = "/products/{productId}",
UpstreamHttpMethod = "Get",
ReRouteIsCaseSensitive = true
}
@ -115,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/.*/$")
@ -134,7 +271,7 @@ namespace Ocelot.UnitTests.Configuration
new FileReRoute
{
UpstreamTemplate = "/api/products/{productId}",
DownstreamTemplate = "/products/{productId}",
DownstreamPathTemplate = "/products/{productId}",
UpstreamHttpMethod = "Get",
ReRouteIsCaseSensitive = true
}
@ -149,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/.*/$")
@ -169,7 +306,7 @@ namespace Ocelot.UnitTests.Configuration
new FileReRoute
{
UpstreamTemplate = "/api/products/{productId}",
DownstreamTemplate = "/products/{productId}",
DownstreamPathTemplate = "/products/{productId}",
UpstreamHttpMethod = "Get",
ReRouteIsCaseSensitive = true
}
@ -180,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/.*/$")
@ -195,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/.*/$")
@ -218,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
@ -258,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/.*/$")
@ -277,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
@ -309,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
}
@ -320,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/.*/$")
@ -339,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
}
@ -350,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/.*/$")
@ -369,7 +506,7 @@ namespace Ocelot.UnitTests.Configuration
new FileReRoute
{
UpstreamTemplate = "/",
DownstreamTemplate = "/api/products/",
DownstreamPathTemplate = "/api/products/",
UpstreamHttpMethod = "Get",
ReRouteIsCaseSensitive = true
}
@ -380,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("/$")
@ -416,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);

View File

@ -1,7 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Collections.Generic;
using Moq;
using Ocelot.Configuration;
using Ocelot.Configuration.Creator;

View File

@ -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()
};
}
}

View File

@ -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();

View File

@ -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++)
{

View File

@ -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()

View 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();
}
}
}

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -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))