Skip to content

Commit

Permalink
split DownstreamTemplate into DownstreamPathTemplate, DownstreamSchem…
Browse files Browse the repository at this point in the history
…e, DownstreamHost and DownstreamPort in order to prepare for service discovery
  • Loading branch information
TomPallister committed Jan 21, 2017
1 parent 044b609 commit 0f71c04
Show file tree
Hide file tree
Showing 53 changed files with 767 additions and 258 deletions.
2 changes: 2 additions & 0 deletions Ocelot.sln
Original file line number Diff line number Diff line change
Expand Up @@ -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}"
Expand Down
11 changes: 7 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.

Expand Down
19 changes: 14 additions & 5 deletions configuration-explanation.txt
Original file line number Diff line number Diff line change
@@ -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",
Expand Down
18 changes: 13 additions & 5 deletions src/Ocelot/Configuration/Builder/ReRouteBuilder.cs
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -30,6 +31,7 @@ public class ReRouteBuilder
private string _serviceDiscoveryAddress;
private string _downstreamScheme;
private string _downstreamHost;
private int _dsPort;

public ReRouteBuilder()
{
Expand Down Expand Up @@ -72,9 +74,9 @@ public ReRouteBuilder WithUseServiceDiscovery(bool useServiceDiscovery)
return this;
}

public ReRouteBuilder WithDownstreamTemplate(string input)
public ReRouteBuilder WithDownstreamPathTemplate(string input)
{
_downstreamTemplate = input;
_downstreamPathTemplate = input;
return this;
}

Expand Down Expand Up @@ -184,11 +186,17 @@ public ReRouteBuilder WithCacheOptions(CacheOptions input)
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,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
using Ocelot.Configuration.Validator;
using Ocelot.Responses;
using Ocelot.Utilities;
using Ocelot.Values;

namespace Ocelot.Configuration.Creator
{
Expand Down Expand Up @@ -96,7 +97,7 @@ private ReRoute SetUpReRoute(FileReRoute reRoute, FileGlobalConfiguration global
&& !string.IsNullOrEmpty(globalConfiguration?.ServiceDiscoveryProvider?.Provider);


Func<string> downstreamHostFunc = () => { return reRoute.DownstreamHost; };
Func<HostAndPort> downstreamHostAndPortFunc = () => new HostAndPort(reRoute.DownstreamHost.Trim('/'), reRoute.DownstreamPort);

if (isAuthenticated)
{
Expand All @@ -109,22 +110,22 @@ private ReRoute SetUpReRoute(FileReRoute reRoute, FileGlobalConfiguration global
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)
Expand Down
3 changes: 2 additions & 1 deletion src/Ocelot/Configuration/File/FileReRoute.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ public FileReRoute()
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; }
Expand All @@ -28,5 +28,6 @@ public FileReRoute()
public string ServiceName { get; set; }
public string DownstreamScheme {get;set;}
public string DownstreamHost {get;set;}
public int DownstreamPort { get; set; }
}
}
13 changes: 7 additions & 6 deletions src/Ocelot/Configuration/ReRoute.cs
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -32,11 +33,11 @@ public ReRoute(string downstreamTemplate, string upstreamTemplate, string upstre
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; }
Expand All @@ -54,7 +55,7 @@ public ReRoute(string downstreamTemplate, string upstreamTemplate, string upstre
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;}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
using Ocelot.Errors;

namespace Ocelot.Configuration.Validator
{
public class DownstreamPathTemplateAlreadyUsedError : Error
{
public DownstreamPathTemplateAlreadyUsedError(string message) : base(message, OcelotErrorCode.DownstreampathTemplateAlreadyUsedError)
{
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
using Ocelot.Errors;

namespace Ocelot.Configuration.Validator
{
public class DownstreamPathTemplateContainsSchemeError : Error
{
public DownstreamPathTemplateContainsSchemeError(string message)
: base(message, OcelotErrorCode.DownstreamPathTemplateContainsSchemeError)
{
}
}
}

This file was deleted.

This file was deleted.

This file was deleted.

16 changes: 8 additions & 8 deletions src/Ocelot/Configuration/Validator/FileConfigurationValidator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ public Response<ConfigurationValidationResult> IsValid(FileConfiguration configu
return new OkResponse<ConfigurationValidationResult>(result);
}

result = CheckForReRoutesContainingDownstreamScheme(configuration);
result = CheckForReRoutesContainingDownstreamSchemeInDownstreamPathTemplate(configuration);

if (result.IsError)
{
Expand Down Expand Up @@ -70,25 +70,25 @@ private bool IsSupportedAuthenticationProvider(string provider)
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)
Expand All @@ -105,7 +105,7 @@ private ConfigurationValidationResult CheckForDupliateReRoutes(FileConfiguration
.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();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
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;
Expand Down Expand Up @@ -59,6 +60,7 @@ public static IServiceCollection AddOcelot(this IServiceCollection services)
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>();
Expand All @@ -69,7 +71,7 @@ public static IServiceCollection AddOcelot(this IServiceCollection services)
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>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ public async Task Invoke(HttpContext context)
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);

Expand Down
12 changes: 12 additions & 0 deletions src/Ocelot/DownstreamUrlCreator/DownstreamHostNullOrEmptyError.cs
Original file line number Diff line number Diff line change
@@ -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)
{
}
}
}
12 changes: 12 additions & 0 deletions src/Ocelot/DownstreamUrlCreator/DownstreamPathNullOrEmptyError.cs
Original file line number Diff line number Diff line change
@@ -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)
{
}
}
}
Loading

0 comments on commit 0f71c04

Please sign in to comment.