diff --git a/API/Content/Concerns.cs b/API/Content/Concerns.cs
index 7c9bc27f..f9bfbb18 100644
--- a/API/Content/Concerns.cs
+++ b/API/Content/Concerns.cs
@@ -6,36 +6,16 @@
public static class Concerns
{
- ///
- /// Creates a handler chain to wrap the specified handler into the
- /// specified concerns.
- ///
- ///
- /// Use this utility within the handler builders to add concerns
- /// to the resulting handler instance. The last concern added
- /// to the list of concerns will be the root handler returned by
- /// this method.
- ///
- /// The parent handler of the chain
- /// The concerns that should be wrapped around the inner handler
- /// The logic creating the actual handler to be chained
- /// The outermost handler or root of the chain
- public static IHandler Chain(IHandler parent, IEnumerable concerns, Func factory)
+ public static IHandler Chain(IEnumerable concerns, IHandler handler)
{
- var stack = new Stack(concerns);
+ var content = handler;
- return Chain(parent, stack, factory);
- }
-
- private static IHandler Chain(IHandler parent, Stack remainders, Func factory)
- {
- if (remainders.Count > 0)
+ foreach (var concern in concerns)
{
- var concern = remainders.Pop();
-
- return concern.Build(parent, p => Chain(p, remainders, factory));
+ content = concern.Build(content);
}
- return factory(parent);
+ return content;
}
+
}
diff --git a/API/Content/IConcernBuilder.cs b/API/Content/IConcernBuilder.cs
index edf21a38..af8d476d 100644
--- a/API/Content/IConcernBuilder.cs
+++ b/API/Content/IConcernBuilder.cs
@@ -1,16 +1,11 @@
namespace GenHTTP.Api.Content;
///
-/// Interface which needs to be implementd by factories providing concern instances.
+/// Interface which needs to be implemented by factories providing concern instances.
///
public interface IConcernBuilder
{
- ///
- /// Builds the concern and sets the inner handler of it.
- ///
- /// The parent of the resulting concern handler instance
- /// A method providing the content of the concern
- /// The newly created concern instance
- IConcern Build(IHandler parent, Func contentFactory);
+ IConcern Build(IHandler content);
+
}
diff --git a/API/Content/IHandler.cs b/API/Content/IHandler.cs
index 507f4c34..55ab942a 100644
--- a/API/Content/IHandler.cs
+++ b/API/Content/IHandler.cs
@@ -9,11 +9,6 @@ namespace GenHTTP.Api.Content;
public interface IHandler
{
- ///
- /// The parent of this handler within the routing tree.
- ///
- IHandler Parent { get; }
-
///
/// Invoked to perform computation heavy or IO bound work
/// that initializes the handler before handling the
@@ -38,4 +33,5 @@ public interface IHandler
/// The request to be handled
/// The response to be sent to the requesting client
ValueTask HandleAsync(IRequest request);
+
}
diff --git a/API/Content/IHandlerBuilder.cs b/API/Content/IHandlerBuilder.cs
index daa3350c..eafa45b0 100644
--- a/API/Content/IHandlerBuilder.cs
+++ b/API/Content/IHandlerBuilder.cs
@@ -9,9 +9,9 @@ public interface IHandlerBuilder
///
/// Creates the configured handler instance.
///
- /// The parent of the handler to be created
/// The newly created handler instance
- IHandler Build(IHandler parent);
+ IHandler Build();
+
}
public interface IHandlerBuilder : IHandlerBuilder where TBuilder : IHandlerBuilder
@@ -26,4 +26,5 @@ public interface IHandlerBuilder : IHandlerBuilder where TBuilder
///
/// The concern to be added to the resulting handler
TBuilder Add(IConcernBuilder concern);
+
}
diff --git a/API/Infrastructure/IServerBuilder.cs b/API/Infrastructure/IServerBuilder.cs
index 4e40d6b7..6b60a94e 100644
--- a/API/Infrastructure/IServerBuilder.cs
+++ b/API/Infrastructure/IServerBuilder.cs
@@ -1,6 +1,7 @@
using System.Net;
using System.Security.Authentication;
using System.Security.Cryptography.X509Certificates;
+
using GenHTTP.Api.Content;
namespace GenHTTP.Api.Infrastructure;
@@ -27,7 +28,18 @@ public interface IServerBuilder : IBuilder
/// Note that only a single handler is supported. To build are more
/// complex application, consider passing a Layout instead.
///
- T Handler(IHandlerBuilder handler);
+ T Handler(IHandler handler);
+
+ ///
+ /// Specifies the root handler that will be invoked when
+ /// a client request needs to be handled.
+ ///
+ /// The handler to be invoked to handle requests
+ ///
+ /// Note that only a single handler is supported. To build are more
+ /// complex application, consider passing a Layout instead.
+ ///
+ T Handler(IHandlerBuilder handlerBuilder) => Handler(handlerBuilder.Build());
#endregion
diff --git a/API/Protocol/ContentType.cs b/API/Protocol/ContentType.cs
index 8108b512..daf164d9 100644
--- a/API/Protocol/ContentType.cs
+++ b/API/Protocol/ContentType.cs
@@ -20,6 +20,11 @@ public enum ContentType
///
TextCss,
+ ///
+ /// A human readable YAML file.
+ ///
+ TextYaml,
+
///
/// A JavaScript source file.
///
@@ -462,6 +467,9 @@ public class FlexibleContentType
{
ContentType.TextEventStream, "text/event-stream"
},
+ {
+ ContentType.TextYaml, "text/yaml"
+ },
{
ContentType.Video3Gpp, "video/3gpp"
},
diff --git a/Engine/Hosting/ServerHost.cs b/Engine/Hosting/ServerHost.cs
index c3de41a9..c31ea038 100644
--- a/Engine/Hosting/ServerHost.cs
+++ b/Engine/Hosting/ServerHost.cs
@@ -91,7 +91,7 @@ public IServerHost RequestReadTimeout(TimeSpan timeout)
return this;
}
- public IServerHost Handler(IHandlerBuilder handler)
+ public IServerHost Handler(IHandler handler)
{
_Builder.Handler(handler);
return this;
diff --git a/Engine/Infrastructure/CoreRouter.cs b/Engine/Infrastructure/CoreRouter.cs
index 50c294ae..9f883a44 100644
--- a/Engine/Infrastructure/CoreRouter.cs
+++ b/Engine/Infrastructure/CoreRouter.cs
@@ -11,25 +11,19 @@ namespace GenHTTP.Engine.Infrastructure;
internal sealed class CoreRouter : IHandler
{
- #region Initialization
+ #region Get-/Setters
- internal CoreRouter(IHandlerBuilder content, IEnumerable concerns)
- {
- Content = Concerns.Chain(this, concerns, content.Build);
- }
+ internal IHandler Content { get; }
#endregion
- #region Get-/Setters
+ #region Initialization
- public IHandler Parent
+ internal CoreRouter(IHandler content, IEnumerable concerns)
{
- get => throw new NotSupportedException("Core router has no parent");
- set => throw new NotSupportedException("Setting core router's parent is not allowed");
+ Content = Concerns.Chain(concerns, content);
}
- internal IHandler Content { get; }
-
#endregion
#region Functionality
diff --git a/Engine/Infrastructure/ThreadedServerBuilder.cs b/Engine/Infrastructure/ThreadedServerBuilder.cs
index 8cf94e5b..f65ab5f5 100644
--- a/Engine/Infrastructure/ThreadedServerBuilder.cs
+++ b/Engine/Infrastructure/ThreadedServerBuilder.cs
@@ -1,9 +1,12 @@
using System.Net;
using System.Security.Authentication;
using System.Security.Cryptography.X509Certificates;
+
using GenHTTP.Api.Content;
using GenHTTP.Api.Infrastructure;
+
using GenHTTP.Engine.Infrastructure.Endpoints;
+
using GenHTTP.Modules.ErrorHandling;
namespace GenHTTP.Engine.Infrastructure;
@@ -19,7 +22,7 @@ internal sealed class ThreadedServerBuilder : IServerBuilder
private bool _Development;
- private IHandlerBuilder? _Handler;
+ private IHandler? _Handler;
private ushort _Port = 8080;
@@ -30,7 +33,7 @@ internal sealed class ThreadedServerBuilder : IServerBuilder
#region Content
- public IServerBuilder Handler(IHandlerBuilder handler)
+ public IServerBuilder Handler(IHandler handler)
{
_Handler = handler;
return this;
diff --git a/GenHTTP.sln b/GenHTTP.sln
index ee28b0aa..10116639 100644
--- a/GenHTTP.sln
+++ b/GenHTTP.sln
@@ -94,6 +94,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GenHTTP.Modules.Websockets"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GenHTTP.Modules.ServerSentEvents", "Modules\ServerSentEvents\GenHTTP.Modules.ServerSentEvents.csproj", "{69F3862A-0027-4312-A890-45549AF5D2B1}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GenHTTP.Modules.Inspection", "Modules\Inspection\GenHTTP.Modules.Inspection.csproj", "{2FE9B758-187F-41B3-96BF-1C2BB006F809}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -228,6 +230,10 @@ Global
{69F3862A-0027-4312-A890-45549AF5D2B1}.Debug|Any CPU.Build.0 = Debug|Any CPU
{69F3862A-0027-4312-A890-45549AF5D2B1}.Release|Any CPU.ActiveCfg = Release|Any CPU
{69F3862A-0027-4312-A890-45549AF5D2B1}.Release|Any CPU.Build.0 = Release|Any CPU
+ {2FE9B758-187F-41B3-96BF-1C2BB006F809}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {2FE9B758-187F-41B3-96BF-1C2BB006F809}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {2FE9B758-187F-41B3-96BF-1C2BB006F809}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {2FE9B758-187F-41B3-96BF-1C2BB006F809}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -267,6 +273,7 @@ Global
{A5149821-D510-4854-9DC9-D489323BC545} = {23B23225-275E-4F52-8B29-6F44C85B6ACE}
{9D3D3B40-691D-4EE1-B948-82525F28FBB2} = {23B23225-275E-4F52-8B29-6F44C85B6ACE}
{69F3862A-0027-4312-A890-45549AF5D2B1} = {23B23225-275E-4F52-8B29-6F44C85B6ACE}
+ {2FE9B758-187F-41B3-96BF-1C2BB006F809} = {23B23225-275E-4F52-8B29-6F44C85B6ACE}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {9C67B3AF-0BF6-4E21-8C39-3F74CFCF9632}
diff --git a/Modules/Authentication/ApiKey/ApiKeyConcern.cs b/Modules/Authentication/ApiKey/ApiKeyConcern.cs
index 1367ea53..81900609 100644
--- a/Modules/Authentication/ApiKey/ApiKeyConcern.cs
+++ b/Modules/Authentication/ApiKey/ApiKeyConcern.cs
@@ -1,5 +1,6 @@
using GenHTTP.Api.Content;
using GenHTTP.Api.Content.Authentication;
+
using GenHTTP.Api.Protocol;
namespace GenHTTP.Modules.Authentication.ApiKey;
@@ -7,23 +8,8 @@ namespace GenHTTP.Modules.Authentication.ApiKey;
public sealed class ApiKeyConcern : IConcern
{
- #region Initialization
-
- public ApiKeyConcern(IHandler parent, Func contentFactory, Func keyExtractor, Func> authenticator)
- {
- Parent = parent;
- Content = contentFactory(this);
-
- KeyExtractor = keyExtractor;
- Authenticator = authenticator;
- }
-
- #endregion
-
#region Get-/Setters
- public IHandler Parent { get; }
-
public IHandler Content { get; }
private Func KeyExtractor { get; }
@@ -32,6 +18,18 @@ public ApiKeyConcern(IHandler parent, Func contentFactory, F
#endregion
+ #region Initialization
+
+ public ApiKeyConcern(IHandler content, Func keyExtractor, Func> authenticator)
+ {
+ Content = content;
+
+ KeyExtractor = keyExtractor;
+ Authenticator = authenticator;
+ }
+
+ #endregion
+
#region Functionality
public async ValueTask HandleAsync(IRequest request)
diff --git a/Modules/Authentication/ApiKey/ApiKeyConcernBuilder.cs b/Modules/Authentication/ApiKey/ApiKeyConcernBuilder.cs
index d596fa6d..fa81ae47 100644
--- a/Modules/Authentication/ApiKey/ApiKeyConcernBuilder.cs
+++ b/Modules/Authentication/ApiKey/ApiKeyConcernBuilder.cs
@@ -70,13 +70,13 @@ public ApiKeyConcernBuilder Keys(params string[] allowedKeys)
return this;
}
- public IConcern Build(IHandler parent, Func contentFactory)
+ public IConcern Build(IHandler content)
{
var keyExtractor = _KeyExtractor ?? throw new BuilderMissingPropertyException("KeyExtractor");
var authenticator = _Authenticator ?? throw new BuilderMissingPropertyException("Authenticator");
- return new ApiKeyConcern(parent, contentFactory, keyExtractor, authenticator);
+ return new ApiKeyConcern(content, keyExtractor, authenticator);
}
#endregion
diff --git a/Modules/Authentication/Basic/BasicAuthenticationConcern.cs b/Modules/Authentication/Basic/BasicAuthenticationConcern.cs
index 8d21bc6a..89aa33ff 100644
--- a/Modules/Authentication/Basic/BasicAuthenticationConcern.cs
+++ b/Modules/Authentication/Basic/BasicAuthenticationConcern.cs
@@ -1,4 +1,5 @@
using System.Text;
+
using GenHTTP.Api.Content;
using GenHTTP.Api.Content.Authentication;
using GenHTTP.Api.Protocol;
@@ -8,32 +9,28 @@ namespace GenHTTP.Modules.Authentication.Basic;
public sealed class BasicAuthenticationConcern : IConcern
{
- #region Initialization
-
- public BasicAuthenticationConcern(IHandler parent, Func contentFactory, string realm,
- Func> authenticator)
- {
- Parent = parent;
- Content = contentFactory(this);
-
- Realm = realm;
- Authenticator = authenticator;
- }
-
- #endregion
-
#region Get-/Setters
public IHandler Content { get; }
- public IHandler Parent { get; }
-
private string Realm { get; }
private Func> Authenticator { get; }
#endregion
+ #region Initialization
+
+ public BasicAuthenticationConcern(IHandler content, string realm, Func> authenticator)
+ {
+ Content = content;
+
+ Realm = realm;
+ Authenticator = authenticator;
+ }
+
+ #endregion
+
#region Functionality
public ValueTask PrepareAsync() => Content.PrepareAsync();
diff --git a/Modules/Authentication/Basic/BasicAuthenticationConcernBuilder.cs b/Modules/Authentication/Basic/BasicAuthenticationConcernBuilder.cs
index 6eae2981..4b7da07d 100644
--- a/Modules/Authentication/Basic/BasicAuthenticationConcernBuilder.cs
+++ b/Modules/Authentication/Basic/BasicAuthenticationConcernBuilder.cs
@@ -24,13 +24,13 @@ public BasicAuthenticationConcernBuilder Handler(Func contentFactory)
+ public IConcern Build(IHandler content)
{
var realm = _Realm ?? throw new BuilderMissingPropertyException("Realm");
var handler = _Handler ?? throw new BuilderMissingPropertyException("Handler");
- return new BasicAuthenticationConcern(parent, contentFactory, realm, handler);
+ return new BasicAuthenticationConcern(content, realm, handler);
}
#endregion
diff --git a/Modules/Authentication/Basic/BasicAuthenticationKnownUsersBuilder.cs b/Modules/Authentication/Basic/BasicAuthenticationKnownUsersBuilder.cs
index 70c2e423..88382569 100644
--- a/Modules/Authentication/Basic/BasicAuthenticationKnownUsersBuilder.cs
+++ b/Modules/Authentication/Basic/BasicAuthenticationKnownUsersBuilder.cs
@@ -24,11 +24,11 @@ public BasicAuthenticationKnownUsersBuilder Add(string user, string password)
return this;
}
- public IConcern Build(IHandler parent, Func contentFactory)
+ public IConcern Build(IHandler content)
{
var realm = _Realm ?? throw new BuilderMissingPropertyException("Realm");
- return new BasicAuthenticationConcern(parent, contentFactory, realm, (user, password) =>
+ return new BasicAuthenticationConcern(content, realm, (user, password) =>
{
if (_Users.TryGetValue(user, out var expected))
{
diff --git a/Modules/Authentication/Bearer/BearerAuthenticationConcern.cs b/Modules/Authentication/Bearer/BearerAuthenticationConcern.cs
index 21e0e504..622d87d0 100644
--- a/Modules/Authentication/Bearer/BearerAuthenticationConcern.cs
+++ b/Modules/Authentication/Bearer/BearerAuthenticationConcern.cs
@@ -23,25 +23,22 @@ internal sealed class BearerAuthenticationConcern : IConcern
{
private ICollection? _IssuerKeys;
- #region Initialization
+ #region Get-/Setters
- internal BearerAuthenticationConcern(IHandler parent, Func contentFactory, TokenValidationOptions validationOptions)
- {
- Parent = parent;
- Content = contentFactory(this);
+ public IHandler Content { get; }
- ValidationOptions = validationOptions;
- }
+ private TokenValidationOptions ValidationOptions { get; }
#endregion
- #region Get-/Setters
-
- public IHandler Content { get; }
+ #region Initialization
- public IHandler Parent { get; }
+ internal BearerAuthenticationConcern(IHandler content, TokenValidationOptions validationOptions)
+ {
+ Content = content;
- private TokenValidationOptions ValidationOptions { get; }
+ ValidationOptions = validationOptions;
+ }
#endregion
diff --git a/Modules/Authentication/Bearer/BearerAuthenticationConcernBuilder.cs b/Modules/Authentication/Bearer/BearerAuthenticationConcernBuilder.cs
index 1c95f950..f97b39df 100644
--- a/Modules/Authentication/Bearer/BearerAuthenticationConcernBuilder.cs
+++ b/Modules/Authentication/Bearer/BearerAuthenticationConcernBuilder.cs
@@ -81,7 +81,7 @@ public BearerAuthenticationConcernBuilder AllowExpired()
return this;
}
- public IConcern Build(IHandler parent, Func contentFactory) => new BearerAuthenticationConcern(parent, contentFactory, _Options);
+ public IConcern Build(IHandler content) => new BearerAuthenticationConcern(content, _Options);
#endregion
diff --git a/Modules/Basics/Providers/RedirectProvider.cs b/Modules/Basics/Providers/RedirectProvider.cs
index 11c1b7d5..3b23a389 100644
--- a/Modules/Basics/Providers/RedirectProvider.cs
+++ b/Modules/Basics/Providers/RedirectProvider.cs
@@ -14,16 +14,12 @@ public sealed partial class RedirectProvider : IHandler
public bool Temporary { get; }
- public IHandler Parent { get; }
-
#endregion
#region Initialization
- public RedirectProvider(IHandler parent, string location, bool temporary)
+ public RedirectProvider(string location, bool temporary)
{
- Parent = parent;
-
Target = location;
Temporary = temporary;
}
diff --git a/Modules/Basics/Providers/RedirectProviderBuilder.cs b/Modules/Basics/Providers/RedirectProviderBuilder.cs
index 775733b7..5661f05e 100644
--- a/Modules/Basics/Providers/RedirectProviderBuilder.cs
+++ b/Modules/Basics/Providers/RedirectProviderBuilder.cs
@@ -30,14 +30,14 @@ public RedirectProviderBuilder Add(IConcernBuilder concern)
return this;
}
- public IHandler Build(IHandler parent)
+ public IHandler Build()
{
if (_Location is null)
{
throw new BuilderMissingPropertyException("Location");
}
- return Concerns.Chain(parent, _Concerns, p => new RedirectProvider(p, _Location, _Temporary));
+ return Concerns.Chain(_Concerns, new RedirectProvider(_Location, _Temporary));
}
#endregion
diff --git a/Modules/ClientCaching/Policy/CachePolicyBuilder.cs b/Modules/ClientCaching/Policy/CachePolicyBuilder.cs
index 0e91cf11..13c81735 100644
--- a/Modules/ClientCaching/Policy/CachePolicyBuilder.cs
+++ b/Modules/ClientCaching/Policy/CachePolicyBuilder.cs
@@ -41,11 +41,11 @@ public CachePolicyBuilder Predicate(Func predicate)
return this;
}
- public IConcern Build(IHandler parent, Func contentFactory)
+ public IConcern Build(IHandler content)
{
var duration = _Duration ?? throw new BuilderMissingPropertyException("Duration");
- return new CachePolicyConcern(parent, contentFactory, duration, _Predicate);
+ return new CachePolicyConcern(content, duration, _Predicate);
}
#endregion
diff --git a/Modules/ClientCaching/Policy/CachePolicyConcern.cs b/Modules/ClientCaching/Policy/CachePolicyConcern.cs
index 622afda9..9d227388 100644
--- a/Modules/ClientCaching/Policy/CachePolicyConcern.cs
+++ b/Modules/ClientCaching/Policy/CachePolicyConcern.cs
@@ -1,5 +1,6 @@
using GenHTTP.Api.Content;
using GenHTTP.Api.Protocol;
+
using GenHTTP.Modules.Basics;
namespace GenHTTP.Modules.ClientCaching.Policy;
@@ -7,32 +8,28 @@ namespace GenHTTP.Modules.ClientCaching.Policy;
public sealed class CachePolicyConcern : IConcern
{
- #region Initialization
-
- public CachePolicyConcern(IHandler parent, Func contentFactory,
- TimeSpan duration, Func? predicate)
- {
- Parent = parent;
- Content = contentFactory(this);
-
- Duration = duration;
- Predicate = predicate;
- }
-
- #endregion
-
#region Get-/Setters
public IHandler Content { get; }
- public IHandler Parent { get; }
-
private TimeSpan Duration { get; }
private Func? Predicate { get; }
#endregion
+ #region Initialization
+
+ public CachePolicyConcern(IHandler content, TimeSpan duration, Func? predicate)
+ {
+ Content = content;
+
+ Duration = duration;
+ Predicate = predicate;
+ }
+
+ #endregion
+
#region Functionality
public async ValueTask HandleAsync(IRequest request)
diff --git a/Modules/ClientCaching/Validation/CacheValidationBuilder.cs b/Modules/ClientCaching/Validation/CacheValidationBuilder.cs
index 06f1bd56..d9ae16dc 100644
--- a/Modules/ClientCaching/Validation/CacheValidationBuilder.cs
+++ b/Modules/ClientCaching/Validation/CacheValidationBuilder.cs
@@ -5,5 +5,5 @@ namespace GenHTTP.Modules.ClientCaching.Validation;
public sealed class CacheValidationBuilder : IConcernBuilder
{
- public IConcern Build(IHandler parent, Func contentFactory) => new CacheValidationHandler(parent, contentFactory);
+ public IConcern Build(IHandler content) => new CacheValidationHandler(content);
}
diff --git a/Modules/ClientCaching/Validation/CacheValidationHandler.cs b/Modules/ClientCaching/Validation/CacheValidationHandler.cs
index b3fe8909..b38a576c 100644
--- a/Modules/ClientCaching/Validation/CacheValidationHandler.cs
+++ b/Modules/ClientCaching/Validation/CacheValidationHandler.cs
@@ -1,5 +1,6 @@
using GenHTTP.Api.Content;
using GenHTTP.Api.Protocol;
+
using GenHTTP.Modules.Basics;
namespace GenHTTP.Modules.ClientCaching.Validation;
@@ -10,21 +11,18 @@ public sealed class CacheValidationHandler : IConcern
private static readonly RequestMethod[] SupportedMethods = [RequestMethod.Get, RequestMethod.Head];
- #region Initialization
+ #region Get-/Setters
- public CacheValidationHandler(IHandler parent, Func contentFactory)
- {
- Parent = parent;
- Content = contentFactory(this);
- }
+ public IHandler Content { get; }
#endregion
- #region Get-/Setters
-
- public IHandler Parent { get; }
+ #region Initialization
- public IHandler Content { get; }
+ public CacheValidationHandler(IHandler content)
+ {
+ Content = content;
+ }
#endregion
diff --git a/Modules/Compression/Providers/CompressionConcern.cs b/Modules/Compression/Providers/CompressionConcern.cs
index 50489b56..355c8487 100644
--- a/Modules/Compression/Providers/CompressionConcern.cs
+++ b/Modules/Compression/Providers/CompressionConcern.cs
@@ -12,14 +12,22 @@ public sealed class CompressionConcern : IConcern
private const string Vary = "Vary";
+ #region Get-/Setters
+
+ public IHandler Content { get; }
+
+ private IReadOnlyDictionary Algorithms { get; }
+
+ private CompressionLevel Level { get; }
+
+ #endregion
+
#region Initialization
- public CompressionConcern(IHandler parent, Func contentFactory,
- IReadOnlyDictionary algorithms,
+ public CompressionConcern(IHandler content, IReadOnlyDictionary algorithms,
CompressionLevel level)
{
- Parent = parent;
- Content = contentFactory(this);
+ Content = content;
Algorithms = algorithms;
Level = level;
@@ -27,18 +35,6 @@ public CompressionConcern(IHandler parent, Func contentFacto
#endregion
- #region Get-/Setters
-
- public IHandler Content { get; }
-
- public IHandler Parent { get; }
-
- private IReadOnlyDictionary Algorithms { get; }
-
- private CompressionLevel Level { get; }
-
- #endregion
-
#region Functionality
public async ValueTask HandleAsync(IRequest request)
diff --git a/Modules/Compression/Providers/CompressionConcernBuilder.cs b/Modules/Compression/Providers/CompressionConcernBuilder.cs
index dfb387f0..2265c646 100644
--- a/Modules/Compression/Providers/CompressionConcernBuilder.cs
+++ b/Modules/Compression/Providers/CompressionConcernBuilder.cs
@@ -27,11 +27,11 @@ public CompressionConcernBuilder Level(CompressionLevel level)
return this;
}
- public IConcern Build(IHandler parent, Func contentFactory)
+ public IConcern Build(IHandler content)
{
var algorithms = _Algorithms.ToDictionary(a => a.Name);
- return new CompressionConcern(parent, contentFactory, algorithms, _Level);
+ return new CompressionConcern(content, algorithms, _Level);
}
#endregion
diff --git a/Modules/Controllers/Provider/ControllerBuilder.cs b/Modules/Controllers/Provider/ControllerBuilder.cs
index e15aa912..7ede317e 100644
--- a/Modules/Controllers/Provider/ControllerBuilder.cs
+++ b/Modules/Controllers/Provider/ControllerBuilder.cs
@@ -59,7 +59,7 @@ public ControllerBuilder Add(IConcernBuilder concern)
return this;
}
- public IHandler Build(IHandler parent)
+ public IHandler Build()
{
var serializers = (_Serializers ?? Serialization.Default()).Build();
@@ -71,7 +71,7 @@ public IHandler Build(IHandler parent)
var extensions = new MethodRegistry(serializers, injectors, formatters);
- return Concerns.Chain(parent, _Concerns, p => new ControllerHandler(p, instance, extensions));
+ return Concerns.Chain(_Concerns, new ControllerHandler(instance, extensions));
}
#endregion
diff --git a/Modules/Controllers/Provider/ControllerHandler.cs b/Modules/Controllers/Provider/ControllerHandler.cs
index dd6a9c0c..b463f2be 100644
--- a/Modules/Controllers/Provider/ControllerHandler.cs
+++ b/Modules/Controllers/Provider/ControllerHandler.cs
@@ -1,7 +1,9 @@
using System.Reflection;
using System.Text.RegularExpressions;
+
using GenHTTP.Api.Content;
using GenHTTP.Api.Protocol;
+
using GenHTTP.Modules.Reflection;
using GenHTTP.Modules.Reflection.Operations;
@@ -13,8 +15,6 @@ public sealed partial class ControllerHandler : IHandler, IServiceMethodProvider
#region Get-/Setters
- public IHandler Parent { get; }
-
public MethodCollection Methods { get; }
private ResponseProvider ResponseProvider { get; }
@@ -27,19 +27,18 @@ public sealed partial class ControllerHandler : IHandler, IServiceMethodProvider
#region Initialization
- public ControllerHandler(IHandler parent, object instance, MethodRegistry registry)
+ public ControllerHandler(object instance, MethodRegistry registry)
{
- Parent = parent;
Registry = registry;
Instance = instance;
ResponseProvider = new ResponseProvider(registry);
- Methods = new MethodCollection(this, AnalyzeMethods(instance.GetType(), registry));
+ Methods = new MethodCollection(AnalyzeMethods(instance.GetType(), registry));
}
- private IEnumerable> AnalyzeMethods(Type type, MethodRegistry registry)
+ private IEnumerable AnalyzeMethods(Type type, MethodRegistry registry)
{
foreach (var method in type.GetMethods(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly))
{
@@ -49,7 +48,7 @@ private IEnumerable> AnalyzeMethods(Type type, Met
var operation = CreateOperation(method, arguments);
- yield return parent => new MethodHandler(parent, operation, Instance, annotation, registry);
+ yield return new MethodHandler(operation, Instance, annotation, registry);
}
}
diff --git a/Modules/Conversion/GenHTTP.Modules.Conversion.csproj b/Modules/Conversion/GenHTTP.Modules.Conversion.csproj
index c379fe6a..3d552497 100644
--- a/Modules/Conversion/GenHTTP.Modules.Conversion.csproj
+++ b/Modules/Conversion/GenHTTP.Modules.Conversion.csproj
@@ -41,11 +41,13 @@
-
+
+
+
diff --git a/Modules/Conversion/Serialization.cs b/Modules/Conversion/Serialization.cs
index 58a8ee66..1aa6f320 100644
--- a/Modules/Conversion/Serialization.cs
+++ b/Modules/Conversion/Serialization.cs
@@ -1,8 +1,10 @@
using GenHTTP.Api.Protocol;
+
using GenHTTP.Modules.Conversion.Serializers;
using GenHTTP.Modules.Conversion.Serializers.Forms;
using GenHTTP.Modules.Conversion.Serializers.Json;
using GenHTTP.Modules.Conversion.Serializers.Xml;
+using GenHTTP.Modules.Conversion.Serializers.Yaml;
namespace GenHTTP.Modules.Conversion;
@@ -19,6 +21,7 @@ public static class Serialization
///
public static SerializationBuilder Default() => new SerializationBuilder().Default(ContentType.ApplicationJson)
.Add(ContentType.ApplicationJson, new JsonFormat())
+ .Add(ContentType.ApplicationYaml, new YamlFormat())
.Add(ContentType.ApplicationWwwFormUrlEncoded, new FormFormat())
.Add(ContentType.TextXml, new XmlFormat());
@@ -26,4 +29,5 @@ public static class Serialization
/// Returns an empty registry to be customized.
///
public static SerializationBuilder Empty() => new();
+
}
diff --git a/Modules/Conversion/Serializers/Yaml/YamlContent.cs b/Modules/Conversion/Serializers/Yaml/YamlContent.cs
new file mode 100644
index 00000000..c8774c23
--- /dev/null
+++ b/Modules/Conversion/Serializers/Yaml/YamlContent.cs
@@ -0,0 +1,42 @@
+using System.Text;
+
+using GenHTTP.Api.Protocol;
+
+using YamlDotNet.Serialization;
+using YamlDotNet.Serialization.NamingConventions;
+
+namespace GenHTTP.Modules.Conversion.Serializers.Yaml;
+
+public sealed class YamlContent : IResponseContent
+{
+ private static readonly ISerializer Serializer = new SerializerBuilder().WithNamingConvention(CamelCaseNamingConvention.Instance).Build();
+
+ private static readonly Encoding Encoding = Encoding.UTF8;
+
+ #region Get-/Setters
+
+ public ulong? Length => null;
+
+ public object Data { get; }
+
+ #endregion
+
+ #region Initialization
+
+ public YamlContent(object data)
+ {
+ Data = data;
+ }
+
+ #endregion
+
+ #region Functionality
+
+ public ValueTask CalculateChecksumAsync() => new((ulong)Data.GetHashCode());
+
+ public ValueTask WriteAsync(Stream target, uint bufferSize)
+ => target.WriteAsync(Encoding.GetBytes(Serializer.Serialize(Data)));
+
+ #endregion
+
+}
diff --git a/Modules/Conversion/Serializers/Yaml/YamlFormat.cs b/Modules/Conversion/Serializers/Yaml/YamlFormat.cs
new file mode 100644
index 00000000..62acf8c0
--- /dev/null
+++ b/Modules/Conversion/Serializers/Yaml/YamlFormat.cs
@@ -0,0 +1,45 @@
+using GenHTTP.Api.Protocol;
+
+using GenHTTP.Modules.Basics;
+
+using YamlDotNet.Serialization;
+
+namespace GenHTTP.Modules.Conversion.Serializers.Yaml;
+
+public sealed class YamlFormat : ISerializationFormat
+{
+ private static readonly IDeserializer Deserializer = new DeserializerBuilder().WithNamingConvention(new IgnoreCaseNamingConvention())
+ .Build();
+
+ #region Supporting data structures
+
+ private sealed class IgnoreCaseNamingConvention : INamingConvention
+ {
+ public string Apply(string value) => value.ToLowerInvariant();
+
+ public string Reverse(string value) => throw new NotImplementedException();
+ }
+
+ #endregion
+
+ #region Functionality
+
+ public ValueTask