diff options
Diffstat (limited to 'lib/VNLib.Plugins.Extensions.Loading/src/Routing/RoutingExtensions.cs')
-rw-r--r-- | lib/VNLib.Plugins.Extensions.Loading/src/Routing/RoutingExtensions.cs | 82 |
1 files changed, 77 insertions, 5 deletions
diff --git a/lib/VNLib.Plugins.Extensions.Loading/src/Routing/RoutingExtensions.cs b/lib/VNLib.Plugins.Extensions.Loading/src/Routing/RoutingExtensions.cs index ab7dc58..6665a75 100644 --- a/lib/VNLib.Plugins.Extensions.Loading/src/Routing/RoutingExtensions.cs +++ b/lib/VNLib.Plugins.Extensions.Loading/src/Routing/RoutingExtensions.cs @@ -27,23 +27,24 @@ using System.Reflection; using System.Threading.Tasks; using System.Collections.Frozen; using System.Collections.Generic; +using System.Text.RegularExpressions; using System.Runtime.CompilerServices; using VNLib.Net.Http; using VNLib.Utils.Logging; +using VNLib.Utils.Resources; using VNLib.Plugins.Essentials.Runtime; using VNLib.Plugins.Essentials; using VNLib.Plugins.Essentials.Endpoints; using VNLib.Plugins.Extensions.Loading.Routing.Mvc; - namespace VNLib.Plugins.Extensions.Loading.Routing { /// <summary> /// Provides advanced QOL features to plugin loading /// </summary> - public static class RoutingExtensions + public static partial class RoutingExtensions { private static readonly ConditionalWeakTable<IEndpoint, PluginBase?> _pluginRefs = new(); private static readonly ConditionalWeakTable<PluginBase, EndpointCollection> _pluginEndpoints = new(); @@ -60,11 +61,14 @@ namespace VNLib.Plugins.Extensions.Loading.Routing T endpoint = plugin.CreateService<T>(); //Route the endpoint - plugin.Route(endpoint); + Route(plugin, endpoint); //Store ref to plugin for endpoint _pluginRefs.Add(endpoint, plugin); + //Function that initalizes the endpoint's path and logging variables + InitEndpointSettings(plugin, endpoint); + return endpoint; } @@ -104,17 +108,85 @@ namespace VNLib.Plugins.Extensions.Loading.Routing { _ = _pluginRefs.TryGetValue(ep, out PluginBase? pBase); return pBase ?? throw new InvalidOperationException("Endpoint was not dynamically routed"); - } + } + + private static readonly Regex ConfigSyntaxParser = ParserRegex(); + private delegate void InitFunc(string path, ILogProvider log); + + [GeneratedRegex("{{(.*?)}}", RegexOptions.Compiled)] + private static partial Regex ParserRegex(); + + private static void InitEndpointSettings<T>(PluginBase plugin, T endpoint) where T : IEndpoint + { + //Load optional config + IConfigScope config = plugin.GetConfigForType<T>(); + + ILogProvider logger = plugin.Log; + + EndpointPathAttribute? pathAttr = typeof(T).GetCustomAttribute<EndpointPathAttribute>(); + + /* + * gets the protected function for assigning the endpoint path + * and logger instance. + */ + InitFunc? initPathAndLog = ManagedLibrary.TryGetMethod<InitFunc>(endpoint, "InitPathAndLog", BindingFlags.NonPublic); + + if (pathAttr is null || initPathAndLog is null) + { + return; + } + + string? logName = typeof(T).GetCustomAttribute<EndpointLogNameAttribute>()?.LogName; + + if (!string.IsNullOrWhiteSpace(logName)) + { + logger = plugin.Log.CreateScope(SubsituteValue(logName, config)); + } + try + { + //Invoke init function and pass in variable names + initPathAndLog( + path: SubsituteValue(pathAttr.Path, config), + logger + ); + } + catch (ConfigurationException) + { + throw; + } + catch(Exception e) + { + throw new ConfigurationException($"Failed to initalize endpoint {endpoint.GetType().Name}", e); + } + + static string SubsituteValue(string pathVar, IConfigScope? config) + { + if (config is null) + { + return pathVar; + } + + // Replace the matched pattern with the corresponding value from the dictionary + return ConfigSyntaxParser.Replace(pathVar, match => + { + string varName = match.Groups[1].Value; + + //Get the value from the config scope or return the original variable unmodified + return config.GetValueOrDefault(varName, varName); + }); + } + } private sealed class EndpointCollection : IVirtualEndpointDefinition { public List<IEndpoint> Endpoints { get; } = new(); ///<inheritdoc/> - IEnumerable<IEndpoint> IVirtualEndpointDefinition.GetEndpoints() => Endpoints; + IEnumerable<IEndpoint> IVirtualEndpointDefinition.GetEndpoints() => Endpoints; } + private delegate ValueTask<VfReturnType> EndpointWorkFunc(HttpEntity entity); sealed record class HttpControllerEndpoint(MethodInfo MethodInfo, HttpEndpointAttribute Attr) |