예제 #1
0
        private object TransformInput(object input, Dictionary <string, object> bindingData)
        {
            if (input is Stream)
            {
                var dataType = _bindingMetadata.DataType ?? DataType.String;
                FunctionBinding.ConvertStreamToValue((Stream)input, dataType, ref input);
            }

            // TODO: investigate moving POCO style binding addition to sdk
            Utility.ApplyBindingData(input, bindingData);
            return(input);
        }
예제 #2
0
        public async Task BindAsyncCollectorAsync_JObjectCollection()
        {
            JArray values = new JArray();

            for (int i = 1; i <= 3; i++)
            {
                JObject jsonObject = new JObject
                {
                    { "prop1", "value1" },
                    { "prop2", true },
                    { "prop3", 123 }
                };
                values.Add(jsonObject);
            }

            string json          = values.ToString();
            var    results       = new JArray();
            var    collectorMock = new Mock <IAsyncCollector <JObject> >(MockBehavior.Strict);

            collectorMock.Setup(p => p.AddAsync(It.IsAny <JObject>(), CancellationToken.None))
            .Callback <JObject, CancellationToken>((mockObject, mockToken) =>
            {
                results.Add(mockObject);
            }).Returns(Task.CompletedTask);

            var binderMock = new Mock <Binder>(MockBehavior.Strict);
            var attributes = new Attribute[] { new QueueAttribute("test") };

            binderMock.Setup(p => p.BindAsync <IAsyncCollector <JObject> >(attributes, CancellationToken.None)).ReturnsAsync(collectorMock.Object);

            BindingContext bindingContext = new BindingContext
            {
                Attributes = attributes,
                Binder     = binderMock.Object,
                Value      = json
            };

            await FunctionBinding.BindAsyncCollectorAsync <JObject>(bindingContext);

            Assert.Equal(3, results.Count);
            for (int i = 0; i < 3; i++)
            {
                JObject jsonObject = (JObject)results[i];
                Assert.Equal("value1", (string)jsonObject["prop1"]);
                Assert.Equal(true, (bool)jsonObject["prop2"]);
                Assert.Equal(123, (int)jsonObject["prop3"]);
            }
        }
예제 #3
0
        public async Task BindAsyncCollectorAsync_JObjectCollection()
        {
            JArray values = new JArray();

            for (int i = 1; i <= 3; i++)
            {
                JObject jsonObject = new JObject
                {
                    { "prop1", "value1" },
                    { "prop2", true },
                    { "prop3", 123 }
                };
                values.Add(jsonObject);
            }

            string json = values.ToString();

            byte[]       bytes = Encoding.UTF8.GetBytes(json);
            MemoryStream ms    = new MemoryStream(bytes);

            var results       = new JArray();
            var collectorMock = new Mock <IAsyncCollector <JObject> >(MockBehavior.Strict);

            collectorMock.Setup(p => p.AddAsync(It.IsAny <JObject>(), CancellationToken.None))
            .Callback <JObject, CancellationToken>((mockObject, mockToken) =>
            {
                results.Add(mockObject);
            }).Returns(Task.CompletedTask);

            var                   binderMock = new Mock <IBinderEx>(MockBehavior.Strict);
            QueueAttribute        attribute  = new QueueAttribute("test");
            RuntimeBindingContext context    = new RuntimeBindingContext(attribute);

            binderMock.Setup(p => p.BindAsync <IAsyncCollector <JObject> >(context, CancellationToken.None)).ReturnsAsync(collectorMock.Object);

            await FunctionBinding.BindAsyncCollectorAsync <JObject>(ms, binderMock.Object, context);

            Assert.Equal(3, results.Count);
            for (int i = 0; i < 3; i++)
            {
                JObject jsonObject = (JObject)results[i];
                Assert.Equal("value1", (string)jsonObject["prop1"]);
                Assert.Equal(true, (bool)jsonObject["prop2"]);
                Assert.Equal(123, (int)jsonObject["prop3"]);
            }
        }
        public void TryCreateReturnValueParameterDescriptor_NoReturnBinding_ReturnsExpectedValue()
        {
            JObject json = new JObject
            {
                { "type", "httpTrigger" },
                { "name", "myInput" },
                { "direction", "in" }
            };
            FunctionBinding functionBinding = TestHelpers.CreateTestBinding(json);

            FunctionBinding[] bindings = new FunctionBinding[] { functionBinding };

            ParameterDescriptor descriptor = null;
            var result = DotNetFunctionDescriptorProvider.TryCreateReturnValueParameterDescriptor(typeof(void), bindings, out descriptor);

            Assert.False(result);
        }
        public virtual bool TryCreate(FunctionMetadata functionMetadata, out FunctionDescriptor functionDescriptor)
        {
            if (functionMetadata == null)
            {
                throw new InvalidOperationException("functionMetadata");
            }

            ValidateFunction(functionMetadata);

            // parse the bindings
            Collection <FunctionBinding> inputBindings  = FunctionBinding.GetBindings(Config, BindingProviders, functionMetadata.InputBindings, FileAccess.Read);
            Collection <FunctionBinding> outputBindings = FunctionBinding.GetBindings(Config, BindingProviders, functionMetadata.OutputBindings, FileAccess.Write);

            VerifyResolvedBindings(functionMetadata, inputBindings, outputBindings);

            BindingMetadata triggerMetadata = functionMetadata.InputBindings.FirstOrDefault(p => p.IsTrigger);
            string          scriptFilePath  = Path.Combine(Config.RootScriptPath, functionMetadata.ScriptFile ?? string.Empty);

            functionDescriptor = null;
            IFunctionInvoker invoker = null;

            try
            {
                invoker = CreateFunctionInvoker(scriptFilePath, triggerMetadata, functionMetadata, inputBindings, outputBindings);

                Collection <CustomAttributeBuilder> methodAttributes = new Collection <CustomAttributeBuilder>();
                Collection <ParameterDescriptor>    parameters       = GetFunctionParameters(invoker, functionMetadata, triggerMetadata, methodAttributes, inputBindings, outputBindings);

                functionDescriptor = new FunctionDescriptor(functionMetadata.Name, invoker, functionMetadata, parameters, methodAttributes, inputBindings, outputBindings);

                return(true);
            }
            catch (Exception ex)
            {
                Host.Logger.LogTrace(ex, $"Creating function descriptor for function {functionMetadata.Name} failed");
                IDisposable disposableInvoker = invoker as IDisposable;
                if (disposableInvoker != null)
                {
                    disposableInvoker.Dispose();
                }

                throw;
            }
        }
예제 #6
0
        public void ReadAsCollection_StringArray()
        {
            JArray values = new JArray();

            values.Add("Value1");
            values.Add("Value2");
            values.Add("Value3");

            string json = values.ToString();

            byte[]       bytes = Encoding.UTF8.GetBytes(json);
            MemoryStream ms    = new MemoryStream(bytes);

            var collection = FunctionBinding.ReadAsCollection(ms).Cast <JValue>().ToArray();

            Assert.Equal(3, collection.Length);
            Assert.Equal("Value1", (string)collection[0]);
            Assert.Equal("Value2", (string)collection[1]);
            Assert.Equal("Value3", (string)collection[2]);
        }
예제 #7
0
        public void ReadAsCollection_ObjectSingleton()
        {
            JObject jsonObject = new JObject
            {
                { "prop1", "value1" },
                { "prop2", true },
                { "prop3", 123 }
            };

            string json = jsonObject.ToString();

            byte[]       bytes = Encoding.UTF8.GetBytes(json);
            MemoryStream ms    = new MemoryStream(bytes);

            var result = FunctionBinding.ReadAsCollection(ms).Cast <JObject>().ToArray();

            Assert.Equal(1, result.Length);
            jsonObject = (JObject)result[0];
            Assert.Equal("value1", (string)jsonObject["prop1"]);
            Assert.Equal(true, (bool)jsonObject["prop2"]);
            Assert.Equal(123, (int)jsonObject["prop3"]);
        }
        public void TryCreateReturnValueParameterDescriptor_ReturnBindingPresent_ReturnsExpectedValue()
        {
            JObject json = new JObject
            {
                { "type", "blob" },
                { "name", ScriptConstants.SystemReturnParameterBindingName },
                { "direction", "out" },
                { "path", "foo/bar" }
            };

            _host = new HostBuilder().ConfigureDefaultTestWebScriptHost(b =>
            {
                b.AddAzureStorage();
            }).Build();

            FunctionBinding functionBinding = TestHelpers.CreateBindingFromHost(_host, json);

            FunctionBinding[] bindings = new FunctionBinding[] { functionBinding };

            ParameterDescriptor descriptor = null;
            var result = DotNetFunctionDescriptorProvider.TryCreateReturnValueParameterDescriptor(typeof(string), bindings, out descriptor);

            Assert.True(result);
            Assert.Equal(ScriptConstants.SystemReturnParameterName, descriptor.Name);
            Assert.True((descriptor.Attributes & ParameterAttributes.Out) != 0);
            Assert.Equal(typeof(string).MakeByRefType(), descriptor.Type);
            Assert.Equal(1, descriptor.CustomAttributes.Count);

            result = DotNetFunctionDescriptorProvider.TryCreateReturnValueParameterDescriptor(typeof(Task <string>), bindings, out descriptor);
            Assert.True(result);
            Assert.Equal(ScriptConstants.SystemReturnParameterName, descriptor.Name);
            Assert.True((descriptor.Attributes & ParameterAttributes.Out) != 0);
            Assert.Equal(typeof(string).MakeByRefType(), descriptor.Type);
            Assert.Equal(1, descriptor.CustomAttributes.Count);

            // return type task means no return value
            result = DotNetFunctionDescriptorProvider.TryCreateReturnValueParameterDescriptor(typeof(Task), bindings, out descriptor);
            Assert.False(result);
        }
예제 #9
0
        public void TryCreateReturnValueParameterDescriptor_ReturnBindingPresent_ReturnsExpectedValue()
        {
            JObject json = new JObject
            {
                { "type", "blob" },
                { "name", ScriptConstants.SystemReturnParameterBindingName },
                { "direction", "out" },
                { "path", "foo/bar" }
            };
            FunctionBinding functionBinding = TestHelpers.CreateTestBinding(json);

            FunctionBinding[] bindings = new FunctionBinding[] { functionBinding };

            ParameterDescriptor descriptor = null;
            var result = DotNetFunctionDescriptorProvider.TryCreateReturnValueParameterDescriptor(typeof(string), bindings, out descriptor);

            Assert.True(result);
            Assert.Equal(ScriptConstants.SystemReturnParameterName, descriptor.Name);
            Assert.True((descriptor.Attributes & ParameterAttributes.Out) != 0);
            Assert.Equal(typeof(string).MakeByRefType(), descriptor.Type);
            Assert.Equal(1, descriptor.CustomAttributes.Count);

            result = DotNetFunctionDescriptorProvider.TryCreateReturnValueParameterDescriptor(typeof(Task <string>), bindings, out descriptor);
            Assert.True(result);
            Assert.Equal(ScriptConstants.SystemReturnParameterName, descriptor.Name);
            Assert.True((descriptor.Attributes & ParameterAttributes.Out) != 0);
            Assert.Equal(typeof(string).MakeByRefType(), descriptor.Type);
            Assert.Equal(1, descriptor.CustomAttributes.Count);

            var ex = Assert.Throws <InvalidOperationException>(() =>
            {
                DotNetFunctionDescriptorProvider.TryCreateReturnValueParameterDescriptor(typeof(Task), bindings, out descriptor);
            });

            Assert.Equal($"{ScriptConstants.SystemReturnParameterBindingName} cannot be bound to return type {typeof(Task).Name}.", ex.Message);
        }
        private Dictionary <string, object> CreateScriptExecutionContext(object input, DataType dataType, Binder binder, TraceWriter traceWriter, TraceWriter fileTraceWriter, ExecutionContext functionExecutionContext)
        {
            // create a TraceWriter wrapper that can be exposed to Node.js
            var log = (Func <object, Task <object> >)(p =>
            {
                string text = p as string;
                if (text != null)
                {
                    traceWriter.Info(text);
                    fileTraceWriter.Info(text);
                }

                return(Task.FromResult <object>(null));
            });

            var bindings = new Dictionary <string, object>();
            var bind     = (Func <object, Task <object> >)(p =>
            {
                IDictionary <string, object> bindValues = (IDictionary <string, object>)p;
                foreach (var bindValue in bindValues)
                {
                    bindings[bindValue.Key] = bindValue.Value;
                }
                return(Task.FromResult <object>(null));
            });

            var context = new Dictionary <string, object>()
            {
                { "invocationId", functionExecutionContext.InvocationId },
                { "log", log },
                { "bindings", bindings },
                { "bind", bind }
            };

            if (!string.IsNullOrEmpty(_entryPoint))
            {
                context["entryPoint"] = _entryPoint;
            }

            // This is the input value that we will use to extract binding data.
            // Since binding data extraction is based on JSON parsing, in the
            // various conversions below, we set this to the appropriate JSON
            // string when possible.
            object bindDataInput = input;

            if (input is HttpRequestMessage)
            {
                // convert the request to a json object
                HttpRequestMessage request = (HttpRequestMessage)input;
                string             rawBody = null;
                var requestObject          = CreateRequestObject(request, out rawBody);
                input = requestObject;

                if (rawBody != null)
                {
                    requestObject["rawBody"] = rawBody;
                    bindDataInput            = rawBody;
                }

                // If this is a WebHook function, the input should be the
                // request body
                HttpTriggerBindingMetadata httpBinding = _trigger as HttpTriggerBindingMetadata;
                if (httpBinding != null &&
                    !string.IsNullOrEmpty(httpBinding.WebHookType))
                {
                    input = requestObject["body"];

                    // make the entire request object available as well
                    // this is symmetric with context.res which we also support
                    context["req"] = requestObject;
                }
            }
            else if (input is TimerInfo)
            {
                TimerInfo timerInfo   = (TimerInfo)input;
                var       inputValues = new Dictionary <string, object>()
                {
                    { "isPastDue", timerInfo.IsPastDue }
                };
                if (timerInfo.ScheduleStatus != null)
                {
                    inputValues["last"] = timerInfo.ScheduleStatus.Last.ToString("s", CultureInfo.InvariantCulture);
                    inputValues["next"] = timerInfo.ScheduleStatus.Next.ToString("s", CultureInfo.InvariantCulture);
                }
                input = inputValues;
            }
            else if (input is Stream)
            {
                FunctionBinding.ConvertStreamToValue((Stream)input, dataType, ref input);
            }

            ApplyBindingData(bindDataInput, binder);

            // normalize the bindingData object passed into Node
            // we must convert values to types supported by Edge
            // marshalling as needed
            Dictionary <string, object> normalizedBindingData = new Dictionary <string, object>();

            foreach (var pair in binder.BindingData)
            {
                var value = pair.Value;
                if (value != null && !IsEdgeSupportedType(value.GetType()))
                {
                    value = value.ToString();
                }
                normalizedBindingData[pair.Key] = value;
            }
            context["bindingData"] = normalizedBindingData;

            // if the input is json, try converting to an object or array
            object converted;

            if (TryConvertJson(input, out converted))
            {
                input = converted;
            }

            bindings.Add(_trigger.Name, input);

            return(context);
        }
예제 #11
0
        private async Task <IReadOnlyDictionary <string, IValueProvider> > BindCoreAsync(ValueBindingContext context, object value, IDictionary <string, object> parameters)
        {
            Dictionary <string, IValueProvider> valueProviders = new Dictionary <string, IValueProvider>();
            IValueProvider triggerProvider;
            IReadOnlyDictionary <string, object> bindingData;

            try
            {
                ITriggerData triggerData = await _triggerBinding.BindAsync(value, context);

                triggerProvider = triggerData.ValueProvider;
                bindingData     = triggerData.BindingData;
            }
            catch (OperationCanceledException)
            {
                throw;
            }
            catch (Exception exception)
            {
                triggerProvider = new BindingExceptionValueProvider(_triggerParameterName, exception);
                bindingData     = null;
            }
            valueProviders.Add(_triggerParameterName, triggerProvider);
            BindingContext bindingContext = FunctionBinding.NewBindingContext(context, bindingData, parameters);

            // Bind Singleton if specified
            SingletonAttribute singletonAttribute = SingletonManager.GetFunctionSingletonOrNull(_descriptor.Method, isTriggered: true);

            if (singletonAttribute != null)
            {
                string         boundScopeId           = _singletonManager.GetBoundScopeId(singletonAttribute.ScopeId, bindingData);
                IValueProvider singletonValueProvider = new SingletonValueProvider(_descriptor.Method, boundScopeId, context.FunctionInstanceId.ToString(), singletonAttribute, _singletonManager);
                valueProviders.Add(SingletonValueProvider.SingletonParameterName, singletonValueProvider);
            }

            foreach (KeyValuePair <string, IBinding> item in _nonTriggerBindings)
            {
                string         name    = item.Key;
                IBinding       binding = item.Value;
                IValueProvider valueProvider;

                try
                {
                    if (parameters != null && parameters.ContainsKey(name))
                    {
                        valueProvider = await binding.BindAsync(parameters[name], context);
                    }
                    else
                    {
                        valueProvider = await binding.BindAsync(bindingContext);
                    }
                }
                catch (OperationCanceledException)
                {
                    throw;
                }
                catch (Exception exception)
                {
                    valueProvider = new BindingExceptionValueProvider(name, exception);
                }

                valueProviders.Add(name, valueProvider);
            }

            return(valueProviders);
        }
예제 #12
0
        public virtual bool TryCreate(FunctionMetadata functionMetadata, out FunctionDescriptor functionDescriptor)
        {
            functionDescriptor = null;

            if (functionMetadata.IsDisabled)
            {
                return(false);
            }

            // parse the bindings
            Collection <FunctionBinding> inputBindings  = FunctionBinding.GetBindings(Config, functionMetadata.InputBindings, FileAccess.Read);
            Collection <FunctionBinding> outputBindings = FunctionBinding.GetBindings(Config, functionMetadata.OutputBindings, FileAccess.Write);

            BindingMetadata triggerMetadata      = functionMetadata.InputBindings.FirstOrDefault(p => p.IsTrigger);
            BindingType     triggerType          = triggerMetadata.Type;
            string          triggerParameterName = triggerMetadata.Name;
            bool            triggerNameSpecified = true;

            if (string.IsNullOrEmpty(triggerParameterName))
            {
                // default the name to simply 'input'
                triggerMetadata.Name = triggerParameterName = "input";
                triggerNameSpecified = false;
            }

            Collection <CustomAttributeBuilder> methodAttributes = new Collection <CustomAttributeBuilder>();
            ParameterDescriptor triggerParameter = null;
            bool omitInputParameter = false;

            switch (triggerType)
            {
            case BindingType.QueueTrigger:
                triggerParameter = ParseQueueTrigger((QueueBindingMetadata)triggerMetadata);
                break;

            case BindingType.BlobTrigger:
                triggerParameter = ParseBlobTrigger((BlobBindingMetadata)triggerMetadata);
                break;

            case BindingType.ServiceBusTrigger:
                triggerParameter = ParseServiceBusTrigger((ServiceBusBindingMetadata)triggerMetadata);
                break;

            case BindingType.TimerTrigger:
                omitInputParameter = true;
                triggerParameter   = ParseTimerTrigger((TimerBindingMetadata)triggerMetadata, typeof(TimerInfo));
                break;

            case BindingType.HttpTrigger:
                if (!triggerNameSpecified)
                {
                    triggerMetadata.Name = triggerParameterName = "req";
                }
                triggerParameter = ParseHttpTrigger((HttpBindingMetadata)triggerMetadata, methodAttributes, typeof(HttpRequestMessage));
                break;

            case BindingType.ManualTrigger:
                triggerParameter = ParseManualTrigger(triggerMetadata, methodAttributes);
                break;
            }

            Collection <ParameterDescriptor> parameters = new Collection <ParameterDescriptor>();

            triggerParameter.IsTrigger = true;
            parameters.Add(triggerParameter);

            // Add a TraceWriter for logging
            parameters.Add(new ParameterDescriptor("log", typeof(TraceWriter)));

            // Add an IBinder to support the binding programming model
            parameters.Add(new ParameterDescriptor("binder", typeof(IBinder)));

            // Add ExecutionContext to provide access to InvocationId, etc.
            parameters.Add(new ParameterDescriptor("context", typeof(ExecutionContext)));

            string           scriptFilePath = Path.Combine(Config.RootScriptPath, functionMetadata.Source);
            IFunctionInvoker invoker        = CreateFunctionInvoker(scriptFilePath, triggerMetadata, functionMetadata, omitInputParameter, inputBindings, outputBindings);

            functionDescriptor = new FunctionDescriptor(functionMetadata.Name, invoker, functionMetadata, parameters, methodAttributes);

            return(true);
        }
        private async Task <IReadOnlyDictionary <string, IValueProvider> > BindCoreAsync(ValueBindingContext context, object value, IDictionary <string, object> parameters)
        {
            Dictionary <string, IValueProvider> valueProviders = new Dictionary <string, IValueProvider>();
            IValueProvider triggerProvider;
            IReadOnlyDictionary <string, object> bindingData;

            IValueBinder triggerReturnValueProvider = null;

            try
            {
                ITriggerData triggerData = await _triggerBinding.BindAsync(value, context);

                triggerProvider            = triggerData.ValueProvider;
                bindingData                = triggerData.BindingData;
                triggerReturnValueProvider = (triggerData as TriggerData)?.ReturnValueProvider;
            }
            catch (OperationCanceledException)
            {
                throw;
            }
            catch (Exception exception)
            {
                triggerProvider = new BindingExceptionValueProvider(_triggerParameterName, exception);
                bindingData     = null;
            }

            valueProviders.Add(_triggerParameterName, triggerProvider);

            // Bind Singleton if specified
            SingletonAttribute singletonAttribute = SingletonManager.GetFunctionSingletonOrNull(_descriptor, isTriggered: true);

            if (singletonAttribute != null)
            {
                string         boundScopeId           = _singletonManager.GetBoundScopeId(singletonAttribute.ScopeId, bindingData);
                IValueProvider singletonValueProvider = new SingletonValueProvider(_descriptor, boundScopeId, context.FunctionInstanceId.ToString(), singletonAttribute, _singletonManager);
                valueProviders.Add(SingletonValueProvider.SingletonParameterName, singletonValueProvider);
            }

            BindingContext bindingContext = FunctionBinding.NewBindingContext(context, bindingData, parameters);

            foreach (KeyValuePair <string, IBinding> item in _nonTriggerBindings)
            {
                string         name    = item.Key;
                IBinding       binding = item.Value;
                IValueProvider valueProvider;

                try
                {
                    if (parameters != null && parameters.ContainsKey(name))
                    {
                        valueProvider = await binding.BindAsync(parameters[name], context);
                    }
                    else
                    {
                        valueProvider = await binding.BindAsync(bindingContext);
                    }
                }
                catch (OperationCanceledException)
                {
                    throw;
                }
                catch (Exception exception)
                {
                    valueProvider = new BindingExceptionValueProvider(name, exception);
                }

                valueProviders.Add(name, valueProvider);
            }

            // Triggers can optionally process the return values of functions. They do so by declaring
            // a "$return" key in their binding data dictionary and mapping it to an IValueBinder.
            // An explicit return binding takes precedence over an implicit trigger binding.
            if (!valueProviders.ContainsKey(FunctionIndexer.ReturnParamName))
            {
                if (triggerReturnValueProvider != null)
                {
                    valueProviders.Add(FunctionIndexer.ReturnParamName, triggerReturnValueProvider);
                }
            }

            return(valueProviders);
        }
예제 #14
0
 public void AcceptFunction(FunctionBinding function)
 {
     AddInvocable(function);
 }
예제 #15
0
        private Dictionary <string, object> CreateScriptExecutionContext(object input, DataType dataType, TraceWriter traceWriter, FunctionInvocationContext invocationContext)
        {
            // create a TraceWriter wrapper that can be exposed to Node.js
            var log = (Func <object, Task <object> >)(p =>
            {
                string text = p as string;
                if (text != null)
                {
                    try
                    {
                        traceWriter.Info(text);
                    }
                    catch (ObjectDisposedException)
                    {
                        // if a function attempts to write to a disposed
                        // TraceWriter. Might happen if a function tries to
                        // log after calling done()
                    }
                }

                return(Task.FromResult <object>(null));
            });

            var bindings = new Dictionary <string, object>();
            var bind     = (Func <object, Task <object> >)(p =>
            {
                IDictionary <string, object> bindValues = (IDictionary <string, object>)p;
                foreach (var bindValue in bindValues)
                {
                    bindings[bindValue.Key] = bindValue.Value;
                }
                return(Task.FromResult <object>(null));
            });

            var context = new Dictionary <string, object>()
            {
                { "invocationId", invocationContext.ExecutionContext.InvocationId },
                { "log", log },
                { "bindings", bindings },
                { "bind", bind }
            };

            if (!string.IsNullOrEmpty(_entryPoint))
            {
                context["_entryPoint"] = _entryPoint;
            }

            if (input is HttpRequestMessage)
            {
                // convert the request to a json object
                HttpRequestMessage request = (HttpRequestMessage)input;
                string             rawBody = null;
                var requestObject          = CreateRequestObject(request, out rawBody);
                input = requestObject;

                if (rawBody != null)
                {
                    requestObject["rawBody"] = rawBody;
                }

                // If this is a WebHook function, the input should be the
                // request body
                HttpTriggerBindingMetadata httpBinding = _trigger as HttpTriggerBindingMetadata;
                if (httpBinding != null &&
                    !string.IsNullOrEmpty(httpBinding.WebHookType))
                {
                    requestObject.TryGetValue("body", out input);
                }

                // make the entire request object available as well
                // this is symmetric with context.res which we also support
                context["req"] = requestObject;
            }
            else if (input is TimerInfo)
            {
                // TODO: Need to generalize this model rather than hardcode
                // so other extensions can also express their Node.js object model
                TimerInfo timerInfo   = (TimerInfo)input;
                var       inputValues = new Dictionary <string, object>()
                {
                    { "isPastDue", timerInfo.IsPastDue }
                };
                if (timerInfo.ScheduleStatus != null)
                {
                    inputValues["last"] = timerInfo.ScheduleStatus.Last.ToString("s", CultureInfo.InvariantCulture);
                    inputValues["next"] = timerInfo.ScheduleStatus.Next.ToString("s", CultureInfo.InvariantCulture);
                }
                input = inputValues;
            }
            else if (input is Stream)
            {
                FunctionBinding.ConvertStreamToValue((Stream)input, dataType, ref input);
            }

            Utility.ApplyBindingData(input, invocationContext.Binder.BindingData);
            var bindingData = NormalizeBindingData(invocationContext.Binder.BindingData);

            bindingData["invocationId"] = invocationContext.ExecutionContext.InvocationId.ToString();
            context["bindingData"]      = bindingData;

            // if the input is json, try converting to an object or array
            object converted;

            if (TryConvertJson(input, out converted))
            {
                input = converted;
            }

            bindings.Add(_trigger.Name, input);

            context.Add("_triggerType", _trigger.Type);

            return(context);
        }
예제 #16
0
 public ArgumentChecks()
 {
     _aDelegate        = ExceptionBuilder;
     _aParameterInfo   = _aMethodInfo.GetParameters()[0];
     _aFunctionBinding = new ReflectionFunctionBinding(_aMethodInfo, null, false);
 }
        private async Task <Dictionary <string, object> > CreateScriptExecutionContextAsync(object input, DataType dataType, TraceWriter traceWriter, FunctionInvocationContext invocationContext)
        {
            // create a TraceWriter wrapper that can be exposed to Node.js
            var log = (ScriptFunc)(p =>
            {
                var logData = (IDictionary <string, object>)p;
                string message = (string)logData["msg"];
                if (message != null)
                {
                    try
                    {
                        TraceLevel level = (TraceLevel)logData["lvl"];
                        var evt = new TraceEvent(level, message);

                        // Node captures the AsyncLocal value of the first invocation, which means that logs
                        // are correlated incorrectly. Here we'll overwrite that value with the correct value
                        // immediately before logging.
                        using (invocationContext.Logger.BeginScope(
                                   new Dictionary <string, object>
                        {
                            ["MS_FunctionInvocationId"] = invocationContext.ExecutionContext.InvocationId
                        }))
                        {
                            // TraceWriter already logs to ILogger
                            traceWriter.Trace(evt);
                        }
                    }
                    catch (ObjectDisposedException)
                    {
                        // if a function attempts to write to a disposed
                        // TraceWriter. Might happen if a function tries to
                        // log after calling done()
                    }
                }

                return(Task.FromResult <object>(null));
            });

            var bindings = new Dictionary <string, object>();
            var bind     = (ScriptFunc)(p =>
            {
                IDictionary <string, object> bindValues = (IDictionary <string, object>)p;
                foreach (var bindValue in bindValues)
                {
                    bindings[bindValue.Key] = bindValue.Value;
                }
                return(Task.FromResult <object>(null));
            });

            var executionContext = new Dictionary <string, object>
            {
                ["invocationId"]      = invocationContext.ExecutionContext.InvocationId,
                ["functionName"]      = invocationContext.ExecutionContext.FunctionName,
                ["functionDirectory"] = invocationContext.ExecutionContext.FunctionDirectory,
            };

            var context = new Dictionary <string, object>()
            {
                { "invocationId", invocationContext.ExecutionContext.InvocationId },
                { "executionContext", executionContext },
                { "log", log },
                { "bindings", bindings },
                { "bind", bind }
            };

            if (!string.IsNullOrEmpty(_entryPoint))
            {
                context["_entryPoint"] = _entryPoint;
            }

            // convert the request to a json object
            if (input is HttpRequestMessage request)
            {
                var requestObject = await CreateRequestObjectAsync(request).ConfigureAwait(false);

                input = requestObject;

                // If this is a WebHook function, the input should be the
                // request body
                var httpTrigger = _inputBindings.OfType <ExtensionBinding>().SingleOrDefault(p => p.Metadata.IsTrigger)?
                                  .Attributes.OfType <HttpTriggerAttribute>().SingleOrDefault();
                if (httpTrigger != null && !string.IsNullOrEmpty(httpTrigger.WebHookType))
                {
                    requestObject.TryGetValue("body", out input);
                }

                // make the entire request object available as well
                // this is symmetric with context.res which we also support
                context["req"] = requestObject;
            }
            else if (input is TimerInfo)
            {
                // TODO: Need to generalize this model rather than hardcode
                // so other extensions can also express their Node.js object model
                TimerInfo timerInfo   = (TimerInfo)input;
                var       inputValues = new Dictionary <string, object>()
                {
                    { "isPastDue", timerInfo.IsPastDue }
                };
                if (timerInfo.ScheduleStatus != null)
                {
                    inputValues["last"] = timerInfo.ScheduleStatus.Last.ToString("s", CultureInfo.InvariantCulture);
                    inputValues["next"] = timerInfo.ScheduleStatus.Next.ToString("s", CultureInfo.InvariantCulture);
                }
                input = inputValues;
            }
            else if (input is Stream)
            {
                FunctionBinding.ConvertStreamToValue((Stream)input, dataType, ref input);
            }

            Utility.ApplyBindingData(input, invocationContext.Binder.BindingData);

            var bindingData = NormalizeBindingData(invocationContext.Binder.BindingData);

            bindingData["invocationId"] = invocationContext.ExecutionContext.InvocationId.ToString();
            context["bindingData"]      = bindingData;

            // if the input is json, try converting to an object or array
            object converted;

            if (TryConvertJson(input, out converted))
            {
                input = converted;
            }

            bindings.Add(_trigger.Name, input);

            context.Add("_triggerType", _trigger.Type);

            return(context);
        }
예제 #18
0
        public static ArgumentException FunctionWithSameNameAndSignatureAlreadyInCollection(string paramName, FunctionBinding functionBinding)
        {
            if (paramName == null)
            {
                throw new ArgumentNullException("paramName");
            }

            if (functionBinding == null)
            {
                throw new ArgumentNullException("functionBinding");
            }

            StringBuilder sb = new StringBuilder();

            sb.Append(functionBinding.Name);
            sb.Append("(");
            FormattingHelpers.FormatTypeList(functionBinding.GetParameterTypes());
            sb.Append(")");

            string signature = sb.ToString();
            string message   = String.Format(CultureInfo.CurrentCulture, Resources.FunctionWithSameNameAndSignatureAlreadyInCollection, signature);

            return(new ArgumentException(message, paramName));
        }