Added unit test project. Improved route matcher and fixed bugs.
This commit is contained in:
@@ -17,8 +17,8 @@ namespace MontoyaTech.Rest.Net
|
||||
/// ** = anything from this point forward is accepted
|
||||
/// {} = route parameter
|
||||
/// ! = must not match
|
||||
/// || = logical or
|
||||
/// && = logical and
|
||||
/// | = logical or
|
||||
/// & = logical and
|
||||
///
|
||||
/// Note:
|
||||
/// If route parameter doesn't end with /, then the parameter will be the rest of the url.
|
||||
@@ -37,6 +37,18 @@ namespace MontoyaTech.Rest.Net
|
||||
url = url.Trim();
|
||||
syntax = syntax.Trim();
|
||||
|
||||
//If the url starts with http or https remove that so we just have the path left.
|
||||
if (url.StartsWith("http://"))
|
||||
{
|
||||
url = url.Substring(7);
|
||||
url = url.Substring(url.IndexOf('/'));
|
||||
}
|
||||
else if (url.StartsWith("https://"))
|
||||
{
|
||||
url = url.Substring(8);
|
||||
url = url.Substring(url.IndexOf('/'));
|
||||
}
|
||||
|
||||
//Split the url and the syntax into path segments
|
||||
var urlSegments = url.Split('/').Where(segment => segment.Length > 0).Select(segment => segment.Trim()).ToArray();
|
||||
var syntaxSegments = syntax.Split('/').Where(segment => segment.Length > 0).Select(segment => segment.Trim()).ToArray();
|
||||
@@ -47,10 +59,10 @@ namespace MontoyaTech.Rest.Net
|
||||
//If we have no syntax segments this is not a match.
|
||||
else if (syntaxSegments.Length == 0)
|
||||
return false;
|
||||
|
||||
//If we have segments and the url does not then this may not be a match.
|
||||
if (urlSegments.Length == 0 && syntaxSegments[0] == "**")
|
||||
//If the url has no segments but the syntax is a double wild card then this is a match.
|
||||
else if (urlSegments.Length == 0 && syntaxSegments[0] == "**")
|
||||
return true;
|
||||
//If the url has no segments but the syntax is a wildcard then this is a match.
|
||||
else if (urlSegments.Length == 0 && syntaxSegments.Length == 1 && syntaxSegments[0] == "*")
|
||||
return true;
|
||||
|
||||
@@ -64,26 +76,71 @@ namespace MontoyaTech.Rest.Net
|
||||
{
|
||||
var syntaxSegment = syntaxSegments[i];
|
||||
|
||||
var urlSegment = urlSegments[i];
|
||||
|
||||
//If the segments syntax is a double wild card then everything after this is a match.
|
||||
if (syntaxSegment == "**")
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else if (syntaxSegment.StartsWith("{") && syntaxSegment.EndsWith("}") && i + 1 >= syntaxSegments.Length && syntax.EndsWith("/") == false)
|
||||
else
|
||||
{
|
||||
//Special case, syntax ends with a parameter, so recombine the rest of the url and add it as a parameter.
|
||||
var key = syntaxSegment.Substring(1, syntaxSegment.Length - 2);
|
||||
var conditions = new List<string>();
|
||||
var builder = new StringBuilder();
|
||||
for (int c = 0; c < syntaxSegment.Length; c++)
|
||||
{
|
||||
if (syntaxSegment[c] == '|' || syntaxSegment[c] == '&')
|
||||
{
|
||||
conditions.Add(builder.ToString());
|
||||
conditions.Add(syntaxSegment[c].ToString());
|
||||
builder.Clear();
|
||||
}
|
||||
else if (syntaxSegment[c] != ' ')
|
||||
{
|
||||
builder.Append(syntaxSegment[c]);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i2 = i; i2 < urlSegments.Length; i2++)
|
||||
builder.Append(urlSegments[i2]).Append(i2 + 1 < urlSegments.Length ? "/" : "");
|
||||
if (builder.Length > 0)
|
||||
conditions.Add(builder.ToString());
|
||||
|
||||
arguments[argumentIndex++] = builder.ToString();
|
||||
bool match = false;
|
||||
foreach (var condition in conditions)
|
||||
{
|
||||
if (condition == "*")
|
||||
{
|
||||
match = true;
|
||||
}
|
||||
else if (condition == "**")
|
||||
{
|
||||
match = true;
|
||||
}
|
||||
else if (condition.StartsWith("!") && condition.Substring(1) != urlSegment)
|
||||
{
|
||||
match = true;
|
||||
}
|
||||
else if (condition.StartsWith("{") && condition.EndsWith("}"))
|
||||
{
|
||||
arguments[argumentIndex++] = urlSegment;
|
||||
|
||||
return true;
|
||||
}
|
||||
else if (SegmentMatches(urlSegments[i], syntaxSegment, arguments, ref argumentIndex) == false)
|
||||
{
|
||||
return false;
|
||||
match = true;
|
||||
}
|
||||
else if (condition == "&" && !match)
|
||||
{
|
||||
break;
|
||||
}
|
||||
else if (condition == "|" && match)
|
||||
{
|
||||
break;
|
||||
}
|
||||
else if (condition == urlSegment)
|
||||
{
|
||||
match = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!match)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -94,58 +151,5 @@ namespace MontoyaTech.Rest.Net
|
||||
else
|
||||
return true;
|
||||
}
|
||||
|
||||
private static bool SegmentMatches(string segment, string syntax, string[] arguments, ref int argumentIndex)
|
||||
{
|
||||
//Split the syntax into conditions
|
||||
string[] conditions = syntax.Split(' ').Where(condition => condition.Length > 0).ToArray();
|
||||
|
||||
//Based off the matches, see if the segment matches.
|
||||
bool match = false;
|
||||
for (int i = 0; i < conditions.Length; i++)
|
||||
{
|
||||
var condition = conditions[i];
|
||||
|
||||
if (condition == "*")
|
||||
{
|
||||
match = true;
|
||||
}
|
||||
else if (condition == "**")
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else if (condition.StartsWith("!"))
|
||||
{
|
||||
if (condition.Substring(1) == segment)
|
||||
match = false;
|
||||
else
|
||||
match = true;
|
||||
}
|
||||
else if (condition.StartsWith("{") && condition.EndsWith("}"))
|
||||
{
|
||||
var key = condition.Substring(1, condition.Length - 2);
|
||||
|
||||
arguments[argumentIndex++] = segment;
|
||||
|
||||
match = true;
|
||||
}
|
||||
else if (condition == "&&")
|
||||
{
|
||||
if (match == false)
|
||||
return false;
|
||||
}
|
||||
else if (condition == "||")
|
||||
{
|
||||
if (match)
|
||||
return true;
|
||||
}
|
||||
else if (condition == segment)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return match;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user