mirror of
				https://github.com/nsnail/Ocelot.git
				synced 2025-11-04 09:55:28 +08:00 
			
		
		
		
	#683 validate if there are duplicated placeholders in UpstreamPathTemplate
This commit is contained in:
		@@ -9,6 +9,7 @@
 | 
				
			|||||||
    using System;
 | 
					    using System;
 | 
				
			||||||
    using System.Collections.Generic;
 | 
					    using System.Collections.Generic;
 | 
				
			||||||
    using System.Linq;
 | 
					    using System.Linq;
 | 
				
			||||||
 | 
					    using System.Text.RegularExpressions;
 | 
				
			||||||
    using System.Threading.Tasks;
 | 
					    using System.Threading.Tasks;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public class FileConfigurationFluentValidator : AbstractValidator<FileConfiguration>, IConfigurationValidator
 | 
					    public class FileConfigurationFluentValidator : AbstractValidator<FileConfiguration>, IConfigurationValidator
 | 
				
			||||||
@@ -35,6 +36,10 @@
 | 
				
			|||||||
                .Must((config, reRoute) => HaveServiceDiscoveryProviderRegistered(reRoute, config.GlobalConfiguration.ServiceDiscoveryProvider))
 | 
					                .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()?");
 | 
					                .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)
 | 
					            RuleFor(configuration => configuration.GlobalConfiguration.ServiceDiscoveryProvider)
 | 
				
			||||||
                .Must(HaveServiceDiscoveryProviderRegistered)
 | 
					                .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()?");
 | 
					                .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;
 | 
					            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,
 | 
					        private static bool DoesNotContainReRoutesWithSpecificRequestIdKeys(FileAggregateReRoute fileAggregateReRoute,
 | 
				
			||||||
            List<FileReRoute> reRoutes)
 | 
					            List<FileReRoute> reRoutes)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1341,6 +1341,32 @@
 | 
				
			|||||||
                .BDDfy();
 | 
					                .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)
 | 
					        private void GivenAConfiguration(FileConfiguration fileConfiguration)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            _fileConfiguration = fileConfiguration;
 | 
					            _fileConfiguration = fileConfiguration;
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user