Skip to content

Commit 2f5ae91

Browse files
committed
Normalize route pattern ending slash
1 parent 96a525f commit 2f5ae91

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
@@ -243,20 +243,12 @@ private static string GetClientIp(HttpContext httpContext)
243243
/// <returns>A parameterized route string, always starting with a leading slash</returns>
244244
internal string GetParametrizedRoute(HttpContext context)
245245
{
246-
var routePattern = context.Request.Path.Value;
247-
248-
if (string.IsNullOrEmpty(routePattern))
249-
{
250-
return "/";
251-
}
252-
253-
// Ensure the request path starts with a slash for consistency
254-
routePattern = "/" + routePattern.TrimStart('/');
246+
var routePattern = RouteHelper.NormalizeRoutePattern(context.Request.Path.Value);
255247

256248
// Check for an exact match endpoint
257249
var frameworkRoutes = _endpoints
258250
.OfType<RouteEndpoint>()
259-
.Select(e => GetRoutePattern(e))
251+
.Select(e => RouteHelper.NormalizeRoutePattern(e?.RoutePattern.RawText))
260252
.ToList();
261253

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

Aikido.Zen.DotNetFramework/HttpModules/ContextModule.cs

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

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

243236
var exactEndpoint = frameworkRoutes.FirstOrDefault(rp => rp == routePattern);
@@ -279,16 +272,5 @@ internal string GetParametrizedRoute(HttpContext context)
279272

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

0 commit comments

Comments
 (0)