public async Task<HttpResponseMessage> HandleRequestAsync(FunctionDescriptor function, HttpRequestMessage request, Func<HttpRequestMessage, Task<HttpResponseMessage>> invokeFunction)
{
// First check if there is a registered WebHook Receiver for this request, and if
// so use it
HttpTriggerBindingMetadata httpFunctionMetadata = (HttpTriggerBindingMetadata)function.Metadata.InputBindings.FirstOrDefault(p => string.Compare("HttpTrigger", p.Type, StringComparison.OrdinalIgnoreCase) == 0);
string webHookReceiver = httpFunctionMetadata.WebHookType;
IWebHookReceiver receiver = null;
if (string.IsNullOrEmpty(webHookReceiver) || !_receiverLookup.TryGetValue(webHookReceiver, out receiver))
{
// The function is not correctly configured. Log an error and return 500
string configurationError = string.Format(CultureInfo.InvariantCulture, "Invalid WebHook configuration. Unable to find a receiver for WebHook type '{0}'", webHookReceiver);
function.Invoker.OnError(new FunctionInvocationException(configurationError));
return new HttpResponseMessage(System.Net.HttpStatusCode.InternalServerError);
}
HttpRequestContext context = new HttpRequestContext
{
Configuration = _httpConfiguration
};
request.SetConfiguration(_httpConfiguration);
// add the anonymous handler function from above to the request properties
// so our custom WebHookHandler can invoke it at the right time
request.Properties.Add(AzureFunctionsCallbackKey, invokeFunction);
// Request content can't be read multiple
// times, so this forces it to buffer
await request.Content.LoadIntoBufferAsync();
string receiverId = function.Name.ToLowerInvariant();
// Get an optional client ID. This information is passed as the receiver ID, allowing
// the receiver config to map configuration based on the client ID (primarily used for secret resolution).
string clientId = GetClientID(request);
string webhookId = $"{receiverId},{clientId}";
return await receiver.ReceiveAsync(webhookId, context, request);
}