Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions src/Http/DeepMiddlewareUsage/DeepMiddlewareUsage.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<Project Sdk="Microsoft.NET.Sdk.Web">

<PropertyGroup>
<TargetFramework>net9.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>

<ItemGroup>
<ProjectReference Include="..\Wolverine.Http.Marten\Wolverine.Http.Marten.csproj" />
</ItemGroup>

<ItemGroup>
<Compile Include="..\..\Servers.cs">
<Link>Servers.cs</Link>
</Compile>
</ItemGroup>

</Project>
6 changes: 6 additions & 0 deletions src/Http/DeepMiddlewareUsage/DeepMiddlewareUsage.http
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
@DeepMiddlewareUsage_HostAddress = http://localhost:5063

GET {{DeepMiddlewareUsage_HostAddress}}/weatherforecast/
Accept: application/json

###

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
// <auto-generated/>
#pragma warning disable
using Microsoft.AspNetCore.Routing;
using System;
using System.Linq;
using Wolverine.Http;
using Wolverine.Marten.Publishing;
using Wolverine.Runtime;

namespace Internal.Generated.WolverineHandlers
{
// START: GET_api_trainer
[global::System.CodeDom.Compiler.GeneratedCode("JasperFx", "1.0.0")]
public sealed class GET_api_trainer : Wolverine.Http.HttpHandler
{
private readonly Wolverine.Http.WolverineHttpOptions _wolverineHttpOptions;
private readonly Wolverine.Marten.Publishing.OutboxedSessionFactory _outboxedSessionFactory;
private readonly Wolverine.Runtime.IWolverineRuntime _wolverineRuntime;

public GET_api_trainer(Wolverine.Http.WolverineHttpOptions wolverineHttpOptions, Wolverine.Marten.Publishing.OutboxedSessionFactory outboxedSessionFactory, Wolverine.Runtime.IWolverineRuntime wolverineRuntime) : base(wolverineHttpOptions)
{
_wolverineHttpOptions = wolverineHttpOptions;
_outboxedSessionFactory = outboxedSessionFactory;
_wolverineRuntime = wolverineRuntime;
}



public override async System.Threading.Tasks.Task Handle(Microsoft.AspNetCore.Http.HttpContext httpContext)
{
var messageContext = new Wolverine.Runtime.MessageContext(_wolverineRuntime);
// Building the Marten session
await using var documentSession = _outboxedSessionFactory.OpenSession(messageContext);
(var userId, var problemDetails1) = DeepMiddlewareUsage.UserIdMiddleWare.Load(httpContext.User, httpContext);
// Evaluate whether the processing should stop if there are any problems
if (!(ReferenceEquals(problemDetails1, Wolverine.Http.WolverineContinue.NoProblems)))
{
await WriteProblems(problemDetails1, httpContext).ConfigureAwait(false);
return;
}


(var trainer, var problemDetails2) = await DeepMiddlewareUsage.TrainerMiddleware.LoadAsync(userId, documentSession, httpContext.RequestAborted, httpContext).ConfigureAwait(false);
// Evaluate whether the processing should stop if there are any problems
if (!(ReferenceEquals(problemDetails2, Wolverine.Http.WolverineContinue.NoProblems)))
{
await WriteProblems(problemDetails2, httpContext).ConfigureAwait(false);
return;
}



// The actual HTTP request handler execution
var trainerResponse_response = DeepMiddlewareUsage.TrainerGet.Get(trainer);

// Writing the response body to JSON because this was the first 'return variable' in the method signature
await WriteJsonAsync(httpContext, trainerResponse_response);
}

}

// END: GET_api_trainer


}

40 changes: 40 additions & 0 deletions src/Http/DeepMiddlewareUsage/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
using DeepMiddlewareUsage;
using IntegrationTests;
using JasperFx;
using Marten;
using Wolverine;
using Wolverine.Http;
using Wolverine.Marten;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddMarten(options =>
{
options.Connection(Servers.PostgresConnectionString);
options.DatabaseSchemaName = "trainers";
})
.IntegrateWithWolverine();

builder.Host.ApplyJasperFxExtensions();

builder.Host.UseWolverine(options =>
{
// Setting up the outbox on all locally handled
// background tasks
options.Policies.AutoApplyTransactions();
options.Policies.UseDurableLocalQueues();
options.Policies.UseDurableOutboxOnAllSendingEndpoints();
});

builder.Services.AddWolverineHttp();

WebApplication app = builder.Build();

app.MapWolverineEndpoints(options =>
{
options.AddMiddleware(typeof(UserIdMiddleWare));
options.AddPolicy<RequestTrainerPolicy>();
options.ConfigureEndpoints(e => { });
});

return await app.RunJasperFxCommands(args);
23 changes: 23 additions & 0 deletions src/Http/DeepMiddlewareUsage/Properties/launchSettings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
{
"$schema": "https://json.schemastore.org/launchsettings.json",
"profiles": {
"http": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": false,
"applicationUrl": "http://localhost:5063",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"https": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": false,
"applicationUrl": "https://localhost:7258;http://localhost:5063",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
}
}
}
19 changes: 19 additions & 0 deletions src/Http/DeepMiddlewareUsage/Trainer.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
using System.ComponentModel;
using Marten.Schema;

namespace DeepMiddlewareUsage;

public class Participant { }

public class Trainer: Participant
{
[DefaultValue(null)]
[UniqueIndex(IndexType = UniqueIndexType.Computed)]
public string? Name { get; set; }

[DefaultValue(null)]
public string? Country { get; set; }

[DefaultValue(null)]
public string? TimeZone { get; set; }
}
15 changes: 15 additions & 0 deletions src/Http/DeepMiddlewareUsage/TrainerGet.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
using Wolverine.Http;

namespace DeepMiddlewareUsage;

public static class TrainerGet
{
[Tags("Trainer")]
[WolverineGet("/api/trainer")]
public static TrainerResponse Get(Trainer trainer)
{
return new TrainerResponse(trainer.Name ?? "Unknown", trainer.Country);
}
}

public record TrainerResponse(string Name, string? Country);
49 changes: 49 additions & 0 deletions src/Http/DeepMiddlewareUsage/TrainerMiddleware.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
using JasperFx;
using JasperFx.CodeGeneration;
using JasperFx.CodeGeneration.Frames;
using Marten;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Wolverine.Http;

namespace DeepMiddlewareUsage;

public static class TrainerMiddleware
{
public static async Task<(Trainer? trainer, ProblemDetails)> LoadAsync(
UserId userId,
IDocumentSession session,
CancellationToken ct,
HttpContext context)
{
if (userId.Id == Guid.Empty)
return (null, WolverineContinue.NoProblems);

var trainer = await session.LoadAsync<Trainer>(userId.Id, ct);

bool allowAnonymous = context.GetEndpoint()?.Metadata.GetMetadata<IAllowAnonymous>() != null;
if (trainer == null && !allowAnonymous)
return (null, new ProblemDetails
{
Title = "Unauthorized",
Status = StatusCodes.Status401Unauthorized
});

return (trainer, WolverineContinue.NoProblems);
}
}

internal class RequestTrainerPolicy : IHttpPolicy
{
public void Apply(IReadOnlyList<HttpChain> chains, GenerationRules rules, IServiceContainer container)
{
foreach (HttpChain chain in chains)
{
Type[] serviceDependencies = chain.ServiceDependencies(container, Type.EmptyTypes).ToArray();
if (serviceDependencies.Contains(typeof(Trainer)))
{
chain.Middleware.Add(new MethodCall(typeof(TrainerMiddleware), nameof(TrainerMiddleware.LoadAsync)));
}
}
}
}
25 changes: 25 additions & 0 deletions src/Http/DeepMiddlewareUsage/UserMiddleware.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
using System.Security.Claims;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Wolverine.Http;

namespace DeepMiddlewareUsage;

public record UserId(Guid Id);

public static class UserIdMiddleWare
{
public static (UserId, ProblemDetails) Load(ClaimsPrincipal principal, HttpContext context)
{
Claim? userIdClaim = principal.FindFirst("sub");
if (userIdClaim != null && Guid.TryParse(userIdClaim.Value, out var id))
{
return ( new UserId(id), WolverineContinue.NoProblems);
}

Endpoint? endpoint = context.GetEndpoint();
return endpoint?.Metadata.GetMetadata<IAllowAnonymous>() != null
? ( new UserId(Guid.Empty), WolverineContinue.NoProblems)
: (new UserId(Guid.Empty), new ProblemDetails { Detail = "Unauthorized", Status = 401});
}
}
8 changes: 8 additions & 0 deletions src/Http/DeepMiddlewareUsage/appsettings.Development.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
}
}
9 changes: 9 additions & 0 deletions src/Http/DeepMiddlewareUsage/appsettings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*"
}
Loading
Loading