From 931a115ffae7141b4ccc183d4d253b6ef79ddd2e Mon Sep 17 00:00:00 2001 From: Tom Pallister Date: Tue, 2 Jan 2018 18:49:22 +0000 Subject: [PATCH] changes to add new feature to url routing (#186) --- .../Creator/UpstreamTemplatePatternCreator.cs | 20 ++++++- .../DownstreamRouteFinderMiddleware.cs | 1 + test/Ocelot.AcceptanceTests/RoutingTests.cs | 59 ++++++++++++++++++- .../UpstreamTemplatePatternCreatorTests.cs | 29 +++++++++ 4 files changed, 106 insertions(+), 3 deletions(-) diff --git a/src/Ocelot/Configuration/Creator/UpstreamTemplatePatternCreator.cs b/src/Ocelot/Configuration/Creator/UpstreamTemplatePatternCreator.cs index 92559bfb..a45d2864 100644 --- a/src/Ocelot/Configuration/Creator/UpstreamTemplatePatternCreator.cs +++ b/src/Ocelot/Configuration/Creator/UpstreamTemplatePatternCreator.cs @@ -9,6 +9,7 @@ namespace Ocelot.Configuration.Creator private const string RegExMatchEndString = "$"; private const string RegExIgnoreCase = "(?i)"; private const string RegExForwardSlashOnly = "^/$"; + private const string RegExForwardSlashAndOnePlaceHolder = "^/.*"; public string Create(FileReRoute reRoute) { @@ -22,8 +23,13 @@ namespace Ocelot.Configuration.Creator { var postitionOfPlaceHolderClosingBracket = upstreamTemplate.IndexOf('}', i); var difference = postitionOfPlaceHolderClosingBracket - i + 1; - var variableName = upstreamTemplate.Substring(i, difference); - placeholders.Add(variableName); + var placeHolderName = upstreamTemplate.Substring(i, difference); + placeholders.Add(placeHolderName); + + if(ForwardSlashAndOnePlaceHolder(upstreamTemplate, placeholders, postitionOfPlaceHolderClosingBracket)) + { + return RegExForwardSlashAndOnePlaceHolder; + } } } @@ -49,6 +55,16 @@ namespace Ocelot.Configuration.Creator return route; } + private bool ForwardSlashAndOnePlaceHolder(string upstreamTemplate, List 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) { diff --git a/src/Ocelot/DownstreamRouteFinder/Middleware/DownstreamRouteFinderMiddleware.cs b/src/Ocelot/DownstreamRouteFinder/Middleware/DownstreamRouteFinderMiddleware.cs index 36f01569..15aa79cf 100644 --- a/src/Ocelot/DownstreamRouteFinder/Middleware/DownstreamRouteFinderMiddleware.cs +++ b/src/Ocelot/DownstreamRouteFinder/Middleware/DownstreamRouteFinderMiddleware.cs @@ -38,6 +38,7 @@ namespace Ocelot.DownstreamRouteFinder.Middleware //todo make this getting config its own middleware one day? var configuration = await _configProvider.Get(); + if(configuration.IsError) { _logger.LogError($"{MiddlewareName} setting pipeline errors. IOcelotConfigurationProvider returned {configuration.Errors.ToErrorString()}"); diff --git a/test/Ocelot.AcceptanceTests/RoutingTests.cs b/test/Ocelot.AcceptanceTests/RoutingTests.cs index 926cb849..587327d1 100644 --- a/test/Ocelot.AcceptanceTests/RoutingTests.cs +++ b/test/Ocelot.AcceptanceTests/RoutingTests.cs @@ -32,7 +32,35 @@ namespace Ocelot.AcceptanceTests .Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.NotFound)) .BDDfy(); } - + + [Fact] + public void should_return_response_200_with_forward_slash_and_placeholder_only() + { + var configuration = new FileConfiguration + { + ReRoutes = new List + { + new FileReRoute + { + DownstreamPathTemplate = "/{url}", + DownstreamScheme = "http", + DownstreamHost = "localhost", + DownstreamPort = 51879, + UpstreamPathTemplate = "/{url}", + UpstreamHttpMethod = new List { "Get" }, + } + } + }; + + this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:51879", "", 200, "Hello from Laura")) + .And(x => _steps.GivenThereIsAConfiguration(configuration)) + .And(x => _steps.GivenOcelotIsRunning()) + .When(x => _steps.WhenIGetUrlOnTheApiGateway("/")) + .Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.OK)) + .And(x => _steps.ThenTheResponseBodyShouldBe("Hello from Laura")) + .BDDfy(); + } + [Fact] public void should_return_response_200_with_simple_url() { @@ -275,6 +303,35 @@ namespace Ocelot.AcceptanceTests } + [Fact] + public void should_return_response_200_with_complex_url_that_starts_with_placeholder() + { + var configuration = new FileConfiguration + { + ReRoutes = new List + { + new FileReRoute + { + DownstreamPathTemplate = "/api/{variantId}/products/{productId}", + DownstreamScheme = "http", + DownstreamHost = "localhost", + DownstreamPort = 51879, + UpstreamPathTemplate = "/{variantId}/products/{productId}", + UpstreamHttpMethod = new List { "Get" }, + } + } + }; + + this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:51879", "/api/23/products/1", 200, "Some Product")) + .And(x => _steps.GivenThereIsAConfiguration(configuration)) + .And(x => _steps.GivenOcelotIsRunning()) + .When(x => _steps.WhenIGetUrlOnTheApiGateway("23/products/1")) + .Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.OK)) + .And(x => _steps.ThenTheResponseBodyShouldBe("Some Product")) + .BDDfy(); + } + + [Fact] public void should_not_add_trailing_slash_to_downstream_url() { diff --git a/test/Ocelot.UnitTests/Configuration/UpstreamTemplatePatternCreatorTests.cs b/test/Ocelot.UnitTests/Configuration/UpstreamTemplatePatternCreatorTests.cs index fba285e2..d5c9774b 100644 --- a/test/Ocelot.UnitTests/Configuration/UpstreamTemplatePatternCreatorTests.cs +++ b/test/Ocelot.UnitTests/Configuration/UpstreamTemplatePatternCreatorTests.cs @@ -121,6 +121,35 @@ namespace Ocelot.UnitTests.Configuration .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("^/.*")) + .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("^/[0-9a-zA-Z].*/products/variants/[0-9a-zA-Z].*(/|)$")) + .BDDfy(); + } + private void GivenTheFollowingFileReRoute(FileReRoute fileReRoute) { _fileReRoute = fileReRoute;