now matches and returns templates and values@

This commit is contained in:
Tom Gardham-Pallister 2016-07-10 18:49:09 +01:00
parent cea6a557e9
commit 1993915564
5 changed files with 177 additions and 35 deletions

View File

@ -2,6 +2,6 @@ namespace Ocelot.Library.Infrastructure.UrlPathMatcher
{ {
public interface IUrlPathToUrlPathTemplateMatcher public interface IUrlPathToUrlPathTemplateMatcher
{ {
bool Match(string urlPath, string urlPathTemplate); UrlPathMatch Match(string urlPath, string urlPathTemplate);
} }
} }

View File

@ -0,0 +1,13 @@
namespace Ocelot.Library.Infrastructure.UrlPathMatcher
{
public class TemplateVariableNameAndValue
{
public TemplateVariableNameAndValue(string templateVariableName, string templateVariableValue)
{
TemplateVariableName = templateVariableName;
TemplateVariableValue = templateVariableValue;
}
public string TemplateVariableName {get;private set;}
public string TemplateVariableValue {get;private set;}
}
}

View File

@ -0,0 +1,15 @@
using System.Collections.Generic;
namespace Ocelot.Library.Infrastructure.UrlPathMatcher
{
public class UrlPathMatch
{
public UrlPathMatch(bool match, List<TemplateVariableNameAndValue> templateVariableNameAndValues)
{
Match = match;
TemplateVariableNameAndValues = templateVariableNameAndValues;
}
public bool Match {get;private set;}
public List<TemplateVariableNameAndValue> TemplateVariableNameAndValues {get;private set;}
}
}

View File

@ -1,9 +1,14 @@
using System;
using System.Collections.Generic;
namespace Ocelot.Library.Infrastructure.UrlPathMatcher namespace Ocelot.Library.Infrastructure.UrlPathMatcher
{ {
public class UrlPathToUrlPathTemplateMatcher : IUrlPathToUrlPathTemplateMatcher public class UrlPathToUrlPathTemplateMatcher : IUrlPathToUrlPathTemplateMatcher
{ {
public bool Match(string urlPath, string urlPathTemplate) public UrlPathMatch Match(string urlPath, string urlPathTemplate)
{ {
var templateKeysAndValues = new List<TemplateVariableNameAndValue>();
urlPath = urlPath.ToLower(); urlPath = urlPath.ToLower();
urlPathTemplate = urlPathTemplate.ToLower(); urlPathTemplate = urlPathTemplate.ToLower();
@ -16,20 +21,52 @@ namespace Ocelot.Library.Infrastructure.UrlPathMatcher
{ {
if (IsPlaceholder(urlPathTemplate[counterForTemplate])) if (IsPlaceholder(urlPathTemplate[counterForTemplate]))
{ {
var variableName = GetPlaceholderVariableName(urlPathTemplate, counterForTemplate);
var variableValue = GetPlaceholderVariableValue(urlPath, counterForUrl);
var templateVariableNameAndValue = new TemplateVariableNameAndValue(variableName, variableValue);
templateKeysAndValues.Add(templateVariableNameAndValue);
counterForTemplate = GetNextCounterPosition(urlPathTemplate, counterForTemplate, '}'); counterForTemplate = GetNextCounterPosition(urlPathTemplate, counterForTemplate, '}');
counterForUrl = GetNextCounterPosition(urlPath, counterForUrl, '/'); counterForUrl = GetNextCounterPosition(urlPath, counterForUrl, '/');
continue; continue;
} }
else else
{ {
return false; return new UrlPathMatch(false, templateKeysAndValues);
} }
} }
counterForUrl++; counterForUrl++;
} }
return true; return new UrlPathMatch(true, templateKeysAndValues);
} }
private string GetPlaceholderVariableValue(string urlPath, int counterForUrl)
{
var positionOfNextSlash = urlPath.IndexOf('/', counterForUrl);
if(positionOfNextSlash == -1)
{
positionOfNextSlash = urlPath.Length;
}
var variableValue = urlPath.Substring(counterForUrl, positionOfNextSlash - counterForUrl);
return variableValue;
}
private string GetPlaceholderVariableName(string urlPathTemplate, int counterForTemplate)
{
var postitionOfPlaceHolderClosingBracket = urlPathTemplate.IndexOf('}', counterForTemplate) + 1;
var variableName = urlPathTemplate.Substring(counterForTemplate, postitionOfPlaceHolderClosingBracket - counterForTemplate);
return variableName;
}
private int GetNextCounterPosition(string urlTemplate, int counterForTemplate, char delimiter) private int GetNextCounterPosition(string urlTemplate, int counterForTemplate, char delimiter)
{ {
var closingPlaceHolderPositionOnTemplate = urlTemplate.IndexOf(delimiter, counterForTemplate); var closingPlaceHolderPositionOnTemplate = urlTemplate.IndexOf(delimiter, counterForTemplate);

View File

@ -1,3 +1,5 @@
using System.Collections.Generic;
using System.Linq;
using Ocelot.Library.Infrastructure.UrlPathMatcher; using Ocelot.Library.Infrastructure.UrlPathMatcher;
using Shouldly; using Shouldly;
using Xunit; using Xunit;
@ -7,7 +9,9 @@ namespace Ocelot.UnitTests
public class UrlPathToUrlPathTemplateMatcherTests public class UrlPathToUrlPathTemplateMatcherTests
{ {
private IUrlPathToUrlPathTemplateMatcher _urlMapper; private IUrlPathToUrlPathTemplateMatcher _urlMapper;
private string _downstreamPath;
private string _downstreamPathTemplate;
private UrlPathMatch _result;
public UrlPathToUrlPathTemplateMatcherTests() public UrlPathToUrlPathTemplateMatcherTests()
{ {
_urlMapper = new UrlPathToUrlPathTemplateMatcher(); _urlMapper = new UrlPathToUrlPathTemplateMatcher();
@ -16,64 +20,137 @@ namespace Ocelot.UnitTests
[Fact] [Fact]
public void can_match_down_stream_url_with_downstream_template_with_one_query_string_parameter() public void can_match_down_stream_url_with_downstream_template_with_one_query_string_parameter()
{ {
var downstreamUrl = "api/product/products/?soldout=false"; GivenIHaveADownstreamPath("api/product/products/?soldout=false");
var downstreamTemplate = "api/product/products/"; GivenIHaveAnDownstreamPathTemplate("api/product/products/");
var result = _urlMapper.Match(downstreamUrl, downstreamTemplate); WhenIMatchThePaths();
result.ShouldBeTrue(); ThenTheResultIsTrue();
ThenTheTemplatesDictionaryIs(new List<TemplateVariableNameAndValue>());
} }
[Fact] [Fact]
public void can_match_down_stream_url_with_downstream_template_with_one_query_string_parameter_and_one_template() public void can_match_down_stream_url_with_downstream_template_with_one_query_string_parameter_and_one_template()
{ {
var downstreamUrl = "api/product/products/1/variants/?soldout=false"; var expectedTemplates = new List<TemplateVariableNameAndValue>
var downstreamTemplate = "api/product/products/{productId}/variants/"; {
var result = _urlMapper.Match(downstreamUrl, downstreamTemplate); new TemplateVariableNameAndValue("{productid}", "1")
result.ShouldBeTrue(); };
GivenIHaveADownstreamPath("api/product/products/1/variants/?soldout=false");
GivenIHaveAnDownstreamPathTemplate("api/product/products/{productId}/variants/");
WhenIMatchThePaths();
ThenTheResultIsTrue();
ThenTheTemplatesDictionaryIs(expectedTemplates);
} }
[Fact] [Fact]
public void can_match_down_stream_url_with_downstream_template_with_one_place_holder() public void can_match_down_stream_url_with_downstream_template_with_one_place_holder()
{ {
var downstreamUrl = "api/product/products/1"; var expectedTemplates = new List<TemplateVariableNameAndValue>
var downstreamTemplate = "api/product/products/{productId}"; {
var result = _urlMapper.Match(downstreamUrl, downstreamTemplate); new TemplateVariableNameAndValue("{productid}", "1")
result.ShouldBeTrue(); };
GivenIHaveADownstreamPath("api/product/products/1");
GivenIHaveAnDownstreamPathTemplate("api/product/products/{productId}");
WhenIMatchThePaths();
ThenTheResultIsTrue();
ThenTheTemplatesDictionaryIs(expectedTemplates);
} }
[Fact] [Fact]
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()
{ {
var downstreamUrl = "api/product/products/1/2"; var expectedTemplates = new List<TemplateVariableNameAndValue>
var downstreamTemplate = "api/product/products/{productId}/{categoryId}"; {
var result = _urlMapper.Match(downstreamUrl, downstreamTemplate); new TemplateVariableNameAndValue("{productid}", "1"),
result.ShouldBeTrue(); new TemplateVariableNameAndValue("{categoryid}", "2")
};
GivenIHaveADownstreamPath("api/product/products/1/2");
GivenIHaveAnDownstreamPathTemplate("api/product/products/{productId}/{categoryId}");
WhenIMatchThePaths();
ThenTheResultIsTrue();
ThenTheTemplatesDictionaryIs(expectedTemplates);
} }
[Fact] [Fact]
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()
{ {
var downstreamUrl = "api/product/products/1/categories/2"; var expectedTemplates = new List<TemplateVariableNameAndValue>
var downstreamTemplate = "api/product/products/{productId}/categories/{categoryId}"; {
var result = _urlMapper.Match(downstreamUrl, downstreamTemplate); new TemplateVariableNameAndValue("{productid}", "1"),
result.ShouldBeTrue(); new TemplateVariableNameAndValue("{categoryid}", "2")
};
GivenIHaveADownstreamPath("api/product/products/1/categories/2");
GivenIHaveAnDownstreamPathTemplate("api/product/products/{productId}/categories/{categoryId}");
WhenIMatchThePaths();
ThenTheResultIsTrue();
ThenTheTemplatesDictionaryIs(expectedTemplates);
} }
[Fact] [Fact]
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()
{ {
var downstreamUrl = "api/product/products/1/categories/2/variant/123"; var expectedTemplates = new List<TemplateVariableNameAndValue>
var downstreamTemplate = "api/product/products/{productId}/categories/{categoryId}/variant/{variantId}"; {
var result = _urlMapper.Match(downstreamUrl, downstreamTemplate); new TemplateVariableNameAndValue("{productid}", "1"),
result.ShouldBeTrue(); new TemplateVariableNameAndValue("{categoryid}", "2"),
new TemplateVariableNameAndValue("{variantid}", "123")
};
GivenIHaveADownstreamPath("api/product/products/1/categories/2/variant/123");
GivenIHaveAnDownstreamPathTemplate("api/product/products/{productId}/categories/{categoryId}/variant/{variantId}");
WhenIMatchThePaths();
ThenTheResultIsTrue();
ThenTheTemplatesDictionaryIs(expectedTemplates);
} }
[Fact] [Fact]
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()
{ {
var downstreamUrl = "api/product/products/1/categories/2/variant/"; var expectedTemplates = new List<TemplateVariableNameAndValue>
var downstreamTemplate = "api/product/products/{productId}/categories/{categoryId}/variant/"; {
var result = _urlMapper.Match(downstreamUrl, downstreamTemplate); new TemplateVariableNameAndValue("{productid}", "1"),
result.ShouldBeTrue(); new TemplateVariableNameAndValue("{categoryid}", "2")
};
GivenIHaveADownstreamPath("api/product/products/1/categories/2/variant/");
GivenIHaveAnDownstreamPathTemplate("api/product/products/{productId}/categories/{categoryId}/variant/");
WhenIMatchThePaths();
ThenTheResultIsTrue();
ThenTheTemplatesDictionaryIs(expectedTemplates);
}
private void ThenTheTemplatesDictionaryIs(List<TemplateVariableNameAndValue> expectedResults)
{
foreach (var expectedResult in expectedResults)
{
var result = _result.TemplateVariableNameAndValues
.First(t => t.TemplateVariableName == expectedResult.TemplateVariableName);
result.TemplateVariableValue.ShouldBe(expectedResult.TemplateVariableValue);
}
}
private void GivenIHaveADownstreamPath(string downstreamPath)
{
_downstreamPath = downstreamPath;
}
private void GivenIHaveAnDownstreamPathTemplate(string downstreamTemplate)
{
_downstreamPathTemplate = downstreamTemplate;
}
private void WhenIMatchThePaths()
{
_result = _urlMapper.Match(_downstreamPath, _downstreamPathTemplate);
}
private void ThenTheResultIsTrue()
{
_result.Match.ShouldBeTrue();
} }
} }
} }