Tolerate leading "~/" or "/" (#509)

This commit is contained in:
Jass Bagga 2018-01-11 13:00:01 -08:00 committed by GitHub
parent 93d20ec78c
commit 57697baedb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 86 additions and 47 deletions

View File

@ -249,7 +249,7 @@ namespace Microsoft.AspNetCore.Routing
=> string.Format(CultureInfo.CurrentCulture, GetString("TemplateRoute_InvalidParameterName"), p0); => string.Format(CultureInfo.CurrentCulture, GetString("TemplateRoute_InvalidParameterName"), p0);
/// <summary> /// <summary>
/// The route template cannot start with a '/' or '~' character. /// The route template cannot start with a '~' character unless followed by a '/'.
/// </summary> /// </summary>
internal static string TemplateRoute_InvalidRouteTemplate internal static string TemplateRoute_InvalidRouteTemplate
{ {
@ -257,7 +257,7 @@ namespace Microsoft.AspNetCore.Routing
} }
/// <summary> /// <summary>
/// The route template cannot start with a '/' or '~' character. /// The route template cannot start with a '~' character unless followed by a '/'.
/// </summary> /// </summary>
internal static string FormatTemplateRoute_InvalidRouteTemplate() internal static string FormatTemplateRoute_InvalidRouteTemplate()
=> GetString("TemplateRoute_InvalidRouteTemplate"); => GetString("TemplateRoute_InvalidRouteTemplate");

View File

@ -169,7 +169,7 @@
<value>The route parameter name '{0}' is invalid. Route parameter names must be non-empty and cannot contain these characters: '{{', '}}', '/'. The '?' character marks a parameter as optional, and can occur only at the end of the parameter. The '*' character marks a parameter as catch-all, and can occur only at the start of the parameter.</value> <value>The route parameter name '{0}' is invalid. Route parameter names must be non-empty and cannot contain these characters: '{{', '}}', '/'. The '?' character marks a parameter as optional, and can occur only at the end of the parameter. The '*' character marks a parameter as catch-all, and can occur only at the start of the parameter.</value>
</data> </data>
<data name="TemplateRoute_InvalidRouteTemplate" xml:space="preserve"> <data name="TemplateRoute_InvalidRouteTemplate" xml:space="preserve">
<value>The route template cannot start with a '/' or '~' character.</value> <value>The route template cannot start with a '~' character unless followed by a '/'.</value>
</data> </data>
<data name="TemplateRoute_MismatchedParameter" xml:space="preserve"> <data name="TemplateRoute_MismatchedParameter" xml:space="preserve">
<value>There is an incomplete parameter in the route template. Check that each '{' character has a matching '}' character.</value> <value>There is an incomplete parameter in the route template. Check that each '{' character has a matching '}' character.</value>

View File

@ -25,12 +25,9 @@ namespace Microsoft.AspNetCore.Routing.Template
routeTemplate = String.Empty; routeTemplate = String.Empty;
} }
if (IsInvalidRouteTemplate(routeTemplate)) var trimmedRouteTemplate = TrimPrefix(routeTemplate);
{
throw new ArgumentException(Resources.TemplateRoute_InvalidRouteTemplate, nameof(routeTemplate));
}
var context = new TemplateParserContext(routeTemplate); var context = new TemplateParserContext(trimmedRouteTemplate);
var segments = new List<TemplateSegment>(); var segments = new List<TemplateSegment>();
while (context.Next()) while (context.Next())
@ -61,6 +58,23 @@ namespace Microsoft.AspNetCore.Routing.Template
} }
} }
private static string TrimPrefix(string routeTemplate)
{
if (routeTemplate.StartsWith("~/", StringComparison.Ordinal))
{
return routeTemplate.Substring(2);
}
else if (routeTemplate.StartsWith("/", StringComparison.Ordinal))
{
return routeTemplate.Substring(1);
}
else if (routeTemplate.StartsWith("~", StringComparison.Ordinal))
{
throw new ArgumentException(Resources.TemplateRoute_InvalidRouteTemplate, nameof(routeTemplate));
}
return routeTemplate;
}
private static bool ParseSegment(TemplateParserContext context, List<TemplateSegment> segments) private static bool ParseSegment(TemplateParserContext context, List<TemplateSegment> segments)
{ {
Debug.Assert(context != null); Debug.Assert(context != null);

View File

@ -691,6 +691,28 @@ namespace Microsoft.AspNetCore.Routing.Template.Tests
"/UrlEncode[[v1]]"); "/UrlEncode[[v1]]");
} }
[Fact]
public void GetUrlWithLeadingTildeSlash()
{
RunTest(
"~/foo",
null,
null,
new RouteValueDictionary(new { }),
"/UrlEncode[[foo]]");
}
[Fact]
public void GetUrlWithLeadingSlash()
{
RunTest(
"/foo",
null,
null,
new RouteValueDictionary(new { }),
"/UrlEncode[[foo]]");
}
[Fact] [Fact]
public void TemplateBinder_KeepsExplicitlySuppliedRouteValues_OnFailedRouetMatch() public void TemplateBinder_KeepsExplicitlySuppliedRouteValues_OnFailedRouetMatch()
{ {

View File

@ -655,6 +655,18 @@ namespace Microsoft.AspNetCore.Routing.Template.Tests
"Parameter name: routeTemplate"); "Parameter name: routeTemplate");
} }
[Theory]
[InlineData("/foo")]
[InlineData("~/foo")]
public void ValidTemplate_CanStartWithSlashOrTildeSlash(string routeTemplate)
{
// Arrange & Act
var template = TemplateParser.Parse(routeTemplate);
// Assert
Assert.Equal(routeTemplate, template.TemplateText);
}
[Fact] [Fact]
public void InvalidTemplate_CannotHaveConsecutiveOpenBrace() public void InvalidTemplate_CannotHaveConsecutiveOpenBrace()
{ {
@ -768,21 +780,12 @@ namespace Microsoft.AspNetCore.Routing.Template.Tests
"Parameter name: routeTemplate"); "Parameter name: routeTemplate");
} }
[Fact]
public void InvalidTemplate_CannotStartWithSlash()
{
ExceptionAssert.Throws<ArgumentException>(
() => TemplateParser.Parse("/foo"),
"The route template cannot start with a '/' or '~' character." + Environment.NewLine +
"Parameter name: routeTemplate");
}
[Fact] [Fact]
public void InvalidTemplate_CannotStartWithTilde() public void InvalidTemplate_CannotStartWithTilde()
{ {
ExceptionAssert.Throws<ArgumentException>( ExceptionAssert.Throws<ArgumentException>(
() => TemplateParser.Parse("~foo"), () => TemplateParser.Parse("~foo"),
"The route template cannot start with a '/' or '~' character." + Environment.NewLine + "The route template cannot start with a '~' character unless followed by a '/'." + Environment.NewLine +
"Parameter name: routeTemplate"); "Parameter name: routeTemplate");
} }