Closed Alan-Hinton closed 3 months ago
Notes from investigation:
void
as return type for http trigger.In both cases (api/throw-exception-and-return/true
& api/throw-exception
), the worker is returning the same invocation response back to host. The host code which handles the invocation response is executing differently for these 2 cases.
The function metadata generated for the 2 functions are as below. note that the "throw-exception" function is missing the $return
binding.
public Task<ImmutableArray<IFunctionMetadata>> GetFunctionMetadataAsync(string directory)
{
var metadataList = new List<IFunctionMetadata>();
var Function0RawBindings = new List<string>();
Function0RawBindings.Add(@"{""name"":""req"",""type"":""httpTrigger"",""direction"":""In"",""authLevel"":""Anonymous"",""methods"":[""get""],""route"":""throw-exception""}");
var Function0 = new DefaultFunctionMetadata
{
Language = "dotnet-isolated",
Name = "ThrowException",
EntryPoint = "MiddlewareStatusCode.ExceptionController.ThrowException",
RawBindings = Function0RawBindings,
ScriptFile = "MiddlewareStatusCode.dll"
};
metadataList.Add(Function0);
var Function1RawBindings = new List<string>();
Function1RawBindings.Add(@"{""name"":""req"",""type"":""httpTrigger"",""direction"":""In"",""authLevel"":""Anonymous"",""methods"":[""get""],""route"":""throw-exception-and-return/{returnUsefullData}""}");
Function1RawBindings.Add(@"{""name"":""$return"",""type"":""http"",""direction"":""Out""}");
var Function1 = new DefaultFunctionMetadata
{
Language = "dotnet-isolated",
Name = "ThrowExceptionAndReturn",
EntryPoint = "MiddlewareStatusCode.ExceptionController.ThrowExceptionAndReturn",
RawBindings = Function1RawBindings,
ScriptFile = "MiddlewareStatusCode.dll"
};
metadataList.Add(Function1);
return Task.FromResult(metadataList.ToImmutableArray());
}
The WorkerFunctionInvoker.BindOutputAsync
relies on the output bindings from the metadata to handle the response(output binding data to be specific) after invocation.
For the "throw-exception-and-return" function, there is one output binding which causes the HttpBinding.BindAsync method to be invoked. For throw-exception
case, since there are no output bindings, the FunctionBinding.BindAsync
is not engaged at all, causing the response to be eventually serialized and sent out with a 200 status code.
Update metadata generation to create the $return
binding regardless of functions return type, if the function is Http trigger. What are the impacts of this change?
Update host code to use a fallback HttpBinding.BindAsync
For http trigger invocation, this could be the HttpBinding
binder.
Discussed this in triage. We'll move forward with option 1 and keep this issue open to track the work.
@Alan-Hinton
Version 1.17.4 of Worker.Sdk includes the fix for the issue. Please upgrade your package to this version, and feel free to reach out if you encounter any further issues.
See #936, which was closed despite not being fixed.
If you use the sample exception handling middleware and have an http triggered functions with
void
or bareTask
return type that throws an exception the request results in a 200 response and the whole http response is returned as json.I have created a minimal example which shows the error, as well as showing how returning a different return type works fine.
i.e. the request to the
void
function returns the wrong status code and responsewhereas the endpoint that has a non-void return type gives the correct 500 response
I have tried fiddling with the middleware to get this working, but there doesn't seem to be a way. So I think this is a bug in the underlying framework. There doesn't seem to be any reason I shouldn't be able to have a request with a
void
return type.