mirror of
				https://github.com/nsnail/Ocelot.git
				synced 2025-11-04 19:00:48 +08:00 
			
		
		
		
	Feature/issue 209 upstream host based routing (#216)
* from messing around at lunch...initial hacking seems to sort of work..need to think of all the test scenarios * drunken train hacking * docs for upstreamhost
This commit is contained in:
		@@ -269,6 +269,46 @@ namespace Ocelot.UnitTests.Configuration
 | 
			
		||||
                .BDDfy();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Fact]
 | 
			
		||||
        public void configuration_is_valid_with_duplicate_reroutes_all_verbs_but_different_hosts()
 | 
			
		||||
        {
 | 
			
		||||
            this.Given(x => x.GivenAConfiguration(new FileConfiguration
 | 
			
		||||
                {
 | 
			
		||||
                    ReRoutes = new List<FileReRoute>
 | 
			
		||||
                    {
 | 
			
		||||
                        new FileReRoute
 | 
			
		||||
                        {
 | 
			
		||||
                            DownstreamPathTemplate = "/api/products/",
 | 
			
		||||
                            UpstreamPathTemplate = "/asdf/",
 | 
			
		||||
                            DownstreamHostAndPorts = new List<FileHostAndPort>
 | 
			
		||||
                            {
 | 
			
		||||
                                new FileHostAndPort
 | 
			
		||||
                                {
 | 
			
		||||
                                    Host = "bb.co.uk"
 | 
			
		||||
                                }
 | 
			
		||||
                            },
 | 
			
		||||
                            UpstreamHost = "host1"
 | 
			
		||||
                        },
 | 
			
		||||
                        new FileReRoute
 | 
			
		||||
                        {
 | 
			
		||||
                            DownstreamPathTemplate = "/www/test/",
 | 
			
		||||
                            UpstreamPathTemplate = "/asdf/",
 | 
			
		||||
                            DownstreamHostAndPorts = new List<FileHostAndPort>
 | 
			
		||||
                            {
 | 
			
		||||
                                new FileHostAndPort
 | 
			
		||||
                                {
 | 
			
		||||
                                    Host = "bb.co.uk"
 | 
			
		||||
                                }
 | 
			
		||||
                            },
 | 
			
		||||
                            UpstreamHost = "host1"
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                }))
 | 
			
		||||
                .When(x => x.WhenIValidateTheConfiguration())
 | 
			
		||||
                .Then(x => x.ThenTheResultIsValid())
 | 
			
		||||
                .BDDfy();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Fact]
 | 
			
		||||
        public void configuration_is_not_valid_with_duplicate_reroutes_specific_verbs()
 | 
			
		||||
        {
 | 
			
		||||
 
 | 
			
		||||
@@ -75,7 +75,7 @@
 | 
			
		||||
        {
 | 
			
		||||
            _downstreamRoute = new OkResponse<DownstreamRoute>(downstreamRoute);
 | 
			
		||||
            _downstreamRouteFinder
 | 
			
		||||
                .Setup(x => x.FindDownstreamRoute(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<IOcelotConfiguration>()))
 | 
			
		||||
                .Setup(x => x.FindDownstreamRoute(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<IOcelotConfiguration>(), It.IsAny<string>()))
 | 
			
		||||
                .Returns(_downstreamRoute);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -26,6 +26,7 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
 | 
			
		||||
        private OcelotConfiguration _config;
 | 
			
		||||
        private Response<UrlMatch> _match;
 | 
			
		||||
        private string _upstreamHttpMethod;
 | 
			
		||||
        private string _upstreamHost;
 | 
			
		||||
 | 
			
		||||
        public DownstreamRouteFinderTests()
 | 
			
		||||
        {
 | 
			
		||||
@@ -210,7 +211,6 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
 | 
			
		||||
                            .WithUpstreamTemplatePattern(new UpstreamPathTemplate("someUpstreamPath", 1))
 | 
			
		||||
                            .Build()
 | 
			
		||||
                        )))
 | 
			
		||||
                .And(x => x.ThenTheUrlMatcherIsNotCalled())
 | 
			
		||||
                .BDDfy();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@@ -370,12 +370,161 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
 | 
			
		||||
                .And(x => x.GivenTheUrlMatcherReturns(new OkResponse<UrlMatch>(new UrlMatch(true))))
 | 
			
		||||
                .And(x => x.GivenTheUpstreamHttpMethodIs("Post"))
 | 
			
		||||
                .When(x => x.WhenICallTheFinder())
 | 
			
		||||
                 .Then(
 | 
			
		||||
                     x => x.ThenAnErrorResponseIsReturned())
 | 
			
		||||
                 .Then(x => x.ThenAnErrorResponseIsReturned())
 | 
			
		||||
                 .And(x => x.ThenTheUrlMatcherIsNotCalled())
 | 
			
		||||
                 .BDDfy();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Fact]
 | 
			
		||||
        public void should_return_route_when_host_matches()
 | 
			
		||||
        {
 | 
			
		||||
            var serviceProviderConfig = new ServiceProviderConfigurationBuilder().Build();
 | 
			
		||||
 | 
			
		||||
            this.Given(x => x.GivenThereIsAnUpstreamUrlPath("matchInUrlMatcher/"))
 | 
			
		||||
                .And(x => GivenTheUpstreamHostIs("MATCH"))
 | 
			
		||||
                .And(x => x.GivenTheTemplateVariableAndNameFinderReturns(
 | 
			
		||||
                    new OkResponse<List<PlaceholderNameAndValue>>(
 | 
			
		||||
                        new List<PlaceholderNameAndValue>())))
 | 
			
		||||
                .And(x => x.GivenTheConfigurationIs(new List<ReRoute>
 | 
			
		||||
                    {
 | 
			
		||||
                        new ReRouteBuilder()
 | 
			
		||||
                            .WithDownstreamPathTemplate("someDownstreamPath")
 | 
			
		||||
                            .WithUpstreamPathTemplate("someUpstreamPath")
 | 
			
		||||
                            .WithUpstreamHttpMethod(new List<string> { "Get" })
 | 
			
		||||
                            .WithUpstreamTemplatePattern(new UpstreamPathTemplate("someUpstreamPath", 1))
 | 
			
		||||
                            .WithUpstreamHost("MATCH")
 | 
			
		||||
                            .Build()
 | 
			
		||||
                    }, string.Empty, serviceProviderConfig
 | 
			
		||||
                ))
 | 
			
		||||
                .And(x => x.GivenTheUrlMatcherReturns(new OkResponse<UrlMatch>(new UrlMatch(true))))
 | 
			
		||||
                .And(x => x.GivenTheUpstreamHttpMethodIs("Get"))
 | 
			
		||||
                .When(x => x.WhenICallTheFinder())
 | 
			
		||||
                .Then(
 | 
			
		||||
                    x => x.ThenTheFollowingIsReturned(new DownstreamRoute(
 | 
			
		||||
                        new List<PlaceholderNameAndValue>(),
 | 
			
		||||
                        new ReRouteBuilder()
 | 
			
		||||
                            .WithDownstreamPathTemplate("someDownstreamPath")
 | 
			
		||||
                            .WithUpstreamHttpMethod(new List<string> { "Get" })
 | 
			
		||||
                            .WithUpstreamTemplatePattern(new UpstreamPathTemplate("someUpstreamPath", 1))
 | 
			
		||||
                            .Build()
 | 
			
		||||
                    )))
 | 
			
		||||
                .And(x => x.ThenTheUrlMatcherIsCalledCorrectly())
 | 
			
		||||
                .BDDfy();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Fact]
 | 
			
		||||
        public void should_return_route_when_upstreamhost_is_null()
 | 
			
		||||
        {
 | 
			
		||||
            var serviceProviderConfig = new ServiceProviderConfigurationBuilder().Build();
 | 
			
		||||
 | 
			
		||||
            this.Given(x => x.GivenThereIsAnUpstreamUrlPath("matchInUrlMatcher/"))
 | 
			
		||||
                .And(x => GivenTheUpstreamHostIs("MATCH"))
 | 
			
		||||
                .And(x => x.GivenTheTemplateVariableAndNameFinderReturns(
 | 
			
		||||
                    new OkResponse<List<PlaceholderNameAndValue>>(
 | 
			
		||||
                        new List<PlaceholderNameAndValue>())))
 | 
			
		||||
                .And(x => x.GivenTheConfigurationIs(new List<ReRoute>
 | 
			
		||||
                    {
 | 
			
		||||
                        new ReRouteBuilder()
 | 
			
		||||
                            .WithDownstreamPathTemplate("someDownstreamPath")
 | 
			
		||||
                            .WithUpstreamPathTemplate("someUpstreamPath")
 | 
			
		||||
                            .WithUpstreamHttpMethod(new List<string> { "Get" })
 | 
			
		||||
                            .WithUpstreamTemplatePattern(new UpstreamPathTemplate("someUpstreamPath", 1))
 | 
			
		||||
                            .Build()
 | 
			
		||||
                    }, string.Empty, serviceProviderConfig
 | 
			
		||||
                ))
 | 
			
		||||
                .And(x => x.GivenTheUrlMatcherReturns(new OkResponse<UrlMatch>(new UrlMatch(true))))
 | 
			
		||||
                .And(x => x.GivenTheUpstreamHttpMethodIs("Get"))
 | 
			
		||||
                .When(x => x.WhenICallTheFinder())
 | 
			
		||||
                .Then(
 | 
			
		||||
                    x => x.ThenTheFollowingIsReturned(new DownstreamRoute(
 | 
			
		||||
                        new List<PlaceholderNameAndValue>(),
 | 
			
		||||
                        new ReRouteBuilder()
 | 
			
		||||
                            .WithDownstreamPathTemplate("someDownstreamPath")
 | 
			
		||||
                            .WithUpstreamHttpMethod(new List<string> { "Get" })
 | 
			
		||||
                            .WithUpstreamTemplatePattern(new UpstreamPathTemplate("someUpstreamPath", 1))
 | 
			
		||||
                            .Build()
 | 
			
		||||
                    )))
 | 
			
		||||
                .And(x => x.ThenTheUrlMatcherIsCalledCorrectly())
 | 
			
		||||
                .BDDfy();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Fact]
 | 
			
		||||
        public void should_not_return_route_when_host_doesnt_match()
 | 
			
		||||
        {
 | 
			
		||||
            var serviceProviderConfig = new ServiceProviderConfigurationBuilder().Build();
 | 
			
		||||
 | 
			
		||||
            this.Given(x => x.GivenThereIsAnUpstreamUrlPath("matchInUrlMatcher/"))
 | 
			
		||||
                .And(x => GivenTheUpstreamHostIs("DONTMATCH"))
 | 
			
		||||
                .And(x => x.GivenTheTemplateVariableAndNameFinderReturns(new OkResponse<List<PlaceholderNameAndValue>>(new List<PlaceholderNameAndValue>())))
 | 
			
		||||
                .And(x => x.GivenTheConfigurationIs(new List<ReRoute>
 | 
			
		||||
                    {
 | 
			
		||||
                        new ReRouteBuilder()
 | 
			
		||||
                            .WithDownstreamPathTemplate("someDownstreamPath")
 | 
			
		||||
                            .WithUpstreamPathTemplate("someUpstreamPath")
 | 
			
		||||
                            .WithUpstreamHttpMethod(new List<string> { "Get" })
 | 
			
		||||
                            .WithUpstreamTemplatePattern(new UpstreamPathTemplate("someUpstreamPath", 1))
 | 
			
		||||
                            .WithUpstreamHost("MATCH")
 | 
			
		||||
 | 
			
		||||
                            .Build()
 | 
			
		||||
                    }, string.Empty, serviceProviderConfig
 | 
			
		||||
                ))
 | 
			
		||||
                .And(x => x.GivenTheUrlMatcherReturns(new OkResponse<UrlMatch>(new UrlMatch(true))))
 | 
			
		||||
                .And(x => x.GivenTheUpstreamHttpMethodIs("Get"))
 | 
			
		||||
                .When(x => x.WhenICallTheFinder())
 | 
			
		||||
                .Then(x => x.ThenAnErrorResponseIsReturned())
 | 
			
		||||
                .And(x => x.ThenTheUrlMatcherIsNotCalled())
 | 
			
		||||
                .BDDfy();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        [Fact]
 | 
			
		||||
        public void should_return_route_when_host_matches_but_null_host_on_same_path_first()
 | 
			
		||||
        {
 | 
			
		||||
            var serviceProviderConfig = new ServiceProviderConfigurationBuilder().Build();
 | 
			
		||||
 | 
			
		||||
            this.Given(x => x.GivenThereIsAnUpstreamUrlPath("matchInUrlMatcher/"))
 | 
			
		||||
                .And(x => GivenTheUpstreamHostIs("MATCH"))
 | 
			
		||||
                .And(x => x.GivenTheTemplateVariableAndNameFinderReturns(
 | 
			
		||||
                    new OkResponse<List<PlaceholderNameAndValue>>(
 | 
			
		||||
                        new List<PlaceholderNameAndValue>())))
 | 
			
		||||
                .And(x => x.GivenTheConfigurationIs(new List<ReRoute>
 | 
			
		||||
                    {
 | 
			
		||||
                        new ReRouteBuilder()
 | 
			
		||||
                            .WithDownstreamPathTemplate("THENULLPATH")
 | 
			
		||||
                            .WithUpstreamPathTemplate("someUpstreamPath")
 | 
			
		||||
                            .WithUpstreamHttpMethod(new List<string> { "Get" })
 | 
			
		||||
                            .WithUpstreamTemplatePattern(new UpstreamPathTemplate("someUpstreamPath", 1))
 | 
			
		||||
                            .Build(),
 | 
			
		||||
                        new ReRouteBuilder()
 | 
			
		||||
                            .WithDownstreamPathTemplate("someDownstreamPath")
 | 
			
		||||
                            .WithUpstreamPathTemplate("someUpstreamPath")
 | 
			
		||||
                            .WithUpstreamHttpMethod(new List<string> { "Get" })
 | 
			
		||||
                            .WithUpstreamTemplatePattern(new UpstreamPathTemplate("someUpstreamPath", 1))
 | 
			
		||||
                            .WithUpstreamHost("MATCH")
 | 
			
		||||
                            .Build()
 | 
			
		||||
                    }, string.Empty, serviceProviderConfig
 | 
			
		||||
                ))
 | 
			
		||||
                .And(x => x.GivenTheUrlMatcherReturns(new OkResponse<UrlMatch>(new UrlMatch(true))))
 | 
			
		||||
                .And(x => x.GivenTheUpstreamHttpMethodIs("Get"))
 | 
			
		||||
                .When(x => x.WhenICallTheFinder())
 | 
			
		||||
                .Then(
 | 
			
		||||
                    x => x.ThenTheFollowingIsReturned(new DownstreamRoute(
 | 
			
		||||
                        new List<PlaceholderNameAndValue>(),
 | 
			
		||||
                        new ReRouteBuilder()
 | 
			
		||||
                            .WithDownstreamPathTemplate("someDownstreamPath")
 | 
			
		||||
                            .WithUpstreamHttpMethod(new List<string> { "Get" })
 | 
			
		||||
                            .WithUpstreamTemplatePattern(new UpstreamPathTemplate("someUpstreamPath", 1))
 | 
			
		||||
                            .Build()
 | 
			
		||||
                    )))
 | 
			
		||||
                .And(x => x.ThenTheUrlMatcherIsCalledCorrectly(2))
 | 
			
		||||
                .BDDfy();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void GivenTheUpstreamHostIs(string upstreamHost)
 | 
			
		||||
        {
 | 
			
		||||
            _upstreamHost = upstreamHost;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void GivenTheTemplateVariableAndNameFinderReturns(Response<List<PlaceholderNameAndValue>> response)
 | 
			
		||||
        {
 | 
			
		||||
            _finder
 | 
			
		||||
@@ -399,6 +548,12 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
 | 
			
		||||
                .Verify(x => x.Match(_upstreamUrlPath, _reRoutesConfig[0].UpstreamPathTemplate.Value), Times.Once);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void ThenTheUrlMatcherIsCalledCorrectly(int times)
 | 
			
		||||
        {
 | 
			
		||||
            _mockMatcher
 | 
			
		||||
                .Verify(x => x.Match(_upstreamUrlPath, _reRoutesConfig[0].UpstreamPathTemplate.Value), Times.Exactly(times));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void ThenTheUrlMatcherIsCalledCorrectly(string expectedUpstreamUrlPath)
 | 
			
		||||
        {
 | 
			
		||||
            _mockMatcher
 | 
			
		||||
@@ -432,7 +587,7 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
 | 
			
		||||
 | 
			
		||||
        private void WhenICallTheFinder()
 | 
			
		||||
        {
 | 
			
		||||
            _result = _downstreamRouteFinder.FindDownstreamRoute(_upstreamUrlPath, _upstreamHttpMethod, _config);
 | 
			
		||||
            _result = _downstreamRouteFinder.FindDownstreamRoute(_upstreamUrlPath, _upstreamHttpMethod, _config, _upstreamHost);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void ThenTheFollowingIsReturned(DownstreamRoute expected)
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user