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
7 changes: 5 additions & 2 deletions WolverineWebApiFSharp/Library.fs
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,8 @@ open Wolverine.Http
[<WolverinePost("/discovered-fsharp-unit")>]
let myHandler() =
task {
()
}
()
}

[<WolverineGet("/fsharp/is-authenticated")>]
let isAuthenticated () = true
26 changes: 26 additions & 0 deletions src/Http/Wolverine.Http.Tests/end_to_end.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,32 @@ public async Task post_returning_fsharp_taskunit()
});
}

[Fact]
public async Task get_fsharp_bool_endpoint()
{
var body = await Scenario(x =>
{
x.Get.Url("/fsharp/is-authenticated");
x.StatusCodeShouldBeOk();
});

var result = body.ReadAsJson<bool>();
result.ShouldBeTrue();
}

[Fact]
public async Task get_csharp_static_bool_endpoint()
{
var body = await Scenario(x =>
{
x.Get.Url("/simple/bool");
x.StatusCodeShouldBeOk();
});

var result = body.ReadAsJson<bool>();
result.ShouldBeTrue();
}

[Fact]
public async Task retrieve_json_data()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,20 @@ public void discover_endpoint_returning_fsharp_taskunit()
chain.ShouldNotBeNull();
}

[Fact]
public void discover_fsharp_bool_endpoint()
{
var chain = HttpChains.ChainFor("GET", "/fsharp/is-authenticated");
chain.ShouldNotBeNull();
}

[Fact]
public void discover_csharp_static_bool_endpoint()
{
var chain = HttpChains.ChainFor("GET", "/simple/bool");
chain.ShouldNotBeNull();
}

[Fact]
public void read_order_from_attribute()
{
Expand Down
10 changes: 3 additions & 7 deletions src/Http/Wolverine.Http/HttpChain.Codegen.cs
Original file line number Diff line number Diff line change
Expand Up @@ -84,15 +84,11 @@ bool ICodeFile.AttachTypesSynchronously(GenerationRules rules, Assembly assembly
string containingNamespace)
{
Debug.WriteLine(_generatedType?.SourceCode);

_handlerType = assembly.ExportedTypes.FirstOrDefault(x => x.Name == _fileName);

if (_handlerType == null)
{
return false;
}
_handlerType = assembly.ExportedTypes.FirstOrDefault(x => x.Name == _fileName)
?? assembly.GetTypes().FirstOrDefault(x => x.Name == _fileName);

return true;
return _handlerType != null;
}

string ICodeFile.FileName => _fileName!;
Expand Down
41 changes: 20 additions & 21 deletions src/Http/Wolverine.Http/HttpChain.EndpointBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -46,43 +46,42 @@ private bool tryApplyAsEndpointMetadataProvider(Type? type, RouteEndpointBuilder
return false;
}

private HttpHandler buildHandler()
{
this.InitializeSynchronously(_parent.Rules, _parent, _parent.Container.Services);

if (_handlerType == null)
{
throw new InvalidOperationException(
$"Failed to resolve the generated handler type for endpoint {_fileName} " +
$"({string.Join(", ", _httpMethods)} {RoutePattern?.RawText}) " +
$"on handler type {Method.HandlerType.FullNameInCode()}. " +
$"The generated source code was:\n{_generatedType?.SourceCode}");
}

return (HttpHandler)_parent.Container.QuickBuild(_handlerType);
}

public RouteEndpoint BuildEndpoint(RouteWarmup warmup)
{
if (Endpoint != null) return Endpoint;

RequestDelegate? requestDelegate = null;
if (_parent.Rules.TypeLoadMode == TypeLoadMode.Static && !DynamicCodeBuilder.WithinCodegenCommand)
{
this.InitializeSynchronously(_parent.Rules, _parent, _parent.Container.Services);
var handler = (HttpHandler)_parent.Container.QuickBuild(_handlerType);
var handler = buildHandler();
requestDelegate = handler.Handle;
}
else
{
if (warmup == RouteWarmup.Eager && !DynamicCodeBuilder.WithinCodegenCommand)
{
this.InitializeSynchronously(_parent.Rules, _parent, _parent.Container.Services);
var handler = (HttpHandler)_parent.Container.QuickBuild(_handlerType);
var handler = buildHandler();
requestDelegate = c => handler.Handle(c);
}
else
{
var handler = new Lazy<HttpHandler>(() =>
{
this.InitializeSynchronously(_parent.Rules, _parent, _parent.Container.Services);

try
{
return (HttpHandler)_parent.Container.QuickBuild(_handlerType);
}
catch (Exception e)
{
throw new InvalidOperationException(
"Wolverine may be having trouble with concurrent access to the same route at startup. Set the WolverineHttpOptions.Warmup = Eager to work around this problem",
e);
}
});

var handler = new Lazy<HttpHandler>(buildHandler);
requestDelegate = c => handler.Value.Handle(c);
}
}
Expand Down
6 changes: 6 additions & 0 deletions src/Http/WolverineWebApi/FakeEndpoint.cs
Original file line number Diff line number Diff line change
Expand Up @@ -76,4 +76,10 @@ public string ReadEnumArgument(Direction direction)
}
}

public static class NoDependencyEndpoints
{
[WolverineGet("/simple/bool")]
public static bool GetBool() => true;
}

public class BigResponse;
Loading