-
-
Notifications
You must be signed in to change notification settings - Fork 146
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
"Required" entity loading in HTTP mechanics Closes GH-470
- Loading branch information
1 parent
a59f3e9
commit 8d7943b
Showing
5 changed files
with
153 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
using System.ComponentModel.DataAnnotations; | ||
using JasperFx.CodeGeneration; | ||
using JasperFx.CodeGeneration.Frames; | ||
using JasperFx.CodeGeneration.Model; | ||
using JasperFx.Core.Reflection; | ||
using Lamar; | ||
using Microsoft.AspNetCore.Http; | ||
|
||
namespace Wolverine.Http.Policies; | ||
|
||
internal class RequiredEntityPolicy : IHttpPolicy | ||
{ | ||
public void Apply(IReadOnlyList<HttpChain> chains, GenerationRules rules, IContainer container) | ||
{ | ||
foreach (var chain in chains) | ||
{ | ||
if (chain.RoutePattern.Parameters.Any()) | ||
{ | ||
var requiredParameters = chain.Method.Method.GetParameters() | ||
.Where(x => x.HasAttribute<RequiredAttribute>() && x.ParameterType.IsClass).ToArray(); | ||
|
||
if (requiredParameters.Any()) | ||
{ | ||
chain.Metadata.Produces(404); | ||
|
||
foreach (var parameter in requiredParameters) | ||
{ | ||
var frame = new SetStatusCodeAndReturnFrame(parameter.ParameterType); | ||
chain.Middleware.Add(frame); | ||
} | ||
} | ||
} | ||
} | ||
} | ||
} | ||
|
||
internal class SetStatusCodeAndReturnFrame : SyncFrame | ||
{ | ||
private readonly Type _entityType; | ||
private Variable _httpResponse; | ||
private Variable _entity; | ||
|
||
public SetStatusCodeAndReturnFrame(Type entityType) | ||
{ | ||
_entityType = entityType; | ||
} | ||
|
||
public override void GenerateCode(GeneratedMethod method, ISourceWriter writer) | ||
{ | ||
writer.WriteComment("404 if this required object is null"); | ||
writer.Write($"BLOCK:if ({_entity.Usage} == null)"); | ||
writer.Write($"{_httpResponse.Usage}.{nameof(HttpResponse.StatusCode)} = 404;"); | ||
if (method.AsyncMode == AsyncMode.ReturnCompletedTask) | ||
{ | ||
writer.Write($"return {typeof(Task).FullNameInCode()}.{nameof(Task.CompletedTask)};"); | ||
} | ||
else | ||
{ | ||
writer.Write("return;"); | ||
} | ||
|
||
writer.FinishBlock(); | ||
|
||
Next?.GenerateCode(method, writer); | ||
} | ||
|
||
public override IEnumerable<Variable> FindVariables(IMethodVariables chain) | ||
{ | ||
_entity = chain.FindVariable(_entityType); | ||
yield return _entity; | ||
|
||
_httpResponse = chain.FindVariable(typeof(HttpResponse)); | ||
yield return _httpResponse; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
64 changes: 64 additions & 0 deletions
64
src/Http/WolverineWebApi/Internal/Generated/WolverineHandlers/PUT_todos_id.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
// <auto-generated/> | ||
#pragma warning disable | ||
using Marten; | ||
using Microsoft.AspNetCore.Routing; | ||
using System; | ||
using System.Linq; | ||
using Wolverine.Http; | ||
|
||
namespace Internal.Generated.WolverineHandlers | ||
{ | ||
// START: PUT_todos_id | ||
public class PUT_todos_id : Wolverine.Http.HttpHandler | ||
{ | ||
private readonly Wolverine.Http.WolverineHttpOptions _wolverineHttpOptions; | ||
private readonly Marten.ISessionFactory _sessionFactory; | ||
|
||
public PUT_todos_id(Wolverine.Http.WolverineHttpOptions wolverineHttpOptions, Marten.ISessionFactory sessionFactory) : base(wolverineHttpOptions) | ||
{ | ||
_wolverineHttpOptions = wolverineHttpOptions; | ||
_sessionFactory = sessionFactory; | ||
} | ||
|
||
|
||
|
||
public override async System.Threading.Tasks.Task Handle(Microsoft.AspNetCore.Http.HttpContext httpContext) | ||
{ | ||
await using var documentSession = _sessionFactory.OpenSession(); | ||
if (!int.TryParse((string)httpContext.GetRouteValue("id"), out var id)) | ||
{ | ||
httpContext.Response.StatusCode = 404; | ||
return; | ||
} | ||
|
||
|
||
var (request, jsonContinue) = await ReadJsonAsync<WolverineWebApi.Samples.UpdateRequest>(httpContext); | ||
if (jsonContinue == Wolverine.HandlerContinuation.Stop) return; | ||
var todo = await WolverineWebApi.Samples.UpdateEndpoint.LoadAsync(id, documentSession).ConfigureAwait(false); | ||
// 404 if this required object is null | ||
if (todo == null) | ||
{ | ||
httpContext.Response.StatusCode = 404; | ||
return; | ||
} | ||
|
||
var storeDoc = WolverineWebApi.Samples.UpdateEndpoint.Put(id, request, todo); | ||
|
||
// Placed by Wolverine's ISideEffect policy | ||
storeDoc.Execute(documentSession); | ||
|
||
|
||
// Commit any outstanding Marten changes | ||
await documentSession.SaveChangesAsync(httpContext.RequestAborted).ConfigureAwait(false); | ||
|
||
// Wolverine automatically sets the status code to 204 for empty responses | ||
httpContext.Response.StatusCode = 204; | ||
} | ||
|
||
} | ||
|
||
// END: PUT_todos_id | ||
|
||
|
||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters