diff options
author | vnugent <public@vaughnnugent.com> | 2024-06-16 13:16:18 -0400 |
---|---|---|
committer | vnugent <public@vaughnnugent.com> | 2024-06-16 13:16:18 -0400 |
commit | 9bc24801735884e0c03aa00e83804448c466bdf2 (patch) | |
tree | 5b2355805dd99b2922508338992bfb3118b34836 /lib/VNLib.Plugins.Extensions.Loading/src | |
parent | 1229ed75549de1c56aaee42c921acbd96c4d4c9b (diff) |
update plugins array instead of single path
Diffstat (limited to 'lib/VNLib.Plugins.Extensions.Loading/src')
3 files changed, 66 insertions, 13 deletions
diff --git a/lib/VNLib.Plugins.Extensions.Loading/src/ConfigurationExtensions.cs b/lib/VNLib.Plugins.Extensions.Loading/src/ConfigurationExtensions.cs index 0337fbd..3258e27 100644 --- a/lib/VNLib.Plugins.Extensions.Loading/src/ConfigurationExtensions.cs +++ b/lib/VNLib.Plugins.Extensions.Loading/src/ConfigurationExtensions.cs @@ -24,6 +24,7 @@ using System; using System.IO; +using System.Linq; using System.Text.Json; using System.Reflection; using System.Collections.Generic; @@ -71,7 +72,7 @@ namespace VNLib.Plugins.Extensions.Loading public const string S3_SECRET_KEY = "s3_secret"; public const string PLUGIN_ASSET_KEY = "assets"; public const string PLUGINS_HOST_KEY = "plugins"; - public const string PLUGIN_PATH_KEY = "path"; + public const string PLUGIN_PATHS_KEY = "paths"; /// <summary> /// Retrieves a top level configuration dictionary of elements for the specified type. @@ -492,16 +493,16 @@ namespace VNLib.Plugins.Extensions.Loading /// </summary> /// <param name="plugin"></param> /// <returns>The absolute path to the directory containing all plugins</returns> - public static string GetPluginsPath(this PluginBase plugin) + public static string[] GetPluginSearchDirs(this PluginBase plugin) { //Get global plugin config element IConfigScope config = plugin.GetConfig(PLUGINS_HOST_KEY); //Get the plugins path or throw because it should ALWAYS be defined if this method is called - string pluginsPath = config[PLUGIN_PATH_KEY].GetString()!; - - //Get absolute path - return Path.GetFullPath(pluginsPath); + return config[PLUGIN_PATHS_KEY].EnumerateArray() + .Select(static p => p.GetString()!) + .Select(Path.GetFullPath) //Get absolute file paths + .ToArray(); } } } diff --git a/lib/VNLib.Plugins.Extensions.Loading/src/LoadingExtensions.cs b/lib/VNLib.Plugins.Extensions.Loading/src/LoadingExtensions.cs index b65c5e6..c62dff9 100644 --- a/lib/VNLib.Plugins.Extensions.Loading/src/LoadingExtensions.cs +++ b/lib/VNLib.Plugins.Extensions.Loading/src/LoadingExtensions.cs @@ -104,22 +104,30 @@ namespace VNLib.Plugins.Extensions.Loading plugin.ThrowIfUnloaded(); ArgumentNullException.ThrowIfNull(assemblyName); + string[] searchDirs; + /* * Allow an assets directory to limit the scope of the search for the desired * assembly, otherwise search all plugins directories */ string? assetDir = plugin.GetAssetsPath(); - assetDir ??= plugin.GetPluginsPath(); + + searchDirs = assetDir is null + ? plugin.GetPluginSearchDirs() + : ([assetDir]); /* - * This should never happen since this method can only be called from a - * plugin context, which means this path was used to load the current plugin - */ - ArgumentNullException.ThrowIfNull(assetDir, "No plugin asset directory is defined for the current host configuration, this is likely a bug"); + * This should never happen since this method can only be called from a + * plugin context, which means this path was used to load the current plugin + */ + if (searchDirs.Length == 0) + { + throw new ArgumentException("No plugin asset directory is defined for the current host configuration, this is likely a bug"); + } //Get the first file that matches the search file - return Directory.EnumerateFiles(assetDir, assemblyName, searchOption).FirstOrDefault(); + return searchDirs.SelectMany(d => Directory.EnumerateFiles(d, assemblyName, searchOption)).FirstOrDefault(); } /// <summary> diff --git a/lib/VNLib.Plugins.Extensions.Loading/src/Routing/RoutingExtensions.cs b/lib/VNLib.Plugins.Extensions.Loading/src/Routing/RoutingExtensions.cs index a1817a8..ab7dc58 100644 --- a/lib/VNLib.Plugins.Extensions.Loading/src/Routing/RoutingExtensions.cs +++ b/lib/VNLib.Plugins.Extensions.Loading/src/Routing/RoutingExtensions.cs @@ -24,10 +24,18 @@ using System; using System.Reflection; +using System.Threading.Tasks; +using System.Collections.Frozen; using System.Collections.Generic; using System.Runtime.CompilerServices; +using VNLib.Net.Http; +using VNLib.Utils.Logging; 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 { @@ -97,7 +105,7 @@ namespace VNLib.Plugins.Extensions.Loading.Routing _ = _pluginRefs.TryGetValue(ep, out PluginBase? pBase); return pBase ?? throw new InvalidOperationException("Endpoint was not dynamically routed"); } - + private sealed class EndpointCollection : IVirtualEndpointDefinition { @@ -106,5 +114,41 @@ namespace VNLib.Plugins.Extensions.Loading.Routing ///<inheritdoc/> IEnumerable<IEndpoint> IVirtualEndpointDefinition.GetEndpoints() => Endpoints; } + + private delegate ValueTask<VfReturnType> EndpointWorkFunc(HttpEntity entity); + + sealed record class HttpControllerEndpoint(MethodInfo MethodInfo, HttpEndpointAttribute Attr) + { + public string Path => Attr.Path; + + public HttpMethod Method => Attr.Method; + + public EndpointWorkFunc Func { get; } = MethodInfo.CreateDelegate<EndpointWorkFunc>(); + } + + private sealed class EndpointWrapper + : ResourceEndpointBase + { + + private readonly FrozenDictionary<HttpMethod, EndpointWorkFunc> _wrappers; + + public EndpointWrapper(FrozenDictionary<HttpMethod, EndpointWorkFunc> table, string path, ILogProvider log) + { + _wrappers = table; + InitPathAndLog(path, log); + } + + protected override ValueTask<VfReturnType> OnProcessAsync(HttpEntity entity) + { + ref readonly EndpointWorkFunc func = ref _wrappers.GetValueRefOrNullRef(entity.Server.Method); + + if (Unsafe.IsNullRef(in func)) + { + return ValueTask.FromResult(VfReturnType.ProcessAsFile); + } + + return func(entity); + } + } } } |