From b57ae391efe653c656bb1fe1a8f3ac94655c3c18 Mon Sep 17 00:00:00 2001 From: Tom Gardham-Pallister Date: Wed, 1 Nov 2017 18:57:27 +0000 Subject: [PATCH] looking at #135 validation --- ...PathTemplateDoesntStartWithForwardSlash.cs | 12 ++++ .../Validator/FileConfigurationValidator.cs | 54 ++++++++++++++++ src/Ocelot/Errors/OcelotErrorCode.cs | 3 +- .../ConfigurationValidationTests.cs | 64 +++++++++++++++---- .../ErrorsToHttpStatusCodeMapperTests.cs | 2 +- 5 files changed, 120 insertions(+), 15 deletions(-) create mode 100644 src/Ocelot/Configuration/Validator/DownstreamPathTemplateDoesntStartWithForwardSlash.cs diff --git a/src/Ocelot/Configuration/Validator/DownstreamPathTemplateDoesntStartWithForwardSlash.cs b/src/Ocelot/Configuration/Validator/DownstreamPathTemplateDoesntStartWithForwardSlash.cs new file mode 100644 index 00000000..2f09dbfb --- /dev/null +++ b/src/Ocelot/Configuration/Validator/DownstreamPathTemplateDoesntStartWithForwardSlash.cs @@ -0,0 +1,12 @@ +using Ocelot.Errors; + +namespace Ocelot.Configuration.Validator +{ + public class PathTemplateDoesntStartWithForwardSlash : Error + { + public PathTemplateDoesntStartWithForwardSlash(string message) + : base(message, OcelotErrorCode.PathTemplateDoesntStartWithForwardSlash) + { + } + } +} diff --git a/src/Ocelot/Configuration/Validator/FileConfigurationValidator.cs b/src/Ocelot/Configuration/Validator/FileConfigurationValidator.cs index a3a77511..7b4f6dbe 100644 --- a/src/Ocelot/Configuration/Validator/FileConfigurationValidator.cs +++ b/src/Ocelot/Configuration/Validator/FileConfigurationValidator.cs @@ -26,6 +26,20 @@ namespace Ocelot.Configuration.Validator return new OkResponse(result); } + result = CheckDownstreamTemplatePathBeingsWithForwardSlash(configuration); + + if (result.IsError) + { + return new OkResponse(result); + } + + result = CheckUpstreamTemplatePathBeingsWithForwardSlash(configuration); + + if (result.IsError) + { + return new OkResponse(result); + } + result = await CheckForUnsupportedAuthenticationProviders(configuration); if (result.IsError) @@ -49,6 +63,46 @@ namespace Ocelot.Configuration.Validator return new OkResponse(result); } + private ConfigurationValidationResult CheckDownstreamTemplatePathBeingsWithForwardSlash(FileConfiguration configuration) + { + var errors = new List(); + + foreach(var reRoute in configuration.ReRoutes) + { + if(!reRoute.DownstreamPathTemplate.StartsWith("/")) + { + errors.Add(new PathTemplateDoesntStartWithForwardSlash($"{reRoute.DownstreamPathTemplate} doesnt start with forward slash")); + } + } + + if(errors.Any()) + { + return new ConfigurationValidationResult(true, errors); + } + + return new ConfigurationValidationResult(false, errors); + } + + private ConfigurationValidationResult CheckUpstreamTemplatePathBeingsWithForwardSlash(FileConfiguration configuration) + { + var errors = new List(); + + foreach(var reRoute in configuration.ReRoutes) + { + if(!reRoute.UpstreamPathTemplate.StartsWith("/")) + { + errors.Add(new PathTemplateDoesntStartWithForwardSlash($"{reRoute.DownstreamPathTemplate} doesnt start with forward slash")); + } + } + + if(errors.Any()) + { + return new ConfigurationValidationResult(true, errors); + } + + return new ConfigurationValidationResult(false, errors); + } + private async Task CheckForUnsupportedAuthenticationProviders(FileConfiguration configuration) { var errors = new List(); diff --git a/src/Ocelot/Errors/OcelotErrorCode.cs b/src/Ocelot/Errors/OcelotErrorCode.cs index 817edbd8..6f85df58 100644 --- a/src/Ocelot/Errors/OcelotErrorCode.cs +++ b/src/Ocelot/Errors/OcelotErrorCode.cs @@ -31,6 +31,7 @@ UnableToFindQoSProviderError, UnableToSetConfigInConsulError, UnmappableRequestError, - RateLimitOptionsError + RateLimitOptionsError, + PathTemplateDoesntStartWithForwardSlash } } diff --git a/test/Ocelot.UnitTests/Configuration/ConfigurationValidationTests.cs b/test/Ocelot.UnitTests/Configuration/ConfigurationValidationTests.cs index 63282da5..77d1e278 100644 --- a/test/Ocelot.UnitTests/Configuration/ConfigurationValidationTests.cs +++ b/test/Ocelot.UnitTests/Configuration/ConfigurationValidationTests.cs @@ -57,7 +57,7 @@ namespace Ocelot.UnitTests.Configuration new FileReRoute { DownstreamPathTemplate = "/api/products/", - UpstreamPathTemplate = "http://asdf.com" + UpstreamPathTemplate = "/asdf/" } } })) @@ -66,6 +66,44 @@ namespace Ocelot.UnitTests.Configuration .BDDfy(); } + [Fact] + public void configuration_is_invalid_without_slash_prefix_downstream_path_template() + { + this.Given(x => x.GivenAConfiguration(new FileConfiguration + { + ReRoutes = new List + { + new FileReRoute + { + DownstreamPathTemplate = "api/products/", + UpstreamPathTemplate = "/asdf/" + } + } + })) + .When(x => x.WhenIValidateTheConfiguration()) + .Then(x => x.ThenTheResultIsNotValid()) + .BDDfy(); + } + + [Fact] + public void configuration_is_invalid_without_slash_prefix_upstream_path_template() + { + this.Given(x => x.GivenAConfiguration(new FileConfiguration + { + ReRoutes = new List + { + new FileReRoute + { + DownstreamPathTemplate = "/api/products/", + UpstreamPathTemplate = "api/prod/", + } + } + })) + .When(x => x.WhenIValidateTheConfiguration()) + .Then(x => x.ThenTheResultIsNotValid()) + .BDDfy(); + } + [Fact] public void configuration_is_valid_with_valid_authentication_provider() { @@ -76,7 +114,7 @@ namespace Ocelot.UnitTests.Configuration new FileReRoute { DownstreamPathTemplate = "/api/products/", - UpstreamPathTemplate = "http://asdf.com", + UpstreamPathTemplate = "/asdf/", AuthenticationOptions = new FileAuthenticationOptions() { AuthenticationProviderKey = "Test" @@ -90,14 +128,6 @@ namespace Ocelot.UnitTests.Configuration .BDDfy(); } - private void GivenTheAuthSchemeExists(string name) - { - _provider.Setup(x => x.GetAllSchemesAsync()).ReturnsAsync(new List - { - new AuthenticationScheme(name, name, typeof(TestHandler)) - }); - } - [Fact] public void configuration_is_invalid_with_invalid_authentication_provider() { @@ -108,7 +138,7 @@ namespace Ocelot.UnitTests.Configuration new FileReRoute { DownstreamPathTemplate = "/api/products/", - UpstreamPathTemplate = "http://asdf.com", + UpstreamPathTemplate = "/asdf/", AuthenticationOptions = new FileAuthenticationOptions() { AuthenticationProviderKey = "Test" @@ -131,12 +161,12 @@ namespace Ocelot.UnitTests.Configuration new FileReRoute { DownstreamPathTemplate = "/api/products/", - UpstreamPathTemplate = "http://asdf.com" + UpstreamPathTemplate = "/asdf/" }, new FileReRoute { DownstreamPathTemplate = "http://www.bbc.co.uk", - UpstreamPathTemplate = "http://asdf.com" + UpstreamPathTemplate = "/asdf/" } } })) @@ -171,6 +201,14 @@ namespace Ocelot.UnitTests.Configuration _result.Data.Errors[0].ShouldBeOfType(); } + private void GivenTheAuthSchemeExists(string name) + { + _provider.Setup(x => x.GetAllSchemesAsync()).ReturnsAsync(new List + { + new AuthenticationScheme(name, name, typeof(TestHandler)) + }); + } + private class TestOptions : AuthenticationSchemeOptions { } diff --git a/test/Ocelot.UnitTests/Responder/ErrorsToHttpStatusCodeMapperTests.cs b/test/Ocelot.UnitTests/Responder/ErrorsToHttpStatusCodeMapperTests.cs index 426fd1d4..c1165bc4 100644 --- a/test/Ocelot.UnitTests/Responder/ErrorsToHttpStatusCodeMapperTests.cs +++ b/test/Ocelot.UnitTests/Responder/ErrorsToHttpStatusCodeMapperTests.cs @@ -120,7 +120,7 @@ namespace Ocelot.UnitTests.Responder // If this test fails then it's because the number of error codes has changed. // You should make the appropriate changes to the test cases here to ensure // they cover all the error codes, and then modify this assertion. - Enum.GetNames(typeof(OcelotErrorCode)).Length.ShouldBe(30, "Looks like the number of error codes has changed. Do you need to modify ErrorsToHttpStatusCodeMapper?"); + Enum.GetNames(typeof(OcelotErrorCode)).Length.ShouldBe(31, "Looks like the number of error codes has changed. Do you need to modify ErrorsToHttpStatusCodeMapper?"); } private void ShouldMapErrorToStatusCode(OcelotErrorCode errorCode, HttpStatusCode expectedHttpStatusCode)