Skip to content

Commit

Permalink
#683 validate if there are duplicated placeholders in UpstreamPathTem…
Browse files Browse the repository at this point in the history
…plate
  • Loading branch information
jlukawska committed Dec 16, 2019
1 parent f15e3a9 commit caf5cf8
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using System.Threading.Tasks;

public class FileConfigurationFluentValidator : AbstractValidator<FileConfiguration>, IConfigurationValidator
Expand All @@ -35,6 +36,10 @@ public FileConfigurationFluentValidator(IServiceProvider provider, ReRouteFluent
.Must((config, reRoute) => HaveServiceDiscoveryProviderRegistered(reRoute, config.GlobalConfiguration.ServiceDiscoveryProvider))
.WithMessage((config, reRoute) => $"Unable to start Ocelot, errors are: Unable to start Ocelot because either a ReRoute or GlobalConfiguration are using ServiceDiscoveryOptions but no ServiceDiscoveryFinderDelegate has been registered in dependency injection container. Are you missing a package like Ocelot.Provider.Consul and services.AddConsul() or Ocelot.Provider.Eureka and services.AddEureka()?");

RuleForEach(configuration => configuration.ReRoutes)
.Must((config, reRoute) => IsPlaceholderNotDuplicatedIn(reRoute.UpstreamPathTemplate))
.WithMessage((config, reRoute) => $"{nameof(reRoute)} {reRoute.UpstreamPathTemplate} has duplicated placeholder");

RuleFor(configuration => configuration.GlobalConfiguration.ServiceDiscoveryProvider)
.Must(HaveServiceDiscoveryProviderRegistered)
.WithMessage((config, reRoute) => $"Unable to start Ocelot, errors are: Unable to start Ocelot because either a ReRoute or GlobalConfiguration are using ServiceDiscoveryOptions but no ServiceDiscoveryFinderDelegate has been registered in dependency injection container. Are you missing a package like Ocelot.Provider.Consul and services.AddConsul() or Ocelot.Provider.Eureka and services.AddEureka()?");
Expand Down Expand Up @@ -109,6 +114,14 @@ private bool AllReRoutesForAggregateExist(FileAggregateReRoute fileAggregateReRo
return reRoutesForAggregate.Count() == fileAggregateReRoute.ReRouteKeys.Count;
}

private bool IsPlaceholderNotDuplicatedIn(string upstreamPathTemplate)
{
Regex regExPlaceholder = new Regex("{[^}]+}");
var matches = regExPlaceholder.Matches(upstreamPathTemplate);
var upstreamPathPlaceholders = matches.Select(m => m.Value);
return upstreamPathPlaceholders.Count() == upstreamPathPlaceholders.Distinct().Count();
}

private static bool DoesNotContainReRoutesWithSpecificRequestIdKeys(FileAggregateReRoute fileAggregateReRoute,
List<FileReRoute> reRoutes)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1341,6 +1341,32 @@ public void configuration_is_not_valid_when_host_and_port_is_empty()
.BDDfy();
}

[Fact]
public void configuration_is_invalid_when_placeholder_is_used_twice_in_upstream_path_template()
{
this.Given(x => x.GivenAConfiguration(new FileConfiguration
{
ReRoutes = new List<FileReRoute>
{
new FileReRoute
{
DownstreamPathTemplate = "/bar/{everything}",
DownstreamScheme = "http",
DownstreamHostAndPorts = new List<FileHostAndPort>
{
new FileHostAndPort() { Host = "a.b.cd" },
},
UpstreamPathTemplate = "/foo/bar/{everything}/{everything}",
UpstreamHttpMethod = new List<string> { "Get" },
},
},
}))
.When(x => x.WhenIValidateTheConfiguration())
.Then(x => x.ThenTheResultIsNotValid())
.And(x => x.ThenTheErrorMessageAtPositionIs(0, "reRoute /foo/bar/{everything}/{everything} has duplicated placeholder"))
.BDDfy();
}

private void GivenAConfiguration(FileConfiguration fileConfiguration)
{
_fileConfiguration = fileConfiguration;
Expand Down

0 comments on commit caf5cf8

Please sign in to comment.