aboutsummaryrefslogtreecommitdiff
path: root/lib/VNLib.Plugins.Extensions.Loading/src/Routing
diff options
context:
space:
mode:
Diffstat (limited to 'lib/VNLib.Plugins.Extensions.Loading/src/Routing')
-rw-r--r--lib/VNLib.Plugins.Extensions.Loading/src/Routing/EndpointLogNameAttribute.cs41
-rw-r--r--lib/VNLib.Plugins.Extensions.Loading/src/Routing/EndpointPathAttribute.cs40
-rw-r--r--lib/VNLib.Plugins.Extensions.Loading/src/Routing/RoutingExtensions.cs82
3 files changed, 158 insertions, 5 deletions
diff --git a/lib/VNLib.Plugins.Extensions.Loading/src/Routing/EndpointLogNameAttribute.cs b/lib/VNLib.Plugins.Extensions.Loading/src/Routing/EndpointLogNameAttribute.cs
new file mode 100644
index 0000000..d47be22
--- /dev/null
+++ b/lib/VNLib.Plugins.Extensions.Loading/src/Routing/EndpointLogNameAttribute.cs
@@ -0,0 +1,41 @@
+/*
+* Copyright (c) 2024 Vaughn Nugent
+*
+* Library: VNLib
+* Package: VNLib.Plugins.Extensions.Loading
+* File: ConfigurationExtensions.cs
+*
+* ConfigurationExtensions.cs is part of VNLib.Plugins.Extensions.Loading which is part of the larger
+* VNLib collection of libraries and utilities.
+*
+* VNLib.Plugins.Extensions.Loading is free software: you can redistribute it and/or modify
+* it under the terms of the GNU Affero General Public License as
+* published by the Free Software Foundation, either version 3 of the
+* License, or (at your option) any later version.
+*
+* VNLib.Plugins.Extensions.Loading is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Affero General Public License for more details.
+*
+* You should have received a copy of the GNU Affero General Public License
+* along with this program. If not, see https://www.gnu.org/licenses/.
+*/
+
+using System;
+
+namespace VNLib.Plugins.Extensions.Loading.Routing
+{
+
+ /// <summary>
+ /// Defines configurable settings for an endpoint
+ /// </summary>
+ [AttributeUsage(AttributeTargets.Class)]
+ public sealed class EndpointLogNameAttribute(string logName) : Attribute
+ {
+ /// <summary>
+ /// The name of the logging scope for the endpoint
+ /// </summary>
+ public string LogName { get; } = logName;
+ }
+}
diff --git a/lib/VNLib.Plugins.Extensions.Loading/src/Routing/EndpointPathAttribute.cs b/lib/VNLib.Plugins.Extensions.Loading/src/Routing/EndpointPathAttribute.cs
new file mode 100644
index 0000000..a5ab355
--- /dev/null
+++ b/lib/VNLib.Plugins.Extensions.Loading/src/Routing/EndpointPathAttribute.cs
@@ -0,0 +1,40 @@
+/*
+* Copyright (c) 2024 Vaughn Nugent
+*
+* Library: VNLib
+* Package: VNLib.Plugins.Extensions.Loading
+* File: ConfigurationExtensions.cs
+*
+* ConfigurationExtensions.cs is part of VNLib.Plugins.Extensions.Loading which is part of the larger
+* VNLib collection of libraries and utilities.
+*
+* VNLib.Plugins.Extensions.Loading is free software: you can redistribute it and/or modify
+* it under the terms of the GNU Affero General Public License as
+* published by the Free Software Foundation, either version 3 of the
+* License, or (at your option) any later version.
+*
+* VNLib.Plugins.Extensions.Loading is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Affero General Public License for more details.
+*
+* You should have received a copy of the GNU Affero General Public License
+* along with this program. If not, see https://www.gnu.org/licenses/.
+*/
+
+using System;
+
+namespace VNLib.Plugins.Extensions.Loading.Routing
+{
+ /// <summary>
+ /// Defines configurable settings for an endpoint
+ /// </summary>
+ [AttributeUsage(AttributeTargets.Class)]
+ public sealed class EndpointPathAttribute(string path) : Attribute
+ {
+ /// <summary>
+ /// Sets the endpoint path (or configuration template if set)
+ /// </summary>
+ public string Path { get; } = path;
+ }
+}
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)