#534 fixed failing tests for this issue (#575)

This commit is contained in:
Tom Pallister 2018-08-25 12:32:56 +01:00 committed by GitHub
parent 00a600064d
commit b0bdeb9402
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 676 additions and 596 deletions

View File

@ -7,6 +7,7 @@ namespace Ocelot.Configuration.Creator
public class UpstreamTemplatePatternCreator : IUpstreamTemplatePatternCreator public class UpstreamTemplatePatternCreator : IUpstreamTemplatePatternCreator
{ {
private const string RegExMatchOneOrMoreOfEverything = ".+"; private const string RegExMatchOneOrMoreOfEverything = ".+";
private const string RegExMatchOneOrMoreOfEverythingUntilNextForwardSlash = "[^/]+";
private const string RegExMatchEndString = "$"; private const string RegExMatchEndString = "$";
private const string RegExIgnoreCase = "(?i)"; private const string RegExIgnoreCase = "(?i)";
private const string RegExForwardSlashOnly = "^/$"; private const string RegExForwardSlashOnly = "^/$";
@ -16,7 +17,6 @@ namespace Ocelot.Configuration.Creator
{ {
var upstreamTemplate = reRoute.UpstreamPathTemplate; var upstreamTemplate = reRoute.UpstreamPathTemplate;
var placeholders = new List<string>(); var placeholders = new List<string>();
for (var i = 0; i < upstreamTemplate.Length; i++) for (var i = 0; i < upstreamTemplate.Length; i++)
@ -44,9 +44,18 @@ namespace Ocelot.Configuration.Creator
upstreamTemplate = upstreamTemplate.Replace("?", "\\?"); upstreamTemplate = upstreamTemplate.Replace("?", "\\?");
} }
foreach (var placeholder in placeholders) for (int i = 0; i < placeholders.Count; i++)
{ {
upstreamTemplate = upstreamTemplate.Replace(placeholder, RegExMatchOneOrMoreOfEverything); 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 == "/") if (upstreamTemplate == "/")

View File

@ -21,6 +21,41 @@ namespace Ocelot.AcceptanceTests
_steps = new Steps(); _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] [Fact]
public void should_return_response_404_when_no_configuration_at_all() public void should_return_response_404_when_no_configuration_at_all()
{ {

View File

@ -18,6 +18,22 @@ namespace Ocelot.UnitTests.Configuration
_creator = new UpstreamTemplatePatternCreator(); _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] [Fact]
public void should_use_re_route_priority() public void should_use_re_route_priority()
{ {
@ -124,7 +140,7 @@ namespace Ocelot.UnitTests.Configuration
this.Given(x => x.GivenTheFollowingFileReRoute(fileReRoute)) this.Given(x => x.GivenTheFollowingFileReRoute(fileReRoute))
.When(x => x.WhenICreateTheTemplatePattern()) .When(x => x.WhenICreateTheTemplatePattern())
.Then(x => x.ThenTheFollowingIsReturned("^/api/products/.+/variants/.+$")) .Then(x => x.ThenTheFollowingIsReturned("^/api/products/[^/]+/variants/.+$"))
.And(x => ThenThePriorityIs(1)) .And(x => ThenThePriorityIs(1))
.BDDfy(); .BDDfy();
} }
@ -140,7 +156,7 @@ namespace Ocelot.UnitTests.Configuration
this.Given(x => x.GivenTheFollowingFileReRoute(fileReRoute)) this.Given(x => x.GivenTheFollowingFileReRoute(fileReRoute))
.When(x => x.WhenICreateTheTemplatePattern()) .When(x => x.WhenICreateTheTemplatePattern())
.Then(x => x.ThenTheFollowingIsReturned("^/api/products/.+/variants/.+(/|)$")) .Then(x => x.ThenTheFollowingIsReturned("^/api/products/[^/]+/variants/[^/]+(/|)$"))
.And(x => ThenThePriorityIs(1)) .And(x => ThenThePriorityIs(1))
.BDDfy(); .BDDfy();
} }
@ -186,7 +202,7 @@ namespace Ocelot.UnitTests.Configuration
this.Given(x => x.GivenTheFollowingFileReRoute(fileReRoute)) this.Given(x => x.GivenTheFollowingFileReRoute(fileReRoute))
.When(x => x.WhenICreateTheTemplatePattern()) .When(x => x.WhenICreateTheTemplatePattern())
.Then(x => x.ThenTheFollowingIsReturned("^/.+/products/variants/.+(/|)$")) .Then(x => x.ThenTheFollowingIsReturned("^/[^/]+/products/variants/[^/]+(/|)$"))
.And(x => ThenThePriorityIs(1)) .And(x => ThenThePriorityIs(1))
.BDDfy(); .BDDfy();
} }
@ -201,7 +217,7 @@ namespace Ocelot.UnitTests.Configuration
this.Given(x => x.GivenTheFollowingFileReRoute(fileReRoute)) this.Given(x => x.GivenTheFollowingFileReRoute(fileReRoute))
.When(x => x.WhenICreateTheTemplatePattern()) .When(x => x.WhenICreateTheTemplatePattern())
.Then(x => x.ThenTheFollowingIsReturned("^(?i)/api/subscriptions/.+/updates\\?unitId=.+$")) .Then(x => x.ThenTheFollowingIsReturned("^(?i)/api/subscriptions/[^/]+/updates\\?unitId=.+$"))
.And(x => ThenThePriorityIs(1)) .And(x => ThenThePriorityIs(1))
.BDDfy(); .BDDfy();
} }
@ -216,7 +232,7 @@ namespace Ocelot.UnitTests.Configuration
this.Given(x => x.GivenTheFollowingFileReRoute(fileReRoute)) this.Given(x => x.GivenTheFollowingFileReRoute(fileReRoute))
.When(x => x.WhenICreateTheTemplatePattern()) .When(x => x.WhenICreateTheTemplatePattern())
.Then(x => x.ThenTheFollowingIsReturned("^(?i)/api/subscriptions/.+/updates\\?unitId=.+&productId=.+$")) .Then(x => x.ThenTheFollowingIsReturned("^(?i)/api/subscriptions/[^/]+/updates\\?unitId=.+&productId=.+$"))
.And(x => ThenThePriorityIs(1)) .And(x => ThenThePriorityIs(1))
.BDDfy(); .BDDfy();
} }

View File

@ -20,6 +20,26 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder.UrlMatcher
_urlMatcher = new RegExUrlMatcher(); _urlMatcher = new RegExUrlMatcher();
} }
[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] [Fact]
public void should_match_path_with_no_query_string() public void should_match_path_with_no_query_string()
{ {
@ -36,7 +56,7 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder.UrlMatcher
[Fact] [Fact]
public void should_match_query_string() public void should_match_query_string()
{ {
const string regExForwardSlashAndOnePlaceHolder = "^(?i)/api/subscriptions/.+/updates\\?unitId=.+$"; const string regExForwardSlashAndOnePlaceHolder = "^(?i)/api/subscriptions/[^/]+/updates\\?unitId=.+$";
this.Given(x => x.GivenIHaveAUpstreamPath("/api/subscriptions/1/updates")) this.Given(x => x.GivenIHaveAUpstreamPath("/api/subscriptions/1/updates"))
.And(_ => GivenIHaveAQueryString("?unitId=2")) .And(_ => GivenIHaveAQueryString("?unitId=2"))
@ -50,7 +70,7 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder.UrlMatcher
[Fact] [Fact]
public void should_match_query_string_with_multiple_params() public void should_match_query_string_with_multiple_params()
{ {
const string regExForwardSlashAndOnePlaceHolder = "^(?i)/api/subscriptions/.+/updates\\?unitId=.+&productId=.+$"; const string regExForwardSlashAndOnePlaceHolder = "^(?i)/api/subscriptions/[^/]+/updates\\?unitId=.+&productId=.+$";
this.Given(x => x.GivenIHaveAUpstreamPath("/api/subscriptions/1/updates?unitId=2")) this.Given(x => x.GivenIHaveAUpstreamPath("/api/subscriptions/1/updates?unitId=2"))
.And(_ => GivenIHaveAQueryString("?unitId=2&productId=2")) .And(_ => GivenIHaveAQueryString("?unitId=2&productId=2"))
@ -87,7 +107,7 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder.UrlMatcher
public void should_not_match_issue_134() public void should_not_match_issue_134()
{ {
this.Given(x => x.GivenIHaveAUpstreamPath("/api/vacancy/1/")) this.Given(x => x.GivenIHaveAUpstreamPath("/api/vacancy/1/"))
.And(x => x.GivenIHaveAnUpstreamUrlTemplatePattern("^(?i)/vacancy/.+/$")) .And(x => x.GivenIHaveAnUpstreamUrlTemplatePattern("^(?i)/vacancy/[^/]+/$"))
.When(x => x.WhenIMatchThePaths()) .When(x => x.WhenIMatchThePaths())
.And(x => x.ThenTheResultIsFalse()) .And(x => x.ThenTheResultIsFalse())
.BDDfy(); .BDDfy();
@ -177,7 +197,7 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder.UrlMatcher
public void can_match_down_stream_url_with_downstream_template_with_two_place_holders() public void can_match_down_stream_url_with_downstream_template_with_two_place_holders()
{ {
this.Given(x => x.GivenIHaveAUpstreamPath("api/product/products/1/2")) this.Given(x => x.GivenIHaveAUpstreamPath("api/product/products/1/2"))
.Given(x => x.GivenIHaveAnUpstreamUrlTemplatePattern("^api/product/products/.+/.+$")) .Given(x => x.GivenIHaveAnUpstreamUrlTemplatePattern("^api/product/products/[^/]+/.+$"))
.When(x => x.WhenIMatchThePaths()) .When(x => x.WhenIMatchThePaths())
.Then(x => x.ThenTheResultIsTrue()) .Then(x => x.ThenTheResultIsTrue())
.BDDfy(); .BDDfy();
@ -187,7 +207,7 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder.UrlMatcher
public void can_match_down_stream_url_with_downstream_template_with_two_place_holders_seperated_by_something() 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")) this.Given(x => x.GivenIHaveAUpstreamPath("api/product/products/1/categories/2"))
.And(x => x.GivenIHaveAnUpstreamUrlTemplatePattern("^api/product/products/.+/categories/.+$")) .And(x => x.GivenIHaveAnUpstreamUrlTemplatePattern("^api/product/products/[^/]+/categories/.+$"))
.When(x => x.WhenIMatchThePaths()) .When(x => x.WhenIMatchThePaths())
.Then(x => x.ThenTheResultIsTrue()) .Then(x => x.ThenTheResultIsTrue())
.BDDfy(); .BDDfy();
@ -197,7 +217,7 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder.UrlMatcher
public void can_match_down_stream_url_with_downstream_template_with_three_place_holders_seperated_by_something() 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")) this.Given(x => x.GivenIHaveAUpstreamPath("api/product/products/1/categories/2/variant/123"))
.And(x => x.GivenIHaveAnUpstreamUrlTemplatePattern("^api/product/products/.+/categories/.+/variant/.+$")) .And(x => x.GivenIHaveAnUpstreamUrlTemplatePattern("^api/product/products/[^/]+/categories/[^/]+/variant/.+$"))
.When(x => x.WhenIMatchThePaths()) .When(x => x.WhenIMatchThePaths())
.Then(x => x.ThenTheResultIsTrue()) .Then(x => x.ThenTheResultIsTrue())
.BDDfy(); .BDDfy();
@ -207,7 +227,7 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder.UrlMatcher
public void can_match_down_stream_url_with_downstream_template_with_three_place_holders() 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/")) this.Given(x => x.GivenIHaveAUpstreamPath("api/product/products/1/categories/2/variant/"))
.And(x => x.GivenIHaveAnUpstreamUrlTemplatePattern("^api/product/products/.+/categories/.+/variant/$")) .And(x => x.GivenIHaveAnUpstreamUrlTemplatePattern("^api/product/products/[^/]+/categories/[^/]+/variant/$"))
.When(x => x.WhenIMatchThePaths()) .When(x => x.WhenIMatchThePaths())
.Then(x => x.ThenTheResultIsTrue()) .Then(x => x.ThenTheResultIsTrue())
.BDDfy(); .BDDfy();
@ -217,7 +237,7 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder.UrlMatcher
public void should_ignore_case_sensitivity() public void should_ignore_case_sensitivity()
{ {
this.Given(x => x.GivenIHaveAUpstreamPath("API/product/products/1/categories/2/variant/")) this.Given(x => x.GivenIHaveAUpstreamPath("API/product/products/1/categories/2/variant/"))
.And(x => x.GivenIHaveAnUpstreamUrlTemplatePattern("^(?i)api/product/products/.+/categories/.+/variant/$")) .And(x => x.GivenIHaveAnUpstreamUrlTemplatePattern("^(?i)api/product/products/[^/]+/categories/[^/]+/variant/$"))
.When(x => x.WhenIMatchThePaths()) .When(x => x.WhenIMatchThePaths())
.Then(x => x.ThenTheResultIsTrue()) .Then(x => x.ThenTheResultIsTrue())
.BDDfy(); .BDDfy();
@ -227,7 +247,7 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder.UrlMatcher
public void should_respect_case_sensitivity() public void should_respect_case_sensitivity()
{ {
this.Given(x => x.GivenIHaveAUpstreamPath("API/product/products/1/categories/2/variant/")) this.Given(x => x.GivenIHaveAUpstreamPath("API/product/products/1/categories/2/variant/"))
.And(x => x.GivenIHaveAnUpstreamUrlTemplatePattern("^api/product/products/.+/categories/.+/variant/$")) .And(x => x.GivenIHaveAnUpstreamUrlTemplatePattern("^api/product/products/[^/]+/categories/[^/]+/variant/$"))
.When(x => x.WhenIMatchThePaths()) .When(x => x.WhenIMatchThePaths())
.Then(x => x.ThenTheResultIsFalse()) .Then(x => x.ThenTheResultIsFalse())
.BDDfy(); .BDDfy();