protected ParameterDescriptor ParseHttpTrigger(HttpTriggerBindingMetadata trigger, Type triggerParameterType = null) { if (trigger == null) { throw new ArgumentNullException("trigger"); } if (triggerParameterType == null) { triggerParameterType = typeof(string); } return(new ParameterDescriptor(trigger.Name, triggerParameterType)); }
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); }
protected ParameterDescriptor ParseHttpTrigger(HttpTriggerBindingMetadata trigger, Type triggerParameterType = null) { if (trigger == null) { throw new ArgumentNullException("trigger"); } if (triggerParameterType == null) { triggerParameterType = typeof(string); } return new ParameterDescriptor(trigger.Name, triggerParameterType); }
// A route is in conflict if the route matches any other existing // route and there is intersection in the http methods of the two functions internal static bool HttpRoutesConflict(HttpTriggerBindingMetadata functionMetadata, HttpTriggerBindingMetadata otherFunctionMetadata) { if (string.Compare(functionMetadata.Route.Trim('/'), otherFunctionMetadata.Route.Trim('/'), StringComparison.OrdinalIgnoreCase) != 0) { // routes differ, so no conflict return false; } if (functionMetadata.Methods == null || functionMetadata.Methods.Count == 0 || otherFunctionMetadata.Methods == null || otherFunctionMetadata.Methods.Count == 0) { // if either methods collection is null or empty that means // "all methods", which will intersect with any method collection return true; } return functionMetadata.Methods.Intersect(otherFunctionMetadata.Methods).Any(); }
private Dictionary <string, object> CreateScriptExecutionContext(object input, 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.Verbose(text); fileTraceWriter.Verbose(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 (input is HttpRequestMessage) { // convert the request to a json object HttpRequestMessage request = (HttpRequestMessage)input; var requestObject = CreateRequestObject(request); input = requestObject; // 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) { Stream inputStream = (Stream)input; using (StreamReader sr = new StreamReader(inputStream)) { input = sr.ReadToEnd(); } } else { // TODO: Handle case where the input type is something // that we can't convert properly } if (input is string) { // if the input is json, try converting to an object input = TryConvertJsonToObject((string)input); } bindings.Add(_trigger.Name, input); return(context); }
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); }
public void GenerateHttpTriggerFunction() { HttpTriggerBindingMetadata trigger = new HttpTriggerBindingMetadata { 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); }