-
-
Notifications
You must be signed in to change notification settings - Fork 128
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Ability to read and bind data from headers to parameters. Closes GH-301
- Loading branch information
Jeremy D. Miller
authored and
Jeremy D. Miller
committed
Apr 11, 2023
1 parent
a92ea92
commit 29edb9e
Showing
8 changed files
with
284 additions
and
0 deletions.
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
using Alba; | ||
|
||
namespace Wolverine.Http.Tests; | ||
|
||
public class header_binding : IntegrationContext | ||
{ | ||
public header_binding(AppFixture fixture) : base(fixture) | ||
{ | ||
} | ||
|
||
[Fact] | ||
public async Task read_single_header_with_explicit_name_mapping() | ||
{ | ||
await Scenario(x => | ||
{ | ||
x.WithRequestHeader("x-wolverine", "one"); | ||
x.Get.Url("/headers/simple"); | ||
x.ContentShouldBe("one"); | ||
}); | ||
} | ||
|
||
[Fact] | ||
public async Task read_single_parsed_header_with_explicit_name_mapping() | ||
{ | ||
await Scenario(x => | ||
{ | ||
x.WithRequestHeader("x-wolverine", "111"); | ||
x.Get.Url("/headers/int"); | ||
x.ContentShouldBe("222"); | ||
}); | ||
} | ||
|
||
[Fact] | ||
public async Task read_header_by_variable_name() | ||
{ | ||
await Scenario(x => | ||
{ | ||
x.WithRequestHeader("accepts", "text/plain"); | ||
x.Get.Url("/headers/accepts"); | ||
x.ContentShouldBe("text/plain"); | ||
}); | ||
} | ||
} |
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,94 @@ | ||
using System.Reflection; | ||
using JasperFx.CodeGeneration; | ||
using JasperFx.CodeGeneration.Frames; | ||
using JasperFx.CodeGeneration.Model; | ||
using Lamar; | ||
using Microsoft.AspNetCore.Http; | ||
using Microsoft.AspNetCore.Http.Metadata; | ||
|
||
namespace Wolverine.Http.CodeGen; | ||
|
||
public class FromHeaderStrategy : IParameterStrategy | ||
{ | ||
public bool TryMatch(HttpChain chain, IContainer container, ParameterInfo parameter, out Variable? variable) | ||
{ | ||
var att = parameter.GetCustomAttributes().OfType<IFromHeaderMetadata>().FirstOrDefault(); | ||
if (att != null) | ||
{ | ||
if (parameter.ParameterType == typeof(string)) | ||
{ | ||
var frame = new FromHeaderValue(att, parameter); | ||
chain.Middleware.Add(frame); | ||
variable = frame.Variable; | ||
} | ||
else | ||
{ | ||
var frame = new ParsedHeaderValue(att, parameter); | ||
chain.Middleware.Add(frame); | ||
variable = frame.Variable; | ||
} | ||
|
||
|
||
|
||
return true; | ||
} | ||
|
||
variable = default; | ||
return false; | ||
} | ||
} | ||
|
||
internal class FromHeaderValue : SyncFrame | ||
{ | ||
private Variable _httpContext; | ||
private readonly string _header; | ||
|
||
public FromHeaderValue(IFromHeaderMetadata header, ParameterInfo parameter) | ||
{ | ||
Variable = new Variable(parameter.ParameterType, parameter.Name, this); | ||
_header = header.Name ?? parameter.Name; | ||
} | ||
|
||
public Variable Variable { get; } | ||
|
||
public override IEnumerable<Variable> FindVariables(IMethodVariables chain) | ||
{ | ||
_httpContext = chain.FindVariable(typeof(HttpContext)); | ||
yield return _httpContext; | ||
} | ||
|
||
public override void GenerateCode(GeneratedMethod method, ISourceWriter writer) | ||
{ | ||
writer.Write($"var {Variable.Usage} = {nameof(HttpHandler.ReadSingleHeaderValue)}({_httpContext.Usage}, \"{_header}\");"); | ||
Next?.GenerateCode(method, writer); | ||
} | ||
} | ||
|
||
internal class ParsedHeaderValue : SyncFrame | ||
{ | ||
private readonly string _header; | ||
private Variable? _httpContext; | ||
|
||
public ParsedHeaderValue(IFromHeaderMetadata header, ParameterInfo parameter) | ||
{ | ||
_header = header.Name ?? parameter.Name!; | ||
Variable = new Variable(parameter.ParameterType, parameter.Name!, this); | ||
} | ||
|
||
public override IEnumerable<Variable> FindVariables(IMethodVariables chain) | ||
{ | ||
_httpContext = chain.FindVariable(typeof(HttpContext)); | ||
yield return _httpContext; | ||
} | ||
|
||
public Variable Variable { get; } | ||
|
||
public override void GenerateCode(GeneratedMethod method, ISourceWriter writer) | ||
{ | ||
var alias = Variable.VariableType.ShortNameInCode(); | ||
writer.Write($"{alias} {Variable.Usage} = default;"); | ||
writer.Write($"{alias}.TryParse({nameof(HttpHandler.ReadSingleHeaderValue)}({_httpContext!.Usage}, \"{_header}\"), out {Variable.Usage});"); | ||
|
||
Next?.GenerateCode(method, writer); | ||
} | ||
} |
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
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,26 @@ | ||
using JasperFx.Core; | ||
using Microsoft.AspNetCore.Mvc; | ||
using Wolverine.Http; | ||
|
||
namespace WolverineWebApi; | ||
|
||
public class HeaderUsingEndpoint | ||
{ | ||
[WolverineGet("/headers/simple")] | ||
public string Get([FromHeader(Name = "x-wolverine")] string name) | ||
{ | ||
return name; | ||
} | ||
|
||
[WolverineGet("/headers/int")] | ||
public string Get([FromHeader(Name = "x-wolverine")] int number) | ||
{ | ||
return (number * 2).ToString(); | ||
} | ||
|
||
[WolverineGet("/headers/accepts")] | ||
public string GetETag([FromHeader] string accepts) | ||
{ | ||
return accepts; | ||
} | ||
} |
36 changes: 36 additions & 0 deletions
36
src/Http/WolverineWebApi/Internal/Generated/WolverineHandlers/GET_headers_accepts.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,36 @@ | ||
// <auto-generated/> | ||
#pragma warning disable | ||
using Microsoft.AspNetCore.Routing; | ||
using System; | ||
using System.Linq; | ||
using Wolverine.Http; | ||
|
||
namespace Internal.Generated.WolverineHandlers | ||
{ | ||
// START: GET_headers_accepts | ||
public class GET_headers_accepts : Wolverine.Http.HttpHandler | ||
{ | ||
private readonly Wolverine.Http.WolverineHttpOptions _options; | ||
|
||
public GET_headers_accepts(Wolverine.Http.WolverineHttpOptions options) : base(options) | ||
{ | ||
_options = options; | ||
} | ||
|
||
|
||
|
||
public override async System.Threading.Tasks.Task Handle(Microsoft.AspNetCore.Http.HttpContext httpContext) | ||
{ | ||
var headerUsingEndpoint = new WolverineWebApi.HeaderUsingEndpoint(); | ||
var accepts = ReadSingleHeaderValue(httpContext, "accepts"); | ||
var result_of_GetETag = headerUsingEndpoint.GetETag(accepts); | ||
await WriteString(httpContext, result_of_GetETag); | ||
} | ||
|
||
} | ||
|
||
// END: GET_headers_accepts | ||
|
||
|
||
} | ||
|
37 changes: 37 additions & 0 deletions
37
src/Http/WolverineWebApi/Internal/Generated/WolverineHandlers/GET_headers_int.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,37 @@ | ||
// <auto-generated/> | ||
#pragma warning disable | ||
using Microsoft.AspNetCore.Routing; | ||
using System; | ||
using System.Linq; | ||
using Wolverine.Http; | ||
|
||
namespace Internal.Generated.WolverineHandlers | ||
{ | ||
// START: GET_headers_int | ||
public class GET_headers_int : Wolverine.Http.HttpHandler | ||
{ | ||
private readonly Wolverine.Http.WolverineHttpOptions _options; | ||
|
||
public GET_headers_int(Wolverine.Http.WolverineHttpOptions options) : base(options) | ||
{ | ||
_options = options; | ||
} | ||
|
||
|
||
|
||
public override async System.Threading.Tasks.Task Handle(Microsoft.AspNetCore.Http.HttpContext httpContext) | ||
{ | ||
var headerUsingEndpoint = new WolverineWebApi.HeaderUsingEndpoint(); | ||
int number = default; | ||
int.TryParse(ReadSingleHeaderValue(httpContext, "x-wolverine"), out number); | ||
var result_of_Get = headerUsingEndpoint.Get(number); | ||
await WriteString(httpContext, result_of_Get); | ||
} | ||
|
||
} | ||
|
||
// END: GET_headers_int | ||
|
||
|
||
} | ||
|
36 changes: 36 additions & 0 deletions
36
src/Http/WolverineWebApi/Internal/Generated/WolverineHandlers/GET_headers_simple.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,36 @@ | ||
// <auto-generated/> | ||
#pragma warning disable | ||
using Microsoft.AspNetCore.Routing; | ||
using System; | ||
using System.Linq; | ||
using Wolverine.Http; | ||
|
||
namespace Internal.Generated.WolverineHandlers | ||
{ | ||
// START: GET_headers_simple | ||
public class GET_headers_simple : Wolverine.Http.HttpHandler | ||
{ | ||
private readonly Wolverine.Http.WolverineHttpOptions _options; | ||
|
||
public GET_headers_simple(Wolverine.Http.WolverineHttpOptions options) : base(options) | ||
{ | ||
_options = options; | ||
} | ||
|
||
|
||
|
||
public override async System.Threading.Tasks.Task Handle(Microsoft.AspNetCore.Http.HttpContext httpContext) | ||
{ | ||
var headerUsingEndpoint = new WolverineWebApi.HeaderUsingEndpoint(); | ||
var name = ReadSingleHeaderValue(httpContext, "x-wolverine"); | ||
var result_of_Get = headerUsingEndpoint.Get(name); | ||
await WriteString(httpContext, result_of_Get); | ||
} | ||
|
||
} | ||
|
||
// END: GET_headers_simple | ||
|
||
|
||
} | ||
|