aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLibravatar vnugent <public@vaughnnugent.com>2024-06-16 13:16:18 -0400
committerLibravatar vnugent <public@vaughnnugent.com>2024-06-16 13:16:18 -0400
commit9bc24801735884e0c03aa00e83804448c466bdf2 (patch)
tree5b2355805dd99b2922508338992bfb3118b34836
parent1229ed75549de1c56aaee42c921acbd96c4d4c9b (diff)
update plugins array instead of single path
-rw-r--r--lib/VNLib.Plugins.Extensions.Loading/src/ConfigurationExtensions.cs13
-rw-r--r--lib/VNLib.Plugins.Extensions.Loading/src/LoadingExtensions.cs20
-rw-r--r--lib/VNLib.Plugins.Extensions.Loading/src/Routing/RoutingExtensions.cs46
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);
+ }
+ }
}
}