From 685d65cff1c91d302096353f85805a91c6fe7950 Mon Sep 17 00:00:00 2001
From: Vincent van Proosdij <164303+vip32@users.noreply.github.com>
Date: Fri, 11 Oct 2024 00:32:01 +0200
Subject: [PATCH] Better module matching for inbound http resuests
(modulecontextaccessors)
---
.../Accessors/RequestModuleContextAccessor.cs | 49 ++++++++++++++++---
.../TypeNameModuleContextAccessor.cs | 27 ++++++++++
2 files changed, 70 insertions(+), 6 deletions(-)
diff --git a/src/Common.Modules/Accessors/RequestModuleContextAccessor.cs b/src/Common.Modules/Accessors/RequestModuleContextAccessor.cs
index 32b125bd..c97f623f 100644
--- a/src/Common.Modules/Accessors/RequestModuleContextAccessor.cs
+++ b/src/Common.Modules/Accessors/RequestModuleContextAccessor.cs
@@ -7,11 +7,27 @@ namespace BridgingIT.DevKit.Common;
using Microsoft.AspNetCore.Http;
+///
+/// Manages the context for request modules by providing functionality to
+/// find the appropriate module based on the provided HTTP request.
+///
public class RequestModuleContextAccessor : IRequestModuleContextAccessor
{
+ ///
+ /// A variable representing a collection of modules within the application framework.
+ /// Utilized within RequestModuleContextAccessor for providing functionalities such as finding
+ /// the appropriate module based on a provided HTTP request.
+ ///
private readonly IEnumerable modules;
+
+ ///
+ /// An array of string paths used to identify specific modules within HTTP requests.
+ ///
private readonly string[] pathSelectors = ["/api/v", "/api"];
+ ///
+ /// Provides functionality for accessing the appropriate module based on the provided HTTP request.
+ ///
public RequestModuleContextAccessor(IEnumerable modules = null, string[] pathSelectors = null)
{
this.modules = modules.SafeNull();
@@ -22,6 +38,11 @@ public RequestModuleContextAccessor(IEnumerable modules = null, string[
}
}
+ ///
+ /// Finds the appropriate module based on the provided HTTP request.
+ ///
+ /// The HTTP request used to determine the module.
+ /// The module associated with the HTTP request, or null if no module is found.
public virtual IModule Find(HttpRequest request)
{
request.Headers.TryGetValue(ModuleConstants.ModuleNameKey, out var moduleName);
@@ -31,14 +52,30 @@ public virtual IModule Find(HttpRequest request)
moduleName = request.Query[ModuleConstants.ModuleNameKey];
}
- foreach (var pathSelector in this.pathSelectors.SafeNull())
+ if (string.IsNullOrWhiteSpace(moduleName))
+ {
+ foreach (var module in this.modules) // check if modulename is part of path
+ {
+ if (request.Path.Value != null &&
+ request.Path.Value.Contains($"/{module.Name}/", StringComparison.OrdinalIgnoreCase))
+ {
+ moduleName = module.Name;
+ break;
+ }
+ }
+ }
+
+ if (string.IsNullOrWhiteSpace(moduleName))
{
- if (string.IsNullOrWhiteSpace(moduleName) &&
- request.Path.Value.Contains(pathSelector, StringComparison.OrdinalIgnoreCase))
+ foreach (var pathSelector in this.pathSelectors.SafeNull()) // check if module is found with the path selectors
{
- // TODO: source generated regex? api/MODULENAME/controller
- moduleName = request.Path.Value.SliceFrom(pathSelector);
- moduleName = moduleName.ToString().SliceFrom("/").SliceTill("/");
+ if (string.IsNullOrWhiteSpace(moduleName) &&
+ request.Path.Value.Contains(pathSelector, StringComparison.OrdinalIgnoreCase))
+ {
+ // TODO: source generated regex? api/MODULENAME/controller
+ moduleName = request.Path.Value.SliceFrom(pathSelector);
+ moduleName = moduleName.ToString().SliceFrom("/").SliceTill("/");
+ }
}
}
diff --git a/src/Common.Modules/Accessors/TypeNameModuleContextAccessor.cs b/src/Common.Modules/Accessors/TypeNameModuleContextAccessor.cs
index 1434736e..dec4a850 100644
--- a/src/Common.Modules/Accessors/TypeNameModuleContextAccessor.cs
+++ b/src/Common.Modules/Accessors/TypeNameModuleContextAccessor.cs
@@ -5,12 +5,34 @@
namespace BridgingIT.DevKit.Common;
+///
+/// TypeNameModuleContextAccessor provides a mechanism to access module contexts based on the type names.
+///
+///
+/// This class implements the interface and allows retrieving modules by their type name.
+/// A customizable delegate function can be used to select the module name from a given type.
+///
public class TypeNameModuleContextAccessor : IModuleContextAccessor
{
+ ///
+ /// A delegate function used to select the module name from a specified type.
+ ///
+ ///
+ /// This function is typically used within the class to extract
+ /// a module name from its representation.
+ /// By default, this function extracts the module name by slicing the type's full name between "Modules."
+ /// and the next "." character.
+ ///
private readonly Func moduleNameSelector = t => t.FullName.SliceFrom("Modules.").SliceTill(".");
+ ///
+ /// Represents an accessor for module context which allows finding modules by their types.
+ ///
private readonly IEnumerable modules;
+ ///
+ /// Provides a mechanism to access module context information by type name.
+ ///
public TypeNameModuleContextAccessor(
IEnumerable modules = null,
Func moduleNameSelector = null)
@@ -23,6 +45,11 @@ public TypeNameModuleContextAccessor(
}
}
+ ///
+ /// Finds an IModule instance that corresponds to the provided type based on the module name selector.
+ ///
+ /// The type for which the corresponding module needs to be found.
+ /// An IModule instance if a matching module is found; otherwise, null.
public virtual IModule Find(Type type)
{
return this.modules.FirstOrDefault(m => m.Name.SafeEquals(this.moduleNameSelector(type)));