Skip to content

Commit

Permalink
First part of operation refactoring
Browse files Browse the repository at this point in the history
  • Loading branch information
Kaliumhexacyanoferrat committed Oct 15, 2024
1 parent fe17f7d commit d8debf9
Show file tree
Hide file tree
Showing 12 changed files with 286 additions and 153 deletions.
19 changes: 9 additions & 10 deletions Modules/Controllers/Provider/ControllerHandler.cs
Original file line number Diff line number Diff line change
@@ -1,18 +1,19 @@
using System.Reflection;
using System.Text.RegularExpressions;

using GenHTTP.Api.Content;
using GenHTTP.Api.Protocol;

using GenHTTP.Modules.Conversion.Formatters;
using GenHTTP.Modules.Conversion.Serializers;
using GenHTTP.Modules.Reflection;
using GenHTTP.Modules.Reflection.Injectors;
using GenHTTP.Modules.Reflection.Operations;

namespace GenHTTP.Modules.Controllers.Provider;

public sealed partial class ControllerHandler : IHandler
{
private static readonly MethodRouting Empty = new("^(/|)$", true, false);

private static readonly Regex HyphenMatcher = CreateHyphenMatcher();

#region Get-/Setters
Expand Down Expand Up @@ -51,28 +52,26 @@ private IEnumerable<Func<IHandler, MethodHandler>> AnalyzeMethods(Type type, Ser

var arguments = FindPathArguments(method);

var path = DeterminePath(method, arguments);
var path = CreateOperation(method, arguments);

yield return parent => new MethodHandler(parent, method, path, () => Instance, annotation, ResponseProvider.GetResponseAsync, serialization, injection, formatting);
}
}

private static MethodRouting DeterminePath(MethodInfo method, List<string> arguments)
private static Operation CreateOperation(MethodInfo method, List<string> arguments)
{
var pathArgs = string.Join('/', arguments.Select(a => a.ToParameter()));

var isWildcard = PathArguments.CheckWildcardRoute(method.ReturnType);
var pathArguments = string.Join('/', arguments.Select(a => "{" + a + "}"));

if (method.Name == "Index")
{
return pathArgs.Length > 0 ? new MethodRouting($"^/{pathArgs}/", false, isWildcard) : Empty;
return OperationBuilder.Create(pathArguments.Length > 0 ? $"/{pathArguments}/" : null, method);
}

var name = HypenCase(method.Name);

var path = $"^/{name}";
var path = $"/{name}";

return pathArgs.Length > 0 ? new MethodRouting( $"{path}/{pathArgs}/", false, isWildcard) : new MethodRouting($"{path}/", false, isWildcard);
return OperationBuilder.Create(pathArguments.Length > 0 ? $"{path}/{pathArguments}" : $"{path}/", method);
}

private List<string> FindPathArguments(MethodInfo method)
Expand Down
7 changes: 3 additions & 4 deletions Modules/Functional/Provider/InlineHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using GenHTTP.Modules.Conversion.Serializers;
using GenHTTP.Modules.Reflection;
using GenHTTP.Modules.Reflection.Injectors;
using GenHTTP.Modules.Reflection.Operations;

namespace GenHTTP.Modules.Functional.Provider;

Expand Down Expand Up @@ -37,13 +38,11 @@ private IEnumerable<Func<IHandler, MethodHandler>> AnalyzeMethods(List<InlineFun
{
var method = function.Delegate.Method;

var wildcardRoute = PathArguments.CheckWildcardRoute(method.ReturnType);

var path = PathArguments.Route(function.Path, wildcardRoute);
var operation = OperationBuilder.Create(function.Path, method);

var target = function.Delegate.Target ?? throw new InvalidOperationException("Delegate target must not be null");

yield return parent => new MethodHandler(parent, method, path, () => target, function.Configuration, ResponseProvider.GetResponseAsync, formats, injection, formatting);
yield return parent => new MethodHandler(parent, method, operation, () => target, function.Configuration, ResponseProvider.GetResponseAsync, formats, injection, formatting);
}
}

Expand Down
32 changes: 28 additions & 4 deletions Modules/OpenApi/Discovery/MethodHandlerExplorer.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
using GenHTTP.Api.Content;
using System.Text;
using GenHTTP.Api.Content;

using GenHTTP.Modules.Reflection;
using GenHTTP.Modules.Reflection.Operations;

using Microsoft.OpenApi.Models;

Expand All @@ -15,13 +17,13 @@ public void Explore(IHandler handler, List<string> path, OpenApiDocument documen
{
if (handler is MethodHandler methodHandler)
{
var pathItem = GetPathItem(document, path, methodHandler.Routing);
var pathItem = GetPathItem(document, path, methodHandler.Operation);
}
}

private OpenApiPathItem GetPathItem(OpenApiDocument document, List<string> path, MethodRouting route)
private OpenApiPathItem GetPathItem(OpenApiDocument document, List<string> path, Operation operation)
{
var stringPath = $"/{string.Join('/', path)}/{route.ParsedPath}";
var stringPath = BuildPath(operation.Path.Name, path);

document.Paths ??= new();

Expand All @@ -37,4 +39,26 @@ private OpenApiPathItem GetPathItem(OpenApiDocument document, List<string> path,
return newPath;
}

private static string BuildPath(string name, List<string> pathParts)
{
var builder = new StringBuilder("/");

if (pathParts.Count > 0)
{
builder.Append(string.Join('/', pathParts));
builder.Append('/');
}

if (name.Length > 0 && name[0] == '/')
{
builder.Append(name[1..]);
}
else
{
builder.Append(name);
}

return builder.ToString();
}

}
6 changes: 3 additions & 3 deletions Modules/Reflection/MethodCollection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ public MethodCollection(IHandler parent, IEnumerable<Func<IHandler, MethodHandle
if (methods.Count > 1)
{
// if there is only one non-wildcard, use this one
var nonWildcards = methods.Where(m => !m.Routing.IsWildcard).ToList();
var nonWildcards = methods.Where(m => !m.Operation.Path.IsWildcard).ToList();

if (nonWildcards.Count == 1)
{
Expand Down Expand Up @@ -72,7 +72,7 @@ private List<MethodHandler> FindProviders(string path, FlexibleRequestMethod req

foreach (var method in Methods)
{
if (method.Routing.IsIndex && path == "/")
if (method.Operation.Path.IsIndex && path == "/")
{
if (method.Configuration.SupportedMethods.Contains(requestedMethod))
{
Expand All @@ -85,7 +85,7 @@ private List<MethodHandler> FindProviders(string path, FlexibleRequestMethod req
}
else
{
if (method.Routing.ParsedPath.IsMatch(path))
if (method.Operation.Path.Matcher.IsMatch(path))
{
if (method.Configuration.SupportedMethods.Contains(requestedMethod))
{
Expand Down
54 changes: 28 additions & 26 deletions Modules/Reflection/MethodHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
using GenHTTP.Modules.Conversion.Serializers;
using GenHTTP.Modules.Conversion.Serializers.Forms;
using GenHTTP.Modules.Reflection.Injectors;
using GenHTTP.Modules.Reflection.Operations;

namespace GenHTTP.Modules.Reflection;

Expand All @@ -26,34 +27,11 @@ public sealed class MethodHandler : IHandler

private static readonly Type? VoidTaskResult = Type.GetType("System.Threading.Tasks.VoidTaskResult");

#region Initialization

public MethodHandler(IHandler parent, MethodInfo method, MethodRouting routing, Func<object> instanceProvider, IMethodConfiguration metaData,
Func<IRequest, IHandler, object?, Action<IResponseBuilder>?, ValueTask<IResponse?>> responseProvider, SerializationRegistry serialization,
InjectionRegistry injection, FormatterRegistry formatting)
{
Parent = parent;

Method = method;
Configuration = metaData;
InstanceProvider = instanceProvider;

Serialization = serialization;
Injection = injection;
Formatting = formatting;

ResponseProvider = responseProvider;

Routing = routing;
}

#endregion

#region Get-/Setters

public IHandler Parent { get; }

public MethodRouting Routing { get; }
public Operation Operation { get; }

public IMethodConfiguration Configuration { get; }

Expand All @@ -71,6 +49,29 @@ public MethodHandler(IHandler parent, MethodInfo method, MethodRouting routing,

#endregion

#region Initialization

public MethodHandler(IHandler parent, MethodInfo method, Operation operation, Func<object> instanceProvider, IMethodConfiguration metaData,
Func<IRequest, IHandler, object?, Action<IResponseBuilder>?, ValueTask<IResponse?>> responseProvider, SerializationRegistry serialization,
InjectionRegistry injection, FormatterRegistry formatting)
{
Parent = parent;

Method = method;
Configuration = metaData;
InstanceProvider = instanceProvider;

Serialization = serialization;
Injection = injection;
Formatting = formatting;

ResponseProvider = responseProvider;

Operation = operation;
}

#endregion

#region Functionality

public async ValueTask<IResponse?> HandleAsync(IRequest request)
Expand All @@ -88,9 +89,9 @@ public MethodHandler(IHandler parent, MethodInfo method, MethodRouting routing,

Match? sourceParameters = null;

if (!Routing.IsIndex)
if (!Operation.Path.IsIndex)
{
sourceParameters = Routing.ParsedPath.Match(request.Target.GetRemaining().ToString());
sourceParameters = Operation.Path.Matcher.Match(request.Target.GetRemaining().ToString());

var matchedPath = WebPath.FromString(sourceParameters.Value);

Expand Down Expand Up @@ -181,6 +182,7 @@ public MethodHandler(IHandler parent, MethodInfo method, MethodRouting routing,
// assume the default value
continue;
}

// deserialize from body
var deserializer = Serialization.GetDeserialization(request);

Expand Down
24 changes: 24 additions & 0 deletions Modules/Reflection/Operations/Operation.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
namespace GenHTTP.Modules.Reflection.Operations;

public sealed class Operation
{

#region Get-/Setters

public OperationPath Path { get; }

public IReadOnlyDictionary<string, OperationArgument> Arguments { get; }

#endregion

#region Initialization

public Operation(OperationPath path, IReadOnlyDictionary<string, OperationArgument> arguments)
{
Path = path;
Arguments = arguments;
}

#endregion

}
31 changes: 31 additions & 0 deletions Modules/Reflection/Operations/OperationArgument.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
namespace GenHTTP.Modules.Reflection;

public enum OperationArgumentSource
{
Path,
Query,
Body
}

public sealed class OperationArgument
{

#region Get-/Setters

public string Name { get; }

public OperationArgumentSource Source { get; }

#endregion

#region Initialization

public OperationArgument(string name, OperationArgumentSource source)
{
Name = name;
Source = source;
}

#endregion

}
Loading

0 comments on commit d8debf9

Please sign in to comment.