From 89641dc0c0ec9fd0f22e63cda18a9e053f1a31a9 Mon Sep 17 00:00:00 2001 From: nora Date: Thu, 3 Oct 2024 11:35:52 -0400 Subject: [PATCH] query and route params impl --- Managers/RoutesManager.cs | 7 ++++--- Utils/Router.cs | 33 ++++++++++++++++++++++++++++----- 2 files changed, 32 insertions(+), 8 deletions(-) diff --git a/Managers/RoutesManager.cs b/Managers/RoutesManager.cs index c84f808..48e4cc5 100644 --- a/Managers/RoutesManager.cs +++ b/Managers/RoutesManager.cs @@ -31,8 +31,9 @@ public class RoutesManager { var req = ev.Request; var res = ev.Response; var path = req.RawUrl; - var route = _router.MatchRoute(path); - Log.Info($"{req.HttpMethod} {path} {route}"); + var ctx = new Context(new Dictionary(), new Dictionary()); + var route = _router.MatchRoute(path, ref ctx); + Log.Info($"{req.HttpMethod} {path} {route} {string.Join(", ", ctx.QueryParams)}"); if (route is null) { EmptyResponse.Create(ref res, HttpStatusCode.NotFound); return; @@ -40,7 +41,7 @@ public class RoutesManager { var methodName = req.HttpMethod[0] + req.HttpMethod.ToLower().Substring(1); var method = route.GetType().GetMethod(methodName); - method!.Invoke(route, [req, res, new Context(null, null)]); + method!.Invoke(route, [req, res, ctx]); } private void LoadRoutes() { diff --git a/Utils/Router.cs b/Utils/Router.cs index 10e730d..97398d3 100644 --- a/Utils/Router.cs +++ b/Utils/Router.cs @@ -1,8 +1,10 @@ +using System.Text.RegularExpressions; +using Exiled.API.Features; using Mamoru.Routes; namespace Mamoru.Utils; -public record Context(Dictionary? QueryParams, Dictionary? RouteParams); +public record Context(Dictionary QueryParams, Dictionary RouteParams); public class Node(string path, AbstractRoute? route = null) { public readonly List Children = []; @@ -41,16 +43,37 @@ public class Node(string path, AbstractRoute? route = null) { AddRoute(ref route, path.Substring(sep + 1), curr ?? parent.Find(seg)); } - public AbstractRoute? MatchRoute(string path, Node? parent = null) { + public AbstractRoute? MatchRoute(string path, ref Context ctx, Node? parent = null) { path = path.Trim('/'); + string? query = null; + if (path.Contains("?")) { + var p = path.Split('?'); + path = p[0]; + query = "?" + p[1]; + } + parent ??= this; var sep = path.IndexOf('/'); - var seg = sep == -1 ? path : path.Substring(0, sep); - if (string.IsNullOrEmpty(seg)) return MatchRoute(path.Substring(sep + 1), parent); + var seg = sep == -1 ? path.Split('?')[0] : path.Substring(0, sep); + if (string.IsNullOrEmpty(seg)) return MatchRoute(path.Substring(sep + 1), ref ctx, parent); var curr = parent.Find(seg); + var routeParam = curr is null ? parent.Children.FirstOrDefault(node => node.Path.StartsWith(":")) : null; + if (routeParam is not null) { + ctx.RouteParams.Add(routeParam.Path.Substring(1), seg); + curr ??= routeParam; + } + + var queryParams = sep == -1 && query is not null + ? new Regex(@"[\\?&](?([^&=]+))=(?[^&=]+)").Matches(query).Cast().ToArray() + : null; + if (queryParams is not null) { + foreach (var match in queryParams) { + ctx.QueryParams.Add(match.Groups["key"].Value, match.Groups["value"].Value); + } + } if (curr is null) return null; - return sep == -1 ? curr.Route : MatchRoute(path.Substring(sep + 1), curr); + return sep == -1 ? curr.Route : MatchRoute(path.Substring(sep + 1), ref ctx, curr); } } \ No newline at end of file -- 2.45.2