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
            HttpBindingMetadata httpFunctionMetadata = (HttpBindingMetadata)function.Metadata.InputBindings.FirstOrDefault(p => p.Type == BindingType.HttpTrigger);
            string           webHookReceiver         = httpFunctionMetadata.WebHookType;
            IWebHookReceiver receiver = null;

            if (string.IsNullOrEmpty(webHookReceiver) || !_receiverLookup.TryGetValue(webHookReceiver, out receiver))
            {
                // If the function is a not a correctly configured WebHook return 500
                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);

            // TODO: Is there a better way? Requests content can't be read multiple
            // times, so this forces it to buffer
            await request.Content.ReadAsStringAsync();

            string receiverId = function.Name.ToLowerInvariant();

            return(await receiver.ReceiveAsync(receiverId, context, request));
        }
Exemple #2
0
        public void GenerateHttpTriggerFunction()
        {
            HttpBindingMetadata trigger = new HttpBindingMetadata
            {
                Type = BindingType.HttpTrigger
            };
            MethodInfo method = GenerateMethod(trigger);

            VerifyCommonProperties(method);

            // verify trigger parameter
            ParameterInfo parameter = method.GetParameters()[0];

            Assert.Equal("req", parameter.Name);
            Assert.Equal(typeof(HttpRequestMessage), parameter.ParameterType);
            NoAutomaticTriggerAttribute attribute = method.GetCustomAttribute <NoAutomaticTriggerAttribute>();

            Assert.NotNull(attribute);
        }
        public override async Task <HttpResponseMessage> ExecuteAsync(HttpControllerContext controllerContext, CancellationToken cancellationToken)
        {
            HttpRequestMessage request = controllerContext.Request;

            // First see if the request maps to an HTTP function
            FunctionDescriptor function = _scriptHostManager.GetHttpFunctionOrNull(request.RequestUri);

            if (function == null)
            {
                return(new HttpResponseMessage(HttpStatusCode.NotFound));
            }

            // Authorize the request
            SecretManager       secretManager        = (SecretManager)controllerContext.Configuration.DependencyResolver.GetService(typeof(SecretManager));
            HttpBindingMetadata httpFunctionMetadata = (HttpBindingMetadata)function.Metadata.InputBindings.FirstOrDefault(p => p.Type == BindingType.HttpTrigger);
            bool isWebHook = !string.IsNullOrEmpty(httpFunctionMetadata.WebHookType);

            if (!isWebHook && !AuthorizationLevelAttribute.IsAuthorized(request, httpFunctionMetadata.AuthLevel, secretManager, functionName: function.Name))
            {
                return(new HttpResponseMessage(HttpStatusCode.Unauthorized));
            }

            HttpResponseMessage response = null;

            if (isWebHook)
            {
                // This is a WebHook request so define a delegate for the user function.
                // The WebHook Receiver pipeline will first validate the request fully
                // then invoke this callback.
                Func <HttpRequestMessage, Task <HttpResponseMessage> > invokeFunction = async(req) =>
                {
                    return(await _scriptHostManager.HandleRequestAsync(function, req, cancellationToken));
                };
                response = await _webHookReceiverManager.HandleRequestAsync(function, request, invokeFunction);
            }
            else
            {
                // Not a WebHook request so dispatch directly
                response = await _scriptHostManager.HandleRequestAsync(function, request, cancellationToken);
            }

            return(response);
        }
        protected override void OnHostStarted()
        {
            base.OnHostStarted();

            // whenever the host is created (or recreated) we build a cache map of
            // all http function routes
            HttpFunctions = new Dictionary <string, FunctionDescriptor>();
            foreach (var function in Instance.Functions)
            {
                HttpBindingMetadata httpTriggerBinding = (HttpBindingMetadata)function.Metadata.InputBindings.SingleOrDefault(p => p.Type == BindingType.HttpTrigger);
                if (httpTriggerBinding != null)
                {
                    string route = httpTriggerBinding.Route;
                    if (!string.IsNullOrEmpty(route))
                    {
                        route += "/";
                    }
                    route += function.Name;

                    HttpFunctions.Add(route.ToLowerInvariant(), function);
                }
            }
        }
Exemple #5
0
        internal static Collection <FunctionBinding> GetBindings(ScriptHostConfiguration config, IEnumerable <BindingMetadata> bindingMetadatas, FileAccess fileAccess)
        {
            Collection <FunctionBinding> bindings = new Collection <FunctionBinding>();

            if (bindings != null)
            {
                foreach (var bindingMetadata in bindingMetadatas)
                {
                    BindingType type = bindingMetadata.Type;
                    string      name = bindingMetadata.Name;

                    switch (type)
                    {
                    case BindingType.Blob:
                    case BindingType.BlobTrigger:
                        BlobBindingMetadata blobBindingMetadata = (BlobBindingMetadata)bindingMetadata;
                        bindings.Add(new BlobBinding(config, name, blobBindingMetadata.Path, fileAccess, bindingMetadata.IsTrigger));
                        break;

                    case BindingType.Queue:
                    case BindingType.QueueTrigger:
                        QueueBindingMetadata queueBindingMetadata = (QueueBindingMetadata)bindingMetadata;
                        if (!queueBindingMetadata.IsTrigger &&
                            fileAccess != FileAccess.Write)
                        {
                            throw new InvalidOperationException("Queue binding can only be used for output.");
                        }
                        bindings.Add(new QueueBinding(config, name, queueBindingMetadata.QueueName, fileAccess, bindingMetadata.IsTrigger));
                        break;

                    case BindingType.ServiceBus:
                    case BindingType.ServiceBusTrigger:
                        ServiceBusBindingMetadata serviceBusBindingMetadata = (ServiceBusBindingMetadata)bindingMetadata;
                        if (!serviceBusBindingMetadata.IsTrigger &&
                            fileAccess != FileAccess.Write)
                        {
                            throw new InvalidOperationException("ServiceBus binding can only be used for output.");
                        }
                        string queueOrTopicName = serviceBusBindingMetadata.QueueName ?? serviceBusBindingMetadata.TopicName;
                        bindings.Add(new ServiceBusBinding(config, name, queueOrTopicName, fileAccess, bindingMetadata.IsTrigger));
                        break;

                    case BindingType.Table:
                        TableBindingMetadata tableBindingMetadata = (TableBindingMetadata)bindingMetadata;
                        TableQuery           tableQuery           = new TableQuery
                        {
                            TakeCount    = tableBindingMetadata.Take,
                            FilterString = tableBindingMetadata.Filter
                        };
                        bindings.Add(new TableBinding(config, name, tableBindingMetadata.TableName, tableBindingMetadata.PartitionKey, tableBindingMetadata.RowKey, fileAccess, tableQuery));
                        break;

                    case BindingType.Http:
                        HttpBindingMetadata httpBindingMetadata = (HttpBindingMetadata)bindingMetadata;
                        if (fileAccess != FileAccess.Write)
                        {
                            throw new InvalidOperationException("Http binding can only be used for output.");
                        }
                        name = name ?? "res";
                        bindings.Add(new HttpBinding(config, name, FileAccess.Write, bindingMetadata.IsTrigger));
                        break;
                    }
                }
            }

            return(bindings);
        }