mirror of
				https://github.com/nsnail/Ocelot.git
				synced 2025-11-04 16:10:50 +08:00 
			
		
		
		
	#683 validate if there are duplicated placeholders in UpstreamPathTemplate
This commit is contained in:
		@@ -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
 | 
			
		||||
@@ -35,6 +36,10 @@
 | 
			
		||||
                .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()?");
 | 
			
		||||
@@ -109,6 +114,14 @@
 | 
			
		||||
            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)
 | 
			
		||||
        {
 | 
			
		||||
 
 | 
			
		||||
@@ -1341,6 +1341,32 @@
 | 
			
		||||
                .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;
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user