Skip to content

Commit ff8e462

Browse files
authored
Merge pull request #217 from AikidoSec/normalize-route-pattern-ending-slash
Normalize route pattern ending slash
2 parents 09c9750 + 2f5ae91 commit ff8e462

File tree

3 files changed

+20
-46
lines changed

3 files changed

+20
-46
lines changed

Aikido.Zen.Core/Helpers/RouteHelper.cs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,22 @@ public static class RouteHelper
107107
"/.well-known/wot",
108108
};
109109

110+
/// <summary>
111+
/// Normalizes a route pattern string by ensuring it starts with a slash but doesn't end with one.
112+
/// This is because ASP.NET will trim the ending slash in routes to find the original endpoint.
113+
/// </summary>
114+
/// <param name="routePattern">The route pattern string to normalize.</param>
115+
/// <returns>A normalized route pattern string.</returns>
116+
public static string NormalizeRoutePattern(string routePattern)
117+
{
118+
if (string.IsNullOrEmpty(routePattern))
119+
{
120+
return "/";
121+
}
122+
123+
return "/" + routePattern.TrimStart('/').TrimEnd('/');
124+
}
125+
110126
/// <summary>
111127
/// Matches a route pattern against an actual URL path
112128
/// </summary>

Aikido.Zen.DotNetCore/Middleware/ContextMiddleware.cs

Lines changed: 2 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -245,20 +245,12 @@ private static string GetClientIp(HttpContext httpContext)
245245
/// <returns>A parameterized route string, always starting with a leading slash</returns>
246246
internal string GetParametrizedRoute(HttpContext context)
247247
{
248-
var routePattern = context.Request.Path.Value;
249-
250-
if (string.IsNullOrEmpty(routePattern))
251-
{
252-
return "/";
253-
}
254-
255-
// Ensure the request path starts with a slash for consistency
256-
routePattern = "/" + routePattern.TrimStart('/');
248+
var routePattern = RouteHelper.NormalizeRoutePattern(context.Request.Path.Value);
257249

258250
// Check for an exact match endpoint
259251
var frameworkRoutes = _endpoints
260252
.OfType<RouteEndpoint>()
261-
.Select(e => GetRoutePattern(e))
253+
.Select(e => RouteHelper.NormalizeRoutePattern(e?.RoutePattern.RawText))
262254
.ToList();
263255

264256
var exactEndpoint = frameworkRoutes.FirstOrDefault(rp => rp == routePattern);
@@ -302,21 +294,5 @@ internal string GetParametrizedRoute(HttpContext context)
302294
return routePattern;
303295
}
304296
}
305-
306-
/// <summary>
307-
/// Normalizes an endpoint route pattern string by ensuring it starts with a leading slash.
308-
/// Returns "/" if the endpoint or its pattern is null/empty.
309-
/// </summary>
310-
/// <param name="endpoint">The RouteEndpoint to normalize.</param>
311-
/// <returns>A normalized route pattern string starting with "/".</returns>
312-
private static string GetRoutePattern(RouteEndpoint endpoint)
313-
{
314-
var pattern = endpoint?.RoutePattern.RawText;
315-
if (string.IsNullOrEmpty(pattern))
316-
{
317-
return "/";
318-
}
319-
return "/" + pattern.TrimStart('/');
320-
}
321297
}
322298
}

Aikido.Zen.DotNetFramework/HttpModules/ContextModule.cs

Lines changed: 2 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -227,18 +227,11 @@ private static IDictionary<string, string> FlattenHeaders(System.Collections.Spe
227227
/// <returns>A parameterized route string with a leading slash</returns>
228228
internal string GetParametrizedRoute(HttpContext context)
229229
{
230-
var routePattern = context.Request.Path;
231-
if (string.IsNullOrEmpty(routePattern))
232-
{
233-
return "/";
234-
}
235-
236-
// Ensure the request path starts with a slash for consistency
237-
routePattern = "/" + routePattern.TrimStart('/');
230+
var routePattern = RouteHelper.NormalizeRoutePattern(context.Request.Path);
238231

239232
// Check for an exact match endpoint
240233
var frameworkRoutes = RouteTable.Routes.Cast<RouteBase>()
241-
.Select(route => GetRoutePattern(route))
234+
.Select(route => RouteHelper.NormalizeRoutePattern((route as System.Web.Routing.Route)?.Url))
242235
.ToList();
243236

244237
var exactEndpoint = frameworkRoutes.FirstOrDefault(rp => rp == routePattern);
@@ -280,16 +273,5 @@ internal string GetParametrizedRoute(HttpContext context)
280273

281274
return routePattern;
282275
}
283-
284-
private string GetRoutePattern(RouteBase route)
285-
{
286-
string routePattern = null;
287-
if (route is System.Web.Routing.Route)
288-
{
289-
routePattern = (route as System.Web.Routing.Route).Url;
290-
}
291-
// ensure the leading slash from the route pattern, to ensure we don't distinguish for example between api/users and /api/users
292-
return "/" + routePattern?.TrimStart('/');
293-
}
294276
}
295277
}

0 commit comments

Comments
 (0)