mirror of
				https://github.com/nsnail/Ocelot.git
				synced 2025-11-04 12:10:50 +08:00 
			
		
		
		
	@@ -1,84 +1,93 @@
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using Ocelot.Configuration.File;
 | 
			
		||||
using Ocelot.Values;
 | 
			
		||||
 | 
			
		||||
namespace Ocelot.Configuration.Creator
 | 
			
		||||
{
 | 
			
		||||
    public class UpstreamTemplatePatternCreator : IUpstreamTemplatePatternCreator
 | 
			
		||||
    {
 | 
			
		||||
        private const string RegExMatchOneOrMoreOfEverything = ".+";
 | 
			
		||||
        private const string RegExMatchEndString = "$";
 | 
			
		||||
        private const string RegExIgnoreCase = "(?i)";
 | 
			
		||||
        private const string RegExForwardSlashOnly = "^/$";
 | 
			
		||||
        private const string RegExForwardSlashAndOnePlaceHolder = "^/.*";
 | 
			
		||||
 | 
			
		||||
        public UpstreamPathTemplate Create(IReRoute reRoute)
 | 
			
		||||
        {
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using Ocelot.Configuration.File;
 | 
			
		||||
using Ocelot.Values;
 | 
			
		||||
 | 
			
		||||
namespace Ocelot.Configuration.Creator
 | 
			
		||||
{
 | 
			
		||||
    public class UpstreamTemplatePatternCreator : IUpstreamTemplatePatternCreator
 | 
			
		||||
    {
 | 
			
		||||
        private const string RegExMatchOneOrMoreOfEverything = ".+";
 | 
			
		||||
        private const string RegExMatchOneOrMoreOfEverythingUntilNextForwardSlash = "[^/]+";
 | 
			
		||||
        private const string RegExMatchEndString = "$";
 | 
			
		||||
        private const string RegExIgnoreCase = "(?i)";
 | 
			
		||||
        private const string RegExForwardSlashOnly = "^/$";
 | 
			
		||||
        private const string RegExForwardSlashAndOnePlaceHolder = "^/.*";
 | 
			
		||||
 | 
			
		||||
        public UpstreamPathTemplate Create(IReRoute reRoute)
 | 
			
		||||
        {
 | 
			
		||||
            var upstreamTemplate = reRoute.UpstreamPathTemplate;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
            var placeholders = new List<string>();
 | 
			
		||||
 | 
			
		||||
            for (var i = 0; i < upstreamTemplate.Length; i++)
 | 
			
		||||
            {
 | 
			
		||||
                if (IsPlaceHolder(upstreamTemplate, i))
 | 
			
		||||
                {
 | 
			
		||||
                    var postitionOfPlaceHolderClosingBracket = upstreamTemplate.IndexOf('}', i);
 | 
			
		||||
                    var difference = postitionOfPlaceHolderClosingBracket - i + 1;
 | 
			
		||||
                    var placeHolderName = upstreamTemplate.Substring(i, difference);
 | 
			
		||||
                    placeholders.Add(placeHolderName);
 | 
			
		||||
 | 
			
		||||
                    //hack to handle /{url} case
 | 
			
		||||
                    if(ForwardSlashAndOnePlaceHolder(upstreamTemplate, placeholders, postitionOfPlaceHolderClosingBracket))
 | 
			
		||||
                    {
 | 
			
		||||
                        return new UpstreamPathTemplate(RegExForwardSlashAndOnePlaceHolder, 0, false);
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
            var placeholders = new List<string>();
 | 
			
		||||
 | 
			
		||||
            for (var i = 0; i < upstreamTemplate.Length; i++)
 | 
			
		||||
            {
 | 
			
		||||
                if (IsPlaceHolder(upstreamTemplate, i))
 | 
			
		||||
                {
 | 
			
		||||
                    var postitionOfPlaceHolderClosingBracket = upstreamTemplate.IndexOf('}', i);
 | 
			
		||||
                    var difference = postitionOfPlaceHolderClosingBracket - i + 1;
 | 
			
		||||
                    var placeHolderName = upstreamTemplate.Substring(i, difference);
 | 
			
		||||
                    placeholders.Add(placeHolderName);
 | 
			
		||||
 | 
			
		||||
                    //hack to handle /{url} case
 | 
			
		||||
                    if(ForwardSlashAndOnePlaceHolder(upstreamTemplate, placeholders, postitionOfPlaceHolderClosingBracket))
 | 
			
		||||
                    {
 | 
			
		||||
                        return new UpstreamPathTemplate(RegExForwardSlashAndOnePlaceHolder, 0, false);
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            var containsQueryString = false;
 | 
			
		||||
 | 
			
		||||
            if (upstreamTemplate.Contains("?"))
 | 
			
		||||
            {
 | 
			
		||||
                containsQueryString = true;
 | 
			
		||||
                upstreamTemplate = upstreamTemplate.Replace("?", "\\?");
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            foreach (var placeholder in placeholders)
 | 
			
		||||
            {
 | 
			
		||||
                upstreamTemplate = upstreamTemplate.Replace(placeholder, RegExMatchOneOrMoreOfEverything);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (upstreamTemplate == "/")
 | 
			
		||||
            {
 | 
			
		||||
                return new UpstreamPathTemplate(RegExForwardSlashOnly, reRoute.Priority, containsQueryString);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if(upstreamTemplate.EndsWith("/"))
 | 
			
		||||
            {
 | 
			
		||||
                upstreamTemplate = upstreamTemplate.Remove(upstreamTemplate.Length -1, 1) + "(/|)";
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            var route = reRoute.ReRouteIsCaseSensitive 
 | 
			
		||||
                ? $"^{upstreamTemplate}{RegExMatchEndString}" 
 | 
			
		||||
                : $"^{RegExIgnoreCase}{upstreamTemplate}{RegExMatchEndString}";
 | 
			
		||||
 | 
			
		||||
            return new UpstreamPathTemplate(route, reRoute.Priority, containsQueryString);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private bool ForwardSlashAndOnePlaceHolder(string upstreamTemplate, List<string> placeholders, int postitionOfPlaceHolderClosingBracket)
 | 
			
		||||
        {
 | 
			
		||||
            if(upstreamTemplate.Substring(0, 2) == "/{" && placeholders.Count == 1 && upstreamTemplate.Length == postitionOfPlaceHolderClosingBracket + 1)
 | 
			
		||||
            {   
 | 
			
		||||
                return true;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private bool IsPlaceHolder(string upstreamTemplate, int i)
 | 
			
		||||
        {
 | 
			
		||||
            return upstreamTemplate[i] == '{';
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
            var containsQueryString = false;
 | 
			
		||||
 | 
			
		||||
            if (upstreamTemplate.Contains("?"))
 | 
			
		||||
            {
 | 
			
		||||
                containsQueryString = true;
 | 
			
		||||
                upstreamTemplate = upstreamTemplate.Replace("?", "\\?");
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            for (int i = 0; i < placeholders.Count; i++)
 | 
			
		||||
            {
 | 
			
		||||
                var indexOfPlaceholder = upstreamTemplate.IndexOf(placeholders[i]);
 | 
			
		||||
                var indexOfNextForwardSlash = upstreamTemplate.IndexOf("/", indexOfPlaceholder);
 | 
			
		||||
                if(indexOfNextForwardSlash < indexOfPlaceholder || (containsQueryString && upstreamTemplate.IndexOf("?") < upstreamTemplate.IndexOf(placeholders[i])))
 | 
			
		||||
                {
 | 
			
		||||
                    upstreamTemplate = upstreamTemplate.Replace(placeholders[i], RegExMatchOneOrMoreOfEverything);
 | 
			
		||||
                } 
 | 
			
		||||
                else 
 | 
			
		||||
                {
 | 
			
		||||
                    upstreamTemplate = upstreamTemplate.Replace(placeholders[i], RegExMatchOneOrMoreOfEverythingUntilNextForwardSlash);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (upstreamTemplate == "/")
 | 
			
		||||
            {
 | 
			
		||||
                return new UpstreamPathTemplate(RegExForwardSlashOnly, reRoute.Priority, containsQueryString);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if(upstreamTemplate.EndsWith("/"))
 | 
			
		||||
            {
 | 
			
		||||
                upstreamTemplate = upstreamTemplate.Remove(upstreamTemplate.Length -1, 1) + "(/|)";
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            var route = reRoute.ReRouteIsCaseSensitive 
 | 
			
		||||
                ? $"^{upstreamTemplate}{RegExMatchEndString}" 
 | 
			
		||||
                : $"^{RegExIgnoreCase}{upstreamTemplate}{RegExMatchEndString}";
 | 
			
		||||
 | 
			
		||||
            return new UpstreamPathTemplate(route, reRoute.Priority, containsQueryString);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private bool ForwardSlashAndOnePlaceHolder(string upstreamTemplate, List<string> placeholders, int postitionOfPlaceHolderClosingBracket)
 | 
			
		||||
        {
 | 
			
		||||
            if(upstreamTemplate.Substring(0, 2) == "/{" && placeholders.Count == 1 && upstreamTemplate.Length == postitionOfPlaceHolderClosingBracket + 1)
 | 
			
		||||
            {   
 | 
			
		||||
                return true;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private bool IsPlaceHolder(string upstreamTemplate, int i)
 | 
			
		||||
        {
 | 
			
		||||
            return upstreamTemplate[i] == '{';
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -21,6 +21,41 @@ namespace Ocelot.AcceptanceTests
 | 
			
		||||
            _steps = new Steps();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Fact]
 | 
			
		||||
        public void should_not_match_forward_slash_in_pattern_before_next_forward_slash()
 | 
			
		||||
        {
 | 
			
		||||
            var port = 31879;
 | 
			
		||||
            var configuration = new FileConfiguration
 | 
			
		||||
            {
 | 
			
		||||
                ReRoutes = new List<FileReRoute>
 | 
			
		||||
                    {
 | 
			
		||||
                        new FileReRoute
 | 
			
		||||
                        {
 | 
			
		||||
                            DownstreamPathTemplate = "/api/v{apiVersion}/cards",
 | 
			
		||||
                            DownstreamScheme = "http",
 | 
			
		||||
                            UpstreamPathTemplate = "/api/v{apiVersion}/cards",
 | 
			
		||||
                            UpstreamHttpMethod = new List<string> { "Get" },
 | 
			
		||||
                            DownstreamHostAndPorts = new List<FileHostAndPort>
 | 
			
		||||
                            {
 | 
			
		||||
                                new FileHostAndPort
 | 
			
		||||
                                {
 | 
			
		||||
                                    Host = "localhost",
 | 
			
		||||
                                    Port = port,
 | 
			
		||||
                                }
 | 
			
		||||
                            },
 | 
			
		||||
                            Priority = 1
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
            this.Given(x => x.GivenThereIsAServiceRunningOn($"http://localhost:{port}/", "/api/v1/aaaaaaaaa/cards", 200, "Hello from Laura"))
 | 
			
		||||
                .And(x => _steps.GivenThereIsAConfiguration(configuration))
 | 
			
		||||
                .And(x => _steps.GivenOcelotIsRunning())
 | 
			
		||||
                .When(x => _steps.WhenIGetUrlOnTheApiGateway("/api/v1/aaaaaaaaa/cards"))
 | 
			
		||||
                .Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.NotFound))
 | 
			
		||||
                .BDDfy();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Fact]
 | 
			
		||||
        public void should_return_response_404_when_no_configuration_at_all()
 | 
			
		||||
        {
 | 
			
		||||
 
 | 
			
		||||
@@ -1,244 +1,260 @@
 | 
			
		||||
using Ocelot.Configuration.Creator;
 | 
			
		||||
using Ocelot.Configuration.File;
 | 
			
		||||
using Ocelot.Values;
 | 
			
		||||
using Shouldly;
 | 
			
		||||
using TestStack.BDDfy;
 | 
			
		||||
using Xunit;
 | 
			
		||||
 | 
			
		||||
namespace Ocelot.UnitTests.Configuration
 | 
			
		||||
{
 | 
			
		||||
    public class UpstreamTemplatePatternCreatorTests
 | 
			
		||||
    {
 | 
			
		||||
        private FileReRoute _fileReRoute;
 | 
			
		||||
        private readonly UpstreamTemplatePatternCreator _creator;
 | 
			
		||||
        private UpstreamPathTemplate _result;
 | 
			
		||||
 | 
			
		||||
        public UpstreamTemplatePatternCreatorTests()
 | 
			
		||||
        {
 | 
			
		||||
            _creator = new UpstreamTemplatePatternCreator();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Fact]
 | 
			
		||||
        public void should_use_re_route_priority()
 | 
			
		||||
        {
 | 
			
		||||
            var fileReRoute = new FileReRoute
 | 
			
		||||
            {
 | 
			
		||||
                UpstreamPathTemplate = "/orders/{catchAll}",
 | 
			
		||||
                Priority = 0
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
            this.Given(x => x.GivenTheFollowingFileReRoute(fileReRoute))
 | 
			
		||||
                .When(x => x.WhenICreateTheTemplatePattern())
 | 
			
		||||
                .Then(x => x.ThenTheFollowingIsReturned("^(?i)/orders/.+$"))
 | 
			
		||||
                .And(x => ThenThePriorityIs(0))
 | 
			
		||||
                .BDDfy();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Fact]
 | 
			
		||||
        public void should_use_zero_priority()
 | 
			
		||||
        {
 | 
			
		||||
            var fileReRoute = new FileReRoute
 | 
			
		||||
            {
 | 
			
		||||
                UpstreamPathTemplate = "/{catchAll}",
 | 
			
		||||
                Priority = 1
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
            this.Given(x => x.GivenTheFollowingFileReRoute(fileReRoute))
 | 
			
		||||
                .When(x => x.WhenICreateTheTemplatePattern())
 | 
			
		||||
                .Then(x => x.ThenTheFollowingIsReturned("^/.*"))
 | 
			
		||||
                .And(x => ThenThePriorityIs(0))
 | 
			
		||||
                .BDDfy();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Fact]
 | 
			
		||||
        public void should_set_upstream_template_pattern_to_ignore_case_sensitivity()
 | 
			
		||||
        {
 | 
			
		||||
            var fileReRoute = new FileReRoute
 | 
			
		||||
            {
 | 
			
		||||
                UpstreamPathTemplate = "/PRODUCTS/{productId}",
 | 
			
		||||
                ReRouteIsCaseSensitive = false
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
            this.Given(x => x.GivenTheFollowingFileReRoute(fileReRoute))
 | 
			
		||||
                .When(x => x.WhenICreateTheTemplatePattern())
 | 
			
		||||
                .Then(x => x.ThenTheFollowingIsReturned("^(?i)/PRODUCTS/.+$"))
 | 
			
		||||
                .And(x => ThenThePriorityIs(1))
 | 
			
		||||
                .BDDfy();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Fact]
 | 
			
		||||
        public void should_match_forward_slash_or_no_forward_slash_if_template_end_with_forward_slash()
 | 
			
		||||
        {
 | 
			
		||||
            var fileReRoute = new FileReRoute
 | 
			
		||||
            {
 | 
			
		||||
                UpstreamPathTemplate = "/PRODUCTS/",
 | 
			
		||||
                ReRouteIsCaseSensitive = false
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
            this.Given(x => x.GivenTheFollowingFileReRoute(fileReRoute))
 | 
			
		||||
                .When(x => x.WhenICreateTheTemplatePattern())
 | 
			
		||||
                .Then(x => x.ThenTheFollowingIsReturned("^(?i)/PRODUCTS(/|)$"))
 | 
			
		||||
                .And(x => ThenThePriorityIs(1))
 | 
			
		||||
                .BDDfy();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Fact]
 | 
			
		||||
        public void should_set_upstream_template_pattern_to_respect_case_sensitivity()
 | 
			
		||||
        {
 | 
			
		||||
                var fileReRoute = new FileReRoute
 | 
			
		||||
                {
 | 
			
		||||
                    UpstreamPathTemplate = "/PRODUCTS/{productId}",
 | 
			
		||||
                    ReRouteIsCaseSensitive = true
 | 
			
		||||
                };
 | 
			
		||||
            this.Given(x => x.GivenTheFollowingFileReRoute(fileReRoute))
 | 
			
		||||
                .When(x => x.WhenICreateTheTemplatePattern())
 | 
			
		||||
                .Then(x => x.ThenTheFollowingIsReturned("^/PRODUCTS/.+$"))
 | 
			
		||||
                .And(x => ThenThePriorityIs(1))
 | 
			
		||||
                .BDDfy();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Fact]
 | 
			
		||||
        public void should_create_template_pattern_that_matches_anything_to_end_of_string()
 | 
			
		||||
        {
 | 
			
		||||
            var fileReRoute = new FileReRoute
 | 
			
		||||
            {
 | 
			
		||||
                UpstreamPathTemplate = "/api/products/{productId}",
 | 
			
		||||
                ReRouteIsCaseSensitive = true
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
            this.Given(x => x.GivenTheFollowingFileReRoute(fileReRoute))
 | 
			
		||||
                .When(x => x.WhenICreateTheTemplatePattern())
 | 
			
		||||
                .Then(x => x.ThenTheFollowingIsReturned("^/api/products/.+$"))
 | 
			
		||||
                .And(x => ThenThePriorityIs(1))
 | 
			
		||||
                .BDDfy();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Fact]
 | 
			
		||||
        public void should_create_template_pattern_that_matches_more_than_one_placeholder()
 | 
			
		||||
        {
 | 
			
		||||
            var fileReRoute = new FileReRoute
 | 
			
		||||
            {
 | 
			
		||||
                UpstreamPathTemplate = "/api/products/{productId}/variants/{variantId}",
 | 
			
		||||
                ReRouteIsCaseSensitive = true
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
            this.Given(x => x.GivenTheFollowingFileReRoute(fileReRoute))
 | 
			
		||||
                .When(x => x.WhenICreateTheTemplatePattern())
 | 
			
		||||
                .Then(x => x.ThenTheFollowingIsReturned("^/api/products/.+/variants/.+$"))
 | 
			
		||||
                .And(x => ThenThePriorityIs(1))
 | 
			
		||||
                .BDDfy();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Fact]
 | 
			
		||||
        public void should_create_template_pattern_that_matches_more_than_one_placeholder_with_trailing_slash()
 | 
			
		||||
        {
 | 
			
		||||
            var fileReRoute = new FileReRoute
 | 
			
		||||
            {
 | 
			
		||||
                UpstreamPathTemplate = "/api/products/{productId}/variants/{variantId}/",
 | 
			
		||||
                ReRouteIsCaseSensitive = true
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
            this.Given(x => x.GivenTheFollowingFileReRoute(fileReRoute))
 | 
			
		||||
                .When(x => x.WhenICreateTheTemplatePattern())
 | 
			
		||||
                .Then(x => x.ThenTheFollowingIsReturned("^/api/products/.+/variants/.+(/|)$"))
 | 
			
		||||
                .And(x => ThenThePriorityIs(1))
 | 
			
		||||
                .BDDfy();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Fact]
 | 
			
		||||
        public void should_create_template_pattern_that_matches_to_end_of_string()
 | 
			
		||||
        {
 | 
			
		||||
            var fileReRoute = new FileReRoute
 | 
			
		||||
            {
 | 
			
		||||
                UpstreamPathTemplate = "/"
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
            this.Given(x => x.GivenTheFollowingFileReRoute(fileReRoute))
 | 
			
		||||
                .When(x => x.WhenICreateTheTemplatePattern())
 | 
			
		||||
                .Then(x => x.ThenTheFollowingIsReturned("^/$"))
 | 
			
		||||
                .And(x => ThenThePriorityIs(1))
 | 
			
		||||
                .BDDfy();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Fact]
 | 
			
		||||
        public void should_create_template_pattern_that_matches_to_end_of_string_when_slash_and_placeholder()
 | 
			
		||||
        {
 | 
			
		||||
            var fileReRoute = new FileReRoute
 | 
			
		||||
            {
 | 
			
		||||
                UpstreamPathTemplate = "/{url}"
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
            this.Given(x => x.GivenTheFollowingFileReRoute(fileReRoute))
 | 
			
		||||
                .When(x => x.WhenICreateTheTemplatePattern())
 | 
			
		||||
                .Then(x => x.ThenTheFollowingIsReturned("^/.*"))
 | 
			
		||||
                .And(x => ThenThePriorityIs(0))
 | 
			
		||||
                .BDDfy();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Fact]
 | 
			
		||||
        public void should_create_template_pattern_that_starts_with_placeholder_then_has_another_later()
 | 
			
		||||
        {
 | 
			
		||||
            var fileReRoute = new FileReRoute
 | 
			
		||||
            {
 | 
			
		||||
                UpstreamPathTemplate = "/{productId}/products/variants/{variantId}/",
 | 
			
		||||
                ReRouteIsCaseSensitive = true
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
            this.Given(x => x.GivenTheFollowingFileReRoute(fileReRoute))
 | 
			
		||||
                .When(x => x.WhenICreateTheTemplatePattern())
 | 
			
		||||
                .Then(x => x.ThenTheFollowingIsReturned("^/.+/products/variants/.+(/|)$"))
 | 
			
		||||
                .And(x => ThenThePriorityIs(1))
 | 
			
		||||
                .BDDfy();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Fact]
 | 
			
		||||
        public void should_create_template_pattern_that_matches_query_string()
 | 
			
		||||
        {
 | 
			
		||||
            var fileReRoute = new FileReRoute
 | 
			
		||||
            {
 | 
			
		||||
                UpstreamPathTemplate = "/api/subscriptions/{subscriptionId}/updates?unitId={unitId}"
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
            this.Given(x => x.GivenTheFollowingFileReRoute(fileReRoute))
 | 
			
		||||
                .When(x => x.WhenICreateTheTemplatePattern())
 | 
			
		||||
                .Then(x => x.ThenTheFollowingIsReturned("^(?i)/api/subscriptions/.+/updates\\?unitId=.+$"))
 | 
			
		||||
                .And(x => ThenThePriorityIs(1))
 | 
			
		||||
                .BDDfy();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Fact]
 | 
			
		||||
        public void should_create_template_pattern_that_matches_query_string_with_multiple_params()
 | 
			
		||||
        {
 | 
			
		||||
            var fileReRoute = new FileReRoute
 | 
			
		||||
            {
 | 
			
		||||
                UpstreamPathTemplate = "/api/subscriptions/{subscriptionId}/updates?unitId={unitId}&productId={productId}"
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
            this.Given(x => x.GivenTheFollowingFileReRoute(fileReRoute))
 | 
			
		||||
                .When(x => x.WhenICreateTheTemplatePattern())
 | 
			
		||||
                .Then(x => x.ThenTheFollowingIsReturned("^(?i)/api/subscriptions/.+/updates\\?unitId=.+&productId=.+$"))
 | 
			
		||||
                .And(x => ThenThePriorityIs(1))
 | 
			
		||||
                .BDDfy();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void GivenTheFollowingFileReRoute(FileReRoute fileReRoute)
 | 
			
		||||
        {
 | 
			
		||||
            _fileReRoute = fileReRoute;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void WhenICreateTheTemplatePattern()
 | 
			
		||||
        {
 | 
			
		||||
            _result = _creator.Create(_fileReRoute);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void ThenTheFollowingIsReturned(string expected)
 | 
			
		||||
        {
 | 
			
		||||
            _result.Template.ShouldBe(expected);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void ThenThePriorityIs(int v)
 | 
			
		||||
        {
 | 
			
		||||
            _result.Priority.ShouldBe(v);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
using Ocelot.Configuration.Creator;
 | 
			
		||||
using Ocelot.Configuration.File;
 | 
			
		||||
using Ocelot.Values;
 | 
			
		||||
using Shouldly;
 | 
			
		||||
using TestStack.BDDfy;
 | 
			
		||||
using Xunit;
 | 
			
		||||
 | 
			
		||||
namespace Ocelot.UnitTests.Configuration
 | 
			
		||||
{
 | 
			
		||||
    public class UpstreamTemplatePatternCreatorTests
 | 
			
		||||
    {
 | 
			
		||||
        private FileReRoute _fileReRoute;
 | 
			
		||||
        private readonly UpstreamTemplatePatternCreator _creator;
 | 
			
		||||
        private UpstreamPathTemplate _result;
 | 
			
		||||
 | 
			
		||||
        public UpstreamTemplatePatternCreatorTests()
 | 
			
		||||
        {
 | 
			
		||||
            _creator = new UpstreamTemplatePatternCreator();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Fact]
 | 
			
		||||
        public void should_match_up_to_next_slash()
 | 
			
		||||
        {
 | 
			
		||||
            var fileReRoute = new FileReRoute
 | 
			
		||||
            {
 | 
			
		||||
                UpstreamPathTemplate = "/api/v{apiVersion}/cards",
 | 
			
		||||
                Priority = 0
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
            this.Given(x => x.GivenTheFollowingFileReRoute(fileReRoute))
 | 
			
		||||
                .When(x => x.WhenICreateTheTemplatePattern())
 | 
			
		||||
                .Then(x => x.ThenTheFollowingIsReturned("^(?i)/api/v[^/]+/cards$"))
 | 
			
		||||
                .And(x => ThenThePriorityIs(0))
 | 
			
		||||
                .BDDfy();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Fact]
 | 
			
		||||
        public void should_use_re_route_priority()
 | 
			
		||||
        {
 | 
			
		||||
            var fileReRoute = new FileReRoute
 | 
			
		||||
            {
 | 
			
		||||
                UpstreamPathTemplate = "/orders/{catchAll}",
 | 
			
		||||
                Priority = 0
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
            this.Given(x => x.GivenTheFollowingFileReRoute(fileReRoute))
 | 
			
		||||
                .When(x => x.WhenICreateTheTemplatePattern())
 | 
			
		||||
                .Then(x => x.ThenTheFollowingIsReturned("^(?i)/orders/.+$"))
 | 
			
		||||
                .And(x => ThenThePriorityIs(0))
 | 
			
		||||
                .BDDfy();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Fact]
 | 
			
		||||
        public void should_use_zero_priority()
 | 
			
		||||
        {
 | 
			
		||||
            var fileReRoute = new FileReRoute
 | 
			
		||||
            {
 | 
			
		||||
                UpstreamPathTemplate = "/{catchAll}",
 | 
			
		||||
                Priority = 1
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
            this.Given(x => x.GivenTheFollowingFileReRoute(fileReRoute))
 | 
			
		||||
                .When(x => x.WhenICreateTheTemplatePattern())
 | 
			
		||||
                .Then(x => x.ThenTheFollowingIsReturned("^/.*"))
 | 
			
		||||
                .And(x => ThenThePriorityIs(0))
 | 
			
		||||
                .BDDfy();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Fact]
 | 
			
		||||
        public void should_set_upstream_template_pattern_to_ignore_case_sensitivity()
 | 
			
		||||
        {
 | 
			
		||||
            var fileReRoute = new FileReRoute
 | 
			
		||||
            {
 | 
			
		||||
                UpstreamPathTemplate = "/PRODUCTS/{productId}",
 | 
			
		||||
                ReRouteIsCaseSensitive = false
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
            this.Given(x => x.GivenTheFollowingFileReRoute(fileReRoute))
 | 
			
		||||
                .When(x => x.WhenICreateTheTemplatePattern())
 | 
			
		||||
                .Then(x => x.ThenTheFollowingIsReturned("^(?i)/PRODUCTS/.+$"))
 | 
			
		||||
                .And(x => ThenThePriorityIs(1))
 | 
			
		||||
                .BDDfy();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Fact]
 | 
			
		||||
        public void should_match_forward_slash_or_no_forward_slash_if_template_end_with_forward_slash()
 | 
			
		||||
        {
 | 
			
		||||
            var fileReRoute = new FileReRoute
 | 
			
		||||
            {
 | 
			
		||||
                UpstreamPathTemplate = "/PRODUCTS/",
 | 
			
		||||
                ReRouteIsCaseSensitive = false
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
            this.Given(x => x.GivenTheFollowingFileReRoute(fileReRoute))
 | 
			
		||||
                .When(x => x.WhenICreateTheTemplatePattern())
 | 
			
		||||
                .Then(x => x.ThenTheFollowingIsReturned("^(?i)/PRODUCTS(/|)$"))
 | 
			
		||||
                .And(x => ThenThePriorityIs(1))
 | 
			
		||||
                .BDDfy();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Fact]
 | 
			
		||||
        public void should_set_upstream_template_pattern_to_respect_case_sensitivity()
 | 
			
		||||
        {
 | 
			
		||||
                var fileReRoute = new FileReRoute
 | 
			
		||||
                {
 | 
			
		||||
                    UpstreamPathTemplate = "/PRODUCTS/{productId}",
 | 
			
		||||
                    ReRouteIsCaseSensitive = true
 | 
			
		||||
                };
 | 
			
		||||
            this.Given(x => x.GivenTheFollowingFileReRoute(fileReRoute))
 | 
			
		||||
                .When(x => x.WhenICreateTheTemplatePattern())
 | 
			
		||||
                .Then(x => x.ThenTheFollowingIsReturned("^/PRODUCTS/.+$"))
 | 
			
		||||
                .And(x => ThenThePriorityIs(1))
 | 
			
		||||
                .BDDfy();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Fact]
 | 
			
		||||
        public void should_create_template_pattern_that_matches_anything_to_end_of_string()
 | 
			
		||||
        {
 | 
			
		||||
            var fileReRoute = new FileReRoute
 | 
			
		||||
            {
 | 
			
		||||
                UpstreamPathTemplate = "/api/products/{productId}",
 | 
			
		||||
                ReRouteIsCaseSensitive = true
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
            this.Given(x => x.GivenTheFollowingFileReRoute(fileReRoute))
 | 
			
		||||
                .When(x => x.WhenICreateTheTemplatePattern())
 | 
			
		||||
                .Then(x => x.ThenTheFollowingIsReturned("^/api/products/.+$"))
 | 
			
		||||
                .And(x => ThenThePriorityIs(1))
 | 
			
		||||
                .BDDfy();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Fact]
 | 
			
		||||
        public void should_create_template_pattern_that_matches_more_than_one_placeholder()
 | 
			
		||||
        {
 | 
			
		||||
            var fileReRoute = new FileReRoute
 | 
			
		||||
            {
 | 
			
		||||
                UpstreamPathTemplate = "/api/products/{productId}/variants/{variantId}",
 | 
			
		||||
                ReRouteIsCaseSensitive = true
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
            this.Given(x => x.GivenTheFollowingFileReRoute(fileReRoute))
 | 
			
		||||
                .When(x => x.WhenICreateTheTemplatePattern())
 | 
			
		||||
                .Then(x => x.ThenTheFollowingIsReturned("^/api/products/[^/]+/variants/.+$"))
 | 
			
		||||
                .And(x => ThenThePriorityIs(1))
 | 
			
		||||
                .BDDfy();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Fact]
 | 
			
		||||
        public void should_create_template_pattern_that_matches_more_than_one_placeholder_with_trailing_slash()
 | 
			
		||||
        {
 | 
			
		||||
            var fileReRoute = new FileReRoute
 | 
			
		||||
            {
 | 
			
		||||
                UpstreamPathTemplate = "/api/products/{productId}/variants/{variantId}/",
 | 
			
		||||
                ReRouteIsCaseSensitive = true
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
            this.Given(x => x.GivenTheFollowingFileReRoute(fileReRoute))
 | 
			
		||||
                .When(x => x.WhenICreateTheTemplatePattern())
 | 
			
		||||
                .Then(x => x.ThenTheFollowingIsReturned("^/api/products/[^/]+/variants/[^/]+(/|)$"))
 | 
			
		||||
                .And(x => ThenThePriorityIs(1))
 | 
			
		||||
                .BDDfy();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Fact]
 | 
			
		||||
        public void should_create_template_pattern_that_matches_to_end_of_string()
 | 
			
		||||
        {
 | 
			
		||||
            var fileReRoute = new FileReRoute
 | 
			
		||||
            {
 | 
			
		||||
                UpstreamPathTemplate = "/"
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
            this.Given(x => x.GivenTheFollowingFileReRoute(fileReRoute))
 | 
			
		||||
                .When(x => x.WhenICreateTheTemplatePattern())
 | 
			
		||||
                .Then(x => x.ThenTheFollowingIsReturned("^/$"))
 | 
			
		||||
                .And(x => ThenThePriorityIs(1))
 | 
			
		||||
                .BDDfy();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Fact]
 | 
			
		||||
        public void should_create_template_pattern_that_matches_to_end_of_string_when_slash_and_placeholder()
 | 
			
		||||
        {
 | 
			
		||||
            var fileReRoute = new FileReRoute
 | 
			
		||||
            {
 | 
			
		||||
                UpstreamPathTemplate = "/{url}"
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
            this.Given(x => x.GivenTheFollowingFileReRoute(fileReRoute))
 | 
			
		||||
                .When(x => x.WhenICreateTheTemplatePattern())
 | 
			
		||||
                .Then(x => x.ThenTheFollowingIsReturned("^/.*"))
 | 
			
		||||
                .And(x => ThenThePriorityIs(0))
 | 
			
		||||
                .BDDfy();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Fact]
 | 
			
		||||
        public void should_create_template_pattern_that_starts_with_placeholder_then_has_another_later()
 | 
			
		||||
        {
 | 
			
		||||
            var fileReRoute = new FileReRoute
 | 
			
		||||
            {
 | 
			
		||||
                UpstreamPathTemplate = "/{productId}/products/variants/{variantId}/",
 | 
			
		||||
                ReRouteIsCaseSensitive = true
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
            this.Given(x => x.GivenTheFollowingFileReRoute(fileReRoute))
 | 
			
		||||
                .When(x => x.WhenICreateTheTemplatePattern())
 | 
			
		||||
                .Then(x => x.ThenTheFollowingIsReturned("^/[^/]+/products/variants/[^/]+(/|)$"))
 | 
			
		||||
                .And(x => ThenThePriorityIs(1))
 | 
			
		||||
                .BDDfy();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Fact]
 | 
			
		||||
        public void should_create_template_pattern_that_matches_query_string()
 | 
			
		||||
        {
 | 
			
		||||
            var fileReRoute = new FileReRoute
 | 
			
		||||
            {
 | 
			
		||||
                UpstreamPathTemplate = "/api/subscriptions/{subscriptionId}/updates?unitId={unitId}"
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
            this.Given(x => x.GivenTheFollowingFileReRoute(fileReRoute))
 | 
			
		||||
                .When(x => x.WhenICreateTheTemplatePattern())
 | 
			
		||||
                .Then(x => x.ThenTheFollowingIsReturned("^(?i)/api/subscriptions/[^/]+/updates\\?unitId=.+$"))
 | 
			
		||||
                .And(x => ThenThePriorityIs(1))
 | 
			
		||||
                .BDDfy();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Fact]
 | 
			
		||||
        public void should_create_template_pattern_that_matches_query_string_with_multiple_params()
 | 
			
		||||
        {
 | 
			
		||||
            var fileReRoute = new FileReRoute
 | 
			
		||||
            {
 | 
			
		||||
                UpstreamPathTemplate = "/api/subscriptions/{subscriptionId}/updates?unitId={unitId}&productId={productId}"
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
            this.Given(x => x.GivenTheFollowingFileReRoute(fileReRoute))
 | 
			
		||||
                .When(x => x.WhenICreateTheTemplatePattern())
 | 
			
		||||
                .Then(x => x.ThenTheFollowingIsReturned("^(?i)/api/subscriptions/[^/]+/updates\\?unitId=.+&productId=.+$"))
 | 
			
		||||
                .And(x => ThenThePriorityIs(1))
 | 
			
		||||
                .BDDfy();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void GivenTheFollowingFileReRoute(FileReRoute fileReRoute)
 | 
			
		||||
        {
 | 
			
		||||
            _fileReRoute = fileReRoute;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void WhenICreateTheTemplatePattern()
 | 
			
		||||
        {
 | 
			
		||||
            _result = _creator.Create(_fileReRoute);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void ThenTheFollowingIsReturned(string expected)
 | 
			
		||||
        {
 | 
			
		||||
            _result.Template.ShouldBe(expected);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void ThenThePriorityIs(int v)
 | 
			
		||||
        {
 | 
			
		||||
            _result.Priority.ShouldBe(v);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,271 +1,291 @@
 | 
			
		||||
using Ocelot.DownstreamRouteFinder.UrlMatcher;
 | 
			
		||||
using Ocelot.Responses;
 | 
			
		||||
using Shouldly;
 | 
			
		||||
using TestStack.BDDfy;
 | 
			
		||||
using Xunit;
 | 
			
		||||
 | 
			
		||||
namespace Ocelot.UnitTests.DownstreamRouteFinder.UrlMatcher
 | 
			
		||||
{
 | 
			
		||||
    public class RegExUrlMatcherTests
 | 
			
		||||
    {
 | 
			
		||||
        private readonly IUrlPathToUrlTemplateMatcher _urlMatcher;
 | 
			
		||||
        private string _path;
 | 
			
		||||
        private string _downstreamPathTemplate;
 | 
			
		||||
        private Response<UrlMatch> _result;
 | 
			
		||||
        private string _queryString;
 | 
			
		||||
        private bool _containsQueryString;
 | 
			
		||||
 | 
			
		||||
        public RegExUrlMatcherTests()
 | 
			
		||||
        {
 | 
			
		||||
            _urlMatcher = new RegExUrlMatcher();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Fact]
 | 
			
		||||
        public void should_match_path_with_no_query_string()
 | 
			
		||||
        {
 | 
			
		||||
            const string regExForwardSlashAndOnePlaceHolder = "^(?i)/newThing$";
 | 
			
		||||
 | 
			
		||||
            this.Given(x => x.GivenIHaveAUpstreamPath("/newThing"))
 | 
			
		||||
                .And(_ => GivenIHaveAQueryString("?DeviceType=IphoneApp&Browser=moonpigIphone&BrowserString=-&CountryCode=123&DeviceName=iPhone 5 (GSM+CDMA)&OperatingSystem=iPhone OS 7.1.2&BrowserVersion=3708AdHoc&ipAddress=-"))
 | 
			
		||||
                .And(x => x.GivenIHaveAnUpstreamUrlTemplatePattern(regExForwardSlashAndOnePlaceHolder))
 | 
			
		||||
                .When(x => x.WhenIMatchThePaths())
 | 
			
		||||
                .And(x => x.ThenTheResultIsTrue())
 | 
			
		||||
                .BDDfy();
 | 
			
		||||
using Ocelot.DownstreamRouteFinder.UrlMatcher;
 | 
			
		||||
using Ocelot.Responses;
 | 
			
		||||
using Shouldly;
 | 
			
		||||
using TestStack.BDDfy;
 | 
			
		||||
using Xunit;
 | 
			
		||||
 | 
			
		||||
namespace Ocelot.UnitTests.DownstreamRouteFinder.UrlMatcher
 | 
			
		||||
{
 | 
			
		||||
    public class RegExUrlMatcherTests
 | 
			
		||||
    {
 | 
			
		||||
        private readonly IUrlPathToUrlTemplateMatcher _urlMatcher;
 | 
			
		||||
        private string _path;
 | 
			
		||||
        private string _downstreamPathTemplate;
 | 
			
		||||
        private Response<UrlMatch> _result;
 | 
			
		||||
        private string _queryString;
 | 
			
		||||
        private bool _containsQueryString;
 | 
			
		||||
 | 
			
		||||
        public RegExUrlMatcherTests()
 | 
			
		||||
        {
 | 
			
		||||
            _urlMatcher = new RegExUrlMatcher();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Fact]
 | 
			
		||||
        public void should_match_query_string()
 | 
			
		||||
        {
 | 
			
		||||
            const string regExForwardSlashAndOnePlaceHolder = "^(?i)/api/subscriptions/.+/updates\\?unitId=.+$";
 | 
			
		||||
 | 
			
		||||
            this.Given(x => x.GivenIHaveAUpstreamPath("/api/subscriptions/1/updates"))
 | 
			
		||||
                .And(_ => GivenIHaveAQueryString("?unitId=2"))
 | 
			
		||||
                .And(x => x.GivenIHaveAnUpstreamUrlTemplatePattern(regExForwardSlashAndOnePlaceHolder))
 | 
			
		||||
                .And(_ => GivenThereIsAQueryInTemplate())
 | 
			
		||||
                .When(x => x.WhenIMatchThePaths())
 | 
			
		||||
                .And(x => x.ThenTheResultIsTrue())
 | 
			
		||||
                .BDDfy();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Fact]
 | 
			
		||||
        public void should_match_query_string_with_multiple_params()
 | 
			
		||||
        {
 | 
			
		||||
            const string regExForwardSlashAndOnePlaceHolder = "^(?i)/api/subscriptions/.+/updates\\?unitId=.+&productId=.+$";
 | 
			
		||||
 | 
			
		||||
            this.Given(x => x.GivenIHaveAUpstreamPath("/api/subscriptions/1/updates?unitId=2"))
 | 
			
		||||
                .And(_ => GivenIHaveAQueryString("?unitId=2&productId=2"))
 | 
			
		||||
                .And(x => x.GivenIHaveAnUpstreamUrlTemplatePattern(regExForwardSlashAndOnePlaceHolder))
 | 
			
		||||
                .And(_ => GivenThereIsAQueryInTemplate())
 | 
			
		||||
                .When(x => x.WhenIMatchThePaths())
 | 
			
		||||
                .And(x => x.ThenTheResultIsTrue())
 | 
			
		||||
                .BDDfy();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Fact]
 | 
			
		||||
        public void should_not_match_slash_becaue_we_need_to_match_something_after_it()
 | 
			
		||||
        {
 | 
			
		||||
            const string regExForwardSlashAndOnePlaceHolder = "^/[0-9a-zA-Z].+";
 | 
			
		||||
 | 
			
		||||
            this.Given(x => x.GivenIHaveAUpstreamPath("/"))
 | 
			
		||||
              .And(x => x.GivenIHaveAnUpstreamUrlTemplatePattern(regExForwardSlashAndOnePlaceHolder))
 | 
			
		||||
              .When(x => x.WhenIMatchThePaths())
 | 
			
		||||
              .And(x => x.ThenTheResultIsFalse())
 | 
			
		||||
              .BDDfy();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Fact]
 | 
			
		||||
        public void should_not_match_forward_slash_only_regex()
 | 
			
		||||
        {
 | 
			
		||||
            this.Given(x => x.GivenIHaveAUpstreamPath("/working/"))
 | 
			
		||||
              .And(x => x.GivenIHaveAnUpstreamUrlTemplatePattern("^/$"))
 | 
			
		||||
              .When(x => x.WhenIMatchThePaths())
 | 
			
		||||
              .And(x => x.ThenTheResultIsFalse())
 | 
			
		||||
              .BDDfy();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Fact]
 | 
			
		||||
        public void should_not_match_issue_134()
 | 
			
		||||
        {
 | 
			
		||||
            this.Given(x => x.GivenIHaveAUpstreamPath("/api/vacancy/1/"))
 | 
			
		||||
              .And(x => x.GivenIHaveAnUpstreamUrlTemplatePattern("^(?i)/vacancy/.+/$"))
 | 
			
		||||
              .When(x => x.WhenIMatchThePaths())
 | 
			
		||||
              .And(x => x.ThenTheResultIsFalse())
 | 
			
		||||
              .BDDfy();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Fact]
 | 
			
		||||
        public void should_match_forward_slash_only_regex()
 | 
			
		||||
        {
 | 
			
		||||
            this.Given(x => x.GivenIHaveAUpstreamPath("/"))
 | 
			
		||||
              .And(x => x.GivenIHaveAnUpstreamUrlTemplatePattern("^/$"))
 | 
			
		||||
              .When(x => x.WhenIMatchThePaths())
 | 
			
		||||
              .And(x => x.ThenTheResultIsTrue())
 | 
			
		||||
              .BDDfy();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Fact]
 | 
			
		||||
        public void should_find_match_when_template_smaller_than_valid_path()
 | 
			
		||||
        {
 | 
			
		||||
            this.Given(x => x.GivenIHaveAUpstreamPath("/api/products/2354325435624623464235"))
 | 
			
		||||
                .And(x => x.GivenIHaveAnUpstreamUrlTemplatePattern("^/api/products/.+$"))
 | 
			
		||||
                .When(x => x.WhenIMatchThePaths())
 | 
			
		||||
                .And(x => x.ThenTheResultIsTrue())
 | 
			
		||||
                .BDDfy();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Fact]
 | 
			
		||||
        public void should_not_find_match()
 | 
			
		||||
        {
 | 
			
		||||
            this.Given(x => x.GivenIHaveAUpstreamPath("/api/values"))
 | 
			
		||||
                .And(x => x.GivenIHaveAnUpstreamUrlTemplatePattern("^/$"))
 | 
			
		||||
                .When(x => x.WhenIMatchThePaths())
 | 
			
		||||
                .And(x => x.ThenTheResultIsFalse())
 | 
			
		||||
                .BDDfy();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Fact]
 | 
			
		||||
        public void can_match_down_stream_url()
 | 
			
		||||
        {
 | 
			
		||||
            this.Given(x => x.GivenIHaveAUpstreamPath(""))
 | 
			
		||||
                .And(x => x.GivenIHaveAnUpstreamUrlTemplatePattern("^$"))
 | 
			
		||||
                .When(x => x.WhenIMatchThePaths())
 | 
			
		||||
                .And(x => x.ThenTheResultIsTrue())
 | 
			
		||||
                .BDDfy();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Fact]
 | 
			
		||||
        public void can_match_down_stream_url_with_no_slash()
 | 
			
		||||
        {
 | 
			
		||||
            this.Given(x => x.GivenIHaveAUpstreamPath("api"))
 | 
			
		||||
                 .Given(x => x.GivenIHaveAnUpstreamUrlTemplatePattern("^api$"))
 | 
			
		||||
                 .When(x => x.WhenIMatchThePaths())
 | 
			
		||||
                 .Then(x => x.ThenTheResultIsTrue())
 | 
			
		||||
                 .BDDfy();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Fact]
 | 
			
		||||
        public void can_match_down_stream_url_with_one_slash()
 | 
			
		||||
        {
 | 
			
		||||
            this.Given(x => x.GivenIHaveAUpstreamPath("api/"))
 | 
			
		||||
                 .Given(x => x.GivenIHaveAnUpstreamUrlTemplatePattern("^api/$"))
 | 
			
		||||
                 .When(x => x.WhenIMatchThePaths())
 | 
			
		||||
                 .Then(x => x.ThenTheResultIsTrue())
 | 
			
		||||
                 .BDDfy();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Fact]
 | 
			
		||||
        public void can_match_down_stream_url_with_downstream_template()
 | 
			
		||||
        {
 | 
			
		||||
            this.Given(x => x.GivenIHaveAUpstreamPath("api/product/products/"))
 | 
			
		||||
              .Given(x => x.GivenIHaveAnUpstreamUrlTemplatePattern("^api/product/products/$"))
 | 
			
		||||
              .When(x => x.WhenIMatchThePaths())
 | 
			
		||||
              .Then(x => x.ThenTheResultIsTrue())
 | 
			
		||||
              .BDDfy();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Fact]
 | 
			
		||||
        public void can_match_down_stream_url_with_downstream_template_with_one_place_holder()
 | 
			
		||||
        {
 | 
			
		||||
            this.Given(x => x.GivenIHaveAUpstreamPath("api/product/products/1"))
 | 
			
		||||
               .Given(x => x.GivenIHaveAnUpstreamUrlTemplatePattern("^api/product/products/.+$"))
 | 
			
		||||
               .When(x => x.WhenIMatchThePaths())
 | 
			
		||||
               .Then(x => x.ThenTheResultIsTrue())
 | 
			
		||||
               .BDDfy();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Fact]
 | 
			
		||||
        public void can_match_down_stream_url_with_downstream_template_with_two_place_holders()
 | 
			
		||||
        {
 | 
			
		||||
            this.Given(x => x.GivenIHaveAUpstreamPath("api/product/products/1/2"))
 | 
			
		||||
                 .Given(x => x.GivenIHaveAnUpstreamUrlTemplatePattern("^api/product/products/.+/.+$"))
 | 
			
		||||
                 .When(x => x.WhenIMatchThePaths())
 | 
			
		||||
                 .Then(x => x.ThenTheResultIsTrue())
 | 
			
		||||
                 .BDDfy();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Fact]
 | 
			
		||||
        public void can_match_down_stream_url_with_downstream_template_with_two_place_holders_seperated_by_something()
 | 
			
		||||
        {
 | 
			
		||||
            this.Given(x => x.GivenIHaveAUpstreamPath("api/product/products/1/categories/2"))
 | 
			
		||||
                .And(x => x.GivenIHaveAnUpstreamUrlTemplatePattern("^api/product/products/.+/categories/.+$"))
 | 
			
		||||
                .When(x => x.WhenIMatchThePaths())
 | 
			
		||||
                .Then(x => x.ThenTheResultIsTrue())
 | 
			
		||||
                .BDDfy();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Fact]
 | 
			
		||||
        public void can_match_down_stream_url_with_downstream_template_with_three_place_holders_seperated_by_something()
 | 
			
		||||
        {
 | 
			
		||||
            this.Given(x => x.GivenIHaveAUpstreamPath("api/product/products/1/categories/2/variant/123"))
 | 
			
		||||
                .And(x => x.GivenIHaveAnUpstreamUrlTemplatePattern("^api/product/products/.+/categories/.+/variant/.+$"))
 | 
			
		||||
                .When(x => x.WhenIMatchThePaths())
 | 
			
		||||
                .Then(x => x.ThenTheResultIsTrue())
 | 
			
		||||
                .BDDfy();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Fact]
 | 
			
		||||
        public void can_match_down_stream_url_with_downstream_template_with_three_place_holders()
 | 
			
		||||
        {
 | 
			
		||||
            this.Given(x => x.GivenIHaveAUpstreamPath("api/product/products/1/categories/2/variant/"))
 | 
			
		||||
                 .And(x => x.GivenIHaveAnUpstreamUrlTemplatePattern("^api/product/products/.+/categories/.+/variant/$"))
 | 
			
		||||
                 .When(x => x.WhenIMatchThePaths())
 | 
			
		||||
                 .Then(x => x.ThenTheResultIsTrue())
 | 
			
		||||
                 .BDDfy();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Fact]
 | 
			
		||||
        public void should_ignore_case_sensitivity()
 | 
			
		||||
        {
 | 
			
		||||
            this.Given(x => x.GivenIHaveAUpstreamPath("API/product/products/1/categories/2/variant/"))
 | 
			
		||||
               .And(x => x.GivenIHaveAnUpstreamUrlTemplatePattern("^(?i)api/product/products/.+/categories/.+/variant/$"))
 | 
			
		||||
               .When(x => x.WhenIMatchThePaths())
 | 
			
		||||
               .Then(x => x.ThenTheResultIsTrue())
 | 
			
		||||
               .BDDfy();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Fact]
 | 
			
		||||
        public void should_respect_case_sensitivity()
 | 
			
		||||
        {
 | 
			
		||||
            this.Given(x => x.GivenIHaveAUpstreamPath("API/product/products/1/categories/2/variant/"))
 | 
			
		||||
              .And(x => x.GivenIHaveAnUpstreamUrlTemplatePattern("^api/product/products/.+/categories/.+/variant/$"))
 | 
			
		||||
              .When(x => x.WhenIMatchThePaths())
 | 
			
		||||
              .Then(x => x.ThenTheResultIsFalse())
 | 
			
		||||
              .BDDfy();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void GivenIHaveAUpstreamPath(string path)
 | 
			
		||||
        {
 | 
			
		||||
            _path = path;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void GivenIHaveAQueryString(string queryString)
 | 
			
		||||
        {
 | 
			
		||||
            _queryString = queryString;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void GivenIHaveAnUpstreamUrlTemplatePattern(string downstreamUrlTemplate)
 | 
			
		||||
        {
 | 
			
		||||
            _downstreamPathTemplate = downstreamUrlTemplate;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void WhenIMatchThePaths()
 | 
			
		||||
        {
 | 
			
		||||
            _result = _urlMatcher.Match(_path, _queryString, _downstreamPathTemplate, _containsQueryString);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void ThenTheResultIsTrue()
 | 
			
		||||
        {
 | 
			
		||||
            _result.Data.Match.ShouldBeTrue();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void ThenTheResultIsFalse()
 | 
			
		||||
        {
 | 
			
		||||
            _result.Data.Match.ShouldBeFalse();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void GivenThereIsAQueryInTemplate()
 | 
			
		||||
        {
 | 
			
		||||
            _containsQueryString = true;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
} 
 | 
			
		||||
 | 
			
		||||
        [Fact]
 | 
			
		||||
        public void should_not_match()
 | 
			
		||||
        {
 | 
			
		||||
            this.Given(x => x.GivenIHaveAUpstreamPath("/api/v1/aaaaaaaaa/cards"))
 | 
			
		||||
              .And(x => x.GivenIHaveAnUpstreamUrlTemplatePattern("^(?i)/api/v[^/]+/cards$"))
 | 
			
		||||
              .When(x => x.WhenIMatchThePaths())
 | 
			
		||||
              .And(x => x.ThenTheResultIsFalse())
 | 
			
		||||
              .BDDfy();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Fact]
 | 
			
		||||
        public void should_match()
 | 
			
		||||
        {
 | 
			
		||||
            this.Given(x => x.GivenIHaveAUpstreamPath("/api/v1/cards"))
 | 
			
		||||
              .And(x => x.GivenIHaveAnUpstreamUrlTemplatePattern("^(?i)/api/v[^/]+/cards$"))
 | 
			
		||||
              .When(x => x.WhenIMatchThePaths())
 | 
			
		||||
              .And(x => x.ThenTheResultIsTrue())
 | 
			
		||||
              .BDDfy();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Fact]
 | 
			
		||||
        public void should_match_path_with_no_query_string()
 | 
			
		||||
        {
 | 
			
		||||
            const string regExForwardSlashAndOnePlaceHolder = "^(?i)/newThing$";
 | 
			
		||||
 | 
			
		||||
            this.Given(x => x.GivenIHaveAUpstreamPath("/newThing"))
 | 
			
		||||
                .And(_ => GivenIHaveAQueryString("?DeviceType=IphoneApp&Browser=moonpigIphone&BrowserString=-&CountryCode=123&DeviceName=iPhone 5 (GSM+CDMA)&OperatingSystem=iPhone OS 7.1.2&BrowserVersion=3708AdHoc&ipAddress=-"))
 | 
			
		||||
                .And(x => x.GivenIHaveAnUpstreamUrlTemplatePattern(regExForwardSlashAndOnePlaceHolder))
 | 
			
		||||
                .When(x => x.WhenIMatchThePaths())
 | 
			
		||||
                .And(x => x.ThenTheResultIsTrue())
 | 
			
		||||
                .BDDfy();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Fact]
 | 
			
		||||
        public void should_match_query_string()
 | 
			
		||||
        {
 | 
			
		||||
            const string regExForwardSlashAndOnePlaceHolder = "^(?i)/api/subscriptions/[^/]+/updates\\?unitId=.+$";
 | 
			
		||||
 | 
			
		||||
            this.Given(x => x.GivenIHaveAUpstreamPath("/api/subscriptions/1/updates"))
 | 
			
		||||
                .And(_ => GivenIHaveAQueryString("?unitId=2"))
 | 
			
		||||
                .And(x => x.GivenIHaveAnUpstreamUrlTemplatePattern(regExForwardSlashAndOnePlaceHolder))
 | 
			
		||||
                .And(_ => GivenThereIsAQueryInTemplate())
 | 
			
		||||
                .When(x => x.WhenIMatchThePaths())
 | 
			
		||||
                .And(x => x.ThenTheResultIsTrue())
 | 
			
		||||
                .BDDfy();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Fact]
 | 
			
		||||
        public void should_match_query_string_with_multiple_params()
 | 
			
		||||
        {
 | 
			
		||||
            const string regExForwardSlashAndOnePlaceHolder = "^(?i)/api/subscriptions/[^/]+/updates\\?unitId=.+&productId=.+$";
 | 
			
		||||
 | 
			
		||||
            this.Given(x => x.GivenIHaveAUpstreamPath("/api/subscriptions/1/updates?unitId=2"))
 | 
			
		||||
                .And(_ => GivenIHaveAQueryString("?unitId=2&productId=2"))
 | 
			
		||||
                .And(x => x.GivenIHaveAnUpstreamUrlTemplatePattern(regExForwardSlashAndOnePlaceHolder))
 | 
			
		||||
                .And(_ => GivenThereIsAQueryInTemplate())
 | 
			
		||||
                .When(x => x.WhenIMatchThePaths())
 | 
			
		||||
                .And(x => x.ThenTheResultIsTrue())
 | 
			
		||||
                .BDDfy();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Fact]
 | 
			
		||||
        public void should_not_match_slash_becaue_we_need_to_match_something_after_it()
 | 
			
		||||
        {
 | 
			
		||||
            const string regExForwardSlashAndOnePlaceHolder = "^/[0-9a-zA-Z].+";
 | 
			
		||||
 | 
			
		||||
            this.Given(x => x.GivenIHaveAUpstreamPath("/"))
 | 
			
		||||
              .And(x => x.GivenIHaveAnUpstreamUrlTemplatePattern(regExForwardSlashAndOnePlaceHolder))
 | 
			
		||||
              .When(x => x.WhenIMatchThePaths())
 | 
			
		||||
              .And(x => x.ThenTheResultIsFalse())
 | 
			
		||||
              .BDDfy();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Fact]
 | 
			
		||||
        public void should_not_match_forward_slash_only_regex()
 | 
			
		||||
        {
 | 
			
		||||
            this.Given(x => x.GivenIHaveAUpstreamPath("/working/"))
 | 
			
		||||
              .And(x => x.GivenIHaveAnUpstreamUrlTemplatePattern("^/$"))
 | 
			
		||||
              .When(x => x.WhenIMatchThePaths())
 | 
			
		||||
              .And(x => x.ThenTheResultIsFalse())
 | 
			
		||||
              .BDDfy();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Fact]
 | 
			
		||||
        public void should_not_match_issue_134()
 | 
			
		||||
        {
 | 
			
		||||
            this.Given(x => x.GivenIHaveAUpstreamPath("/api/vacancy/1/"))
 | 
			
		||||
              .And(x => x.GivenIHaveAnUpstreamUrlTemplatePattern("^(?i)/vacancy/[^/]+/$"))
 | 
			
		||||
              .When(x => x.WhenIMatchThePaths())
 | 
			
		||||
              .And(x => x.ThenTheResultIsFalse())
 | 
			
		||||
              .BDDfy();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Fact]
 | 
			
		||||
        public void should_match_forward_slash_only_regex()
 | 
			
		||||
        {
 | 
			
		||||
            this.Given(x => x.GivenIHaveAUpstreamPath("/"))
 | 
			
		||||
              .And(x => x.GivenIHaveAnUpstreamUrlTemplatePattern("^/$"))
 | 
			
		||||
              .When(x => x.WhenIMatchThePaths())
 | 
			
		||||
              .And(x => x.ThenTheResultIsTrue())
 | 
			
		||||
              .BDDfy();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Fact]
 | 
			
		||||
        public void should_find_match_when_template_smaller_than_valid_path()
 | 
			
		||||
        {
 | 
			
		||||
            this.Given(x => x.GivenIHaveAUpstreamPath("/api/products/2354325435624623464235"))
 | 
			
		||||
                .And(x => x.GivenIHaveAnUpstreamUrlTemplatePattern("^/api/products/.+$"))
 | 
			
		||||
                .When(x => x.WhenIMatchThePaths())
 | 
			
		||||
                .And(x => x.ThenTheResultIsTrue())
 | 
			
		||||
                .BDDfy();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Fact]
 | 
			
		||||
        public void should_not_find_match()
 | 
			
		||||
        {
 | 
			
		||||
            this.Given(x => x.GivenIHaveAUpstreamPath("/api/values"))
 | 
			
		||||
                .And(x => x.GivenIHaveAnUpstreamUrlTemplatePattern("^/$"))
 | 
			
		||||
                .When(x => x.WhenIMatchThePaths())
 | 
			
		||||
                .And(x => x.ThenTheResultIsFalse())
 | 
			
		||||
                .BDDfy();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Fact]
 | 
			
		||||
        public void can_match_down_stream_url()
 | 
			
		||||
        {
 | 
			
		||||
            this.Given(x => x.GivenIHaveAUpstreamPath(""))
 | 
			
		||||
                .And(x => x.GivenIHaveAnUpstreamUrlTemplatePattern("^$"))
 | 
			
		||||
                .When(x => x.WhenIMatchThePaths())
 | 
			
		||||
                .And(x => x.ThenTheResultIsTrue())
 | 
			
		||||
                .BDDfy();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Fact]
 | 
			
		||||
        public void can_match_down_stream_url_with_no_slash()
 | 
			
		||||
        {
 | 
			
		||||
            this.Given(x => x.GivenIHaveAUpstreamPath("api"))
 | 
			
		||||
                 .Given(x => x.GivenIHaveAnUpstreamUrlTemplatePattern("^api$"))
 | 
			
		||||
                 .When(x => x.WhenIMatchThePaths())
 | 
			
		||||
                 .Then(x => x.ThenTheResultIsTrue())
 | 
			
		||||
                 .BDDfy();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Fact]
 | 
			
		||||
        public void can_match_down_stream_url_with_one_slash()
 | 
			
		||||
        {
 | 
			
		||||
            this.Given(x => x.GivenIHaveAUpstreamPath("api/"))
 | 
			
		||||
                 .Given(x => x.GivenIHaveAnUpstreamUrlTemplatePattern("^api/$"))
 | 
			
		||||
                 .When(x => x.WhenIMatchThePaths())
 | 
			
		||||
                 .Then(x => x.ThenTheResultIsTrue())
 | 
			
		||||
                 .BDDfy();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Fact]
 | 
			
		||||
        public void can_match_down_stream_url_with_downstream_template()
 | 
			
		||||
        {
 | 
			
		||||
            this.Given(x => x.GivenIHaveAUpstreamPath("api/product/products/"))
 | 
			
		||||
              .Given(x => x.GivenIHaveAnUpstreamUrlTemplatePattern("^api/product/products/$"))
 | 
			
		||||
              .When(x => x.WhenIMatchThePaths())
 | 
			
		||||
              .Then(x => x.ThenTheResultIsTrue())
 | 
			
		||||
              .BDDfy();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Fact]
 | 
			
		||||
        public void can_match_down_stream_url_with_downstream_template_with_one_place_holder()
 | 
			
		||||
        {
 | 
			
		||||
            this.Given(x => x.GivenIHaveAUpstreamPath("api/product/products/1"))
 | 
			
		||||
               .Given(x => x.GivenIHaveAnUpstreamUrlTemplatePattern("^api/product/products/.+$"))
 | 
			
		||||
               .When(x => x.WhenIMatchThePaths())
 | 
			
		||||
               .Then(x => x.ThenTheResultIsTrue())
 | 
			
		||||
               .BDDfy();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Fact]
 | 
			
		||||
        public void can_match_down_stream_url_with_downstream_template_with_two_place_holders()
 | 
			
		||||
        {
 | 
			
		||||
            this.Given(x => x.GivenIHaveAUpstreamPath("api/product/products/1/2"))
 | 
			
		||||
                 .Given(x => x.GivenIHaveAnUpstreamUrlTemplatePattern("^api/product/products/[^/]+/.+$"))
 | 
			
		||||
                 .When(x => x.WhenIMatchThePaths())
 | 
			
		||||
                 .Then(x => x.ThenTheResultIsTrue())
 | 
			
		||||
                 .BDDfy();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Fact]
 | 
			
		||||
        public void can_match_down_stream_url_with_downstream_template_with_two_place_holders_seperated_by_something()
 | 
			
		||||
        {
 | 
			
		||||
            this.Given(x => x.GivenIHaveAUpstreamPath("api/product/products/1/categories/2"))
 | 
			
		||||
                .And(x => x.GivenIHaveAnUpstreamUrlTemplatePattern("^api/product/products/[^/]+/categories/.+$"))
 | 
			
		||||
                .When(x => x.WhenIMatchThePaths())
 | 
			
		||||
                .Then(x => x.ThenTheResultIsTrue())
 | 
			
		||||
                .BDDfy();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Fact]
 | 
			
		||||
        public void can_match_down_stream_url_with_downstream_template_with_three_place_holders_seperated_by_something()
 | 
			
		||||
        {
 | 
			
		||||
            this.Given(x => x.GivenIHaveAUpstreamPath("api/product/products/1/categories/2/variant/123"))
 | 
			
		||||
                .And(x => x.GivenIHaveAnUpstreamUrlTemplatePattern("^api/product/products/[^/]+/categories/[^/]+/variant/.+$"))
 | 
			
		||||
                .When(x => x.WhenIMatchThePaths())
 | 
			
		||||
                .Then(x => x.ThenTheResultIsTrue())
 | 
			
		||||
                .BDDfy();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Fact]
 | 
			
		||||
        public void can_match_down_stream_url_with_downstream_template_with_three_place_holders()
 | 
			
		||||
        {
 | 
			
		||||
            this.Given(x => x.GivenIHaveAUpstreamPath("api/product/products/1/categories/2/variant/"))
 | 
			
		||||
                 .And(x => x.GivenIHaveAnUpstreamUrlTemplatePattern("^api/product/products/[^/]+/categories/[^/]+/variant/$"))
 | 
			
		||||
                 .When(x => x.WhenIMatchThePaths())
 | 
			
		||||
                 .Then(x => x.ThenTheResultIsTrue())
 | 
			
		||||
                 .BDDfy();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Fact]
 | 
			
		||||
        public void should_ignore_case_sensitivity()
 | 
			
		||||
        {
 | 
			
		||||
            this.Given(x => x.GivenIHaveAUpstreamPath("API/product/products/1/categories/2/variant/"))
 | 
			
		||||
               .And(x => x.GivenIHaveAnUpstreamUrlTemplatePattern("^(?i)api/product/products/[^/]+/categories/[^/]+/variant/$"))
 | 
			
		||||
               .When(x => x.WhenIMatchThePaths())
 | 
			
		||||
               .Then(x => x.ThenTheResultIsTrue())
 | 
			
		||||
               .BDDfy();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Fact]
 | 
			
		||||
        public void should_respect_case_sensitivity()
 | 
			
		||||
        {
 | 
			
		||||
            this.Given(x => x.GivenIHaveAUpstreamPath("API/product/products/1/categories/2/variant/"))
 | 
			
		||||
              .And(x => x.GivenIHaveAnUpstreamUrlTemplatePattern("^api/product/products/[^/]+/categories/[^/]+/variant/$"))
 | 
			
		||||
              .When(x => x.WhenIMatchThePaths())
 | 
			
		||||
              .Then(x => x.ThenTheResultIsFalse())
 | 
			
		||||
              .BDDfy();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void GivenIHaveAUpstreamPath(string path)
 | 
			
		||||
        {
 | 
			
		||||
            _path = path;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void GivenIHaveAQueryString(string queryString)
 | 
			
		||||
        {
 | 
			
		||||
            _queryString = queryString;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void GivenIHaveAnUpstreamUrlTemplatePattern(string downstreamUrlTemplate)
 | 
			
		||||
        {
 | 
			
		||||
            _downstreamPathTemplate = downstreamUrlTemplate;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void WhenIMatchThePaths()
 | 
			
		||||
        {
 | 
			
		||||
            _result = _urlMatcher.Match(_path, _queryString, _downstreamPathTemplate, _containsQueryString);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void ThenTheResultIsTrue()
 | 
			
		||||
        {
 | 
			
		||||
            _result.Data.Match.ShouldBeTrue();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void ThenTheResultIsFalse()
 | 
			
		||||
        {
 | 
			
		||||
            _result.Data.Match.ShouldBeFalse();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void GivenThereIsAQueryInTemplate()
 | 
			
		||||
        {
 | 
			
		||||
            _containsQueryString = true;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user