Skip to content

Commit

Permalink
Merge branch 'main' into dependabot/nuget/YamlDotNet-16.2.1
Browse files Browse the repository at this point in the history
  • Loading branch information
Kaliumhexacyanoferrat authored Dec 4, 2024
2 parents 34d1e06 + 88482a5 commit 2312485
Show file tree
Hide file tree
Showing 3 changed files with 59 additions and 24 deletions.
10 changes: 10 additions & 0 deletions Modules/Layouting/Provider/HandlerWrapper.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
using GenHTTP.Api.Content;

namespace GenHTTP.Modules.Layouting.Provider;

internal sealed class HandlerWrapper(IHandler handler) : IHandlerBuilder
{

public IHandler Build() => handler;

}
51 changes: 27 additions & 24 deletions Modules/Layouting/Provider/LayoutBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,13 @@ public sealed class LayoutBuilder : IHandlerBuilder<LayoutBuilder>
{
private readonly List<IConcernBuilder> _Concerns = [];

private IHandler? _Index;
private IHandlerBuilder? _Index;

#region Get-/Setters

private Dictionary<string, IHandler> RoutedHandlers { get; }
private Dictionary<string, IHandlerBuilder> RoutedHandlers { get; }

private List<IHandler> RootHandlers { get; }
private List<IHandlerBuilder> RootHandlers { get; }

#endregion

Expand All @@ -33,26 +33,34 @@ public LayoutBuilder()
/// the index of the layout.
/// </summary>
/// <param name="handler">The handler used for the index of the layout</param>
public LayoutBuilder Index(IHandler handler)
public LayoutBuilder Index(IHandler handler) => Index(new HandlerWrapper(handler));

/// <summary>
/// Sets the handler which should be invoked to provide
/// the index of the layout.
/// </summary>
/// <param name="handler">The handler used for the index of the layout</param>
public LayoutBuilder Index(IHandlerBuilder handler)
{
_Index = handler;
return this;
}

/// <summary>
/// Sets the handler which should be invoked to provide
/// the index of the layout.
/// Adds a handler that will be invoked for all URLs below
/// the specified path segment.
/// </summary>
/// <param name="handler">The handler used for the index of the layout</param>
public LayoutBuilder Index(IHandlerBuilder handler) => Index(handler.Build());
/// <param name="name">The name of the path segment to be handled</param>
/// <param name="handler">The handler which will handle the segment</param>
public LayoutBuilder Add(string name, IHandler handler) => Add(new HandlerWrapper(handler));

/// <summary>
/// Adds a handler that will be invoked for all URLs below
/// the specified path segment.
/// </summary>
/// <param name="name">The name of the path segment to be handled</param>
/// <param name="handler">The handler which will handle the segment</param>
public LayoutBuilder Add(string name, IHandler handler)
public LayoutBuilder Add(string name, IHandlerBuilder handler)
{
if (name.Contains('/'))
{
Expand All @@ -63,14 +71,6 @@ public LayoutBuilder Add(string name, IHandler handler)
return this;
}

/// <summary>
/// Adds a handler that will be invoked for all URLs below
/// the specified path segment.
/// </summary>
/// <param name="name">The name of the path segment to be handled</param>
/// <param name="handler">The handler which will handle the segment</param>
public LayoutBuilder Add(string name, IHandlerBuilder handler) => Add(name, handler.Build());

/// <summary>
/// Adds a handler on root level that will be invoked if neither a
/// path segment has been detected nor the index has been invoked.
Expand All @@ -81,11 +81,7 @@ public LayoutBuilder Add(string name, IHandler handler)
/// Fallback handlers will be executed in the order they have been added
/// to the layout.
/// </remarks>
public LayoutBuilder Add(IHandler handler)
{
RootHandlers.Add(handler);
return this;
}
public LayoutBuilder Add(IHandler handler) => Add(new HandlerWrapper(handler));

/// <summary>
/// Adds a handler on root level that will be invoked if neither a
Expand All @@ -97,7 +93,11 @@ public LayoutBuilder Add(IHandler handler)
/// Fallback handlers will be executed in the order they have been added
/// to the layout.
/// </remarks>
public LayoutBuilder Add(IHandlerBuilder handler) => Add(handler.Build());
public LayoutBuilder Add(IHandlerBuilder handler)
{
RootHandlers.Add(handler);
return this;
}

public LayoutBuilder Add(IConcernBuilder concern)
{
Expand All @@ -107,7 +107,10 @@ public LayoutBuilder Add(IConcernBuilder concern)

public IHandler Build()
{
return Concerns.Chain(_Concerns, new LayoutRouter(RoutedHandlers, RootHandlers, _Index));
var routed = RoutedHandlers.ToDictionary(kv => kv.Key, kv => kv.Value.Build());
var root = RootHandlers.Select(h => h.Build()).ToList();

return Concerns.Chain(_Concerns, new LayoutRouter(routed, root, _Index?.Build()));
}

#endregion
Expand Down
22 changes: 22 additions & 0 deletions Testing/Acceptance/Modules/Layouting/LayoutTests.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Net;
using GenHTTP.Modules.Authentication;
using GenHTTP.Modules.IO;
using GenHTTP.Modules.Layouting;
using Microsoft.VisualStudio.TestTools.UnitTesting;
Expand Down Expand Up @@ -84,4 +85,25 @@ public void TestIllegalPathCharacters()
{
Layout.Create().Add("some/path", Content.From(Resource.FromString("Hello World")));
}

[TestMethod]
[MultiEngineTest]
public async Task TestLazyBuilding(TestEngine engine)
{
var inner = Layout.Create();

var outer = Layout.Create()
.Add("inner", inner);

// add a concern _after_ the inner handler has already been added
// still has to take effect
inner.Authentication((_, _) => new());

await using var host = await TestHost.RunAsync(outer, engine: engine);

using var response = await host.GetResponseAsync("/inner/");

await response.AssertStatusAsync(HttpStatusCode.Unauthorized);
}

}

0 comments on commit 2312485

Please sign in to comment.