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
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
using System.Net;
using Alba;
using IntegrationTests;
using Marten;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
using Wolverine.Marten;

namespace Wolverine.Http.Tests.Bugs;

public class Bug_1941_do_not_try_to_parse_IPAddress
{
[Fact]
public async Task pipe_ipaddress_from_load_to_main_handle_method()
{
var builder = WebApplication.CreateBuilder([]);

builder.Services.AddMarten(opts =>
{
// Establish the connection string to your Marten database
opts.Connection(Servers.PostgresConnectionString);
opts.DisableNpgsqlLogging = true;
}).IntegrateWithWolverine();

builder.Host.UseWolverine(opts =>
{
opts.Discovery.DisableConventionalDiscovery().IncludeType(typeof(IpEndpoint));
opts.ApplicationAssembly = GetType().Assembly;
});

builder.Services.AddWolverineHttp();

// This is using Alba, which uses WebApplicationFactory under the covers
await using var host = await AlbaHost.For(builder, app =>
{
app.MapWolverineEndpoints(x =>
{
x.AddMiddleware(typeof(RequestIpMiddleware));
});
});

var result = await host.Scenario(x =>
{
x.Post.Json(new IpRequest { Name = "Jeremy", Age = 51 }).ToUrl("/ip");
});
}
}

public class RequestIpMiddleware
{
public static (IResult, IPAddress?) LoadAsync(HttpContext httpContext)
{
var ip = httpContext.Connection.RemoteIpAddress;
if (ip != null && ip.IsIPv4MappedToIPv6)
{
ip = ip.MapToIPv4();
}
return (WolverineContinue.Result(), ip);
}
}

public class IpRequest
{
public string Name { get; set; }
public int Age { get; set; }
}

public static class IpEndpoint
{

[WolverinePost("/ip")]
public static string Get(IpRequest request, IPAddress? address)
{
return address?.ToString() ?? "no address";
}
}
24 changes: 20 additions & 4 deletions src/Http/Wolverine.Http/CodeGen/ResultContinuationPolicy.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,13 @@ public bool TryFindContinuationHandler(IChain chain, MethodCall call, out Frame?

if (result != null)
{
// Preventing double generation
if (chain.Middleware.OfType<MaybeEndWithResultFrame>().Any(x => ReferenceEquals(x.Result, result)))
{
frame = null;
return false;
}

frame = new MaybeEndWithResultFrame(result);
return true;
}
Expand All @@ -31,15 +38,16 @@ public bool TryFindContinuationHandler(IChain chain, MethodCall call, out Frame?
/// </summary>
public class MaybeEndWithResultFrame : AsyncFrame
{
private readonly Variable _result;
private Variable? _context;

public MaybeEndWithResultFrame(Variable result)
{
uses.Add(result);
_result = result;
Result = result;
}

public Variable Result { get; }

public override IEnumerable<Variable> FindVariables(IMethodVariables chain)
{
_context = chain.FindVariable(typeof(HttpContext));
Expand All @@ -48,9 +56,17 @@ public override IEnumerable<Variable> FindVariables(IMethodVariables chain)

public override void GenerateCode(GeneratedMethod method, ISourceWriter writer)
{
// Super hacky. Cannot for the life of me stop the double generation of "maybe end with IResult", so
// this.
if (Next is MaybeEndWithResultFrame next && ReferenceEquals(next.Result, Result))
{
Next?.GenerateCode(method, writer);
return;
}

writer.WriteComment("Evaluate whether or not the execution should be stopped based on the IResult value");
writer.Write($"BLOCK:if ({_result.Usage} != null && !({_result.Usage} is {typeof(WolverineContinue).FullNameInCode()}))");
writer.Write($"await {_result.Usage}.{nameof(IResult.ExecuteAsync)}({_context!.Usage}).ConfigureAwait(false);");
writer.Write($"BLOCK:if ({Result.Usage} != null && !({Result.Usage} is {typeof(WolverineContinue).FullNameInCode()}))");
writer.Write($"await {Result.Usage}.{nameof(IResult.ExecuteAsync)}({_context!.Usage}).ConfigureAwait(false);");
writer.Write("return;");
writer.FinishBlock();
writer.BlankLine();
Expand Down
4 changes: 4 additions & 0 deletions src/Http/Wolverine.Http/CodeGen/RouteHandling.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using System.Net;
using System.Reflection;
using JasperFx;
using JasperFx.CodeGeneration;
Expand Down Expand Up @@ -56,6 +57,9 @@ public bool TryMatch(HttpChain chain, IServiceContainer container, ParameterInfo

public static bool CanParse(Type argType)
{
// Edge case from GH-1941
if (argType == typeof(IPAddress)) return false;

return TypeOutputs.ContainsKey(argType) || argType.IsEnum || argType.GetMethods().Any( x=> x.Name == "TryParse");
}

Expand Down
Loading