internal static bool TryParseFunctionMetadata(string functionName, JObject functionConfig, Dictionary<string, HttpTriggerBindingMetadata> mappedHttpFunctions, TraceWriter traceWriter, Lazy<string[]> functionFilesProvider, out FunctionMetadata functionMetadata, out string error)
{
error = null;
functionMetadata = ParseFunctionMetadata(functionName, functionConfig);
if (functionMetadata.IsExcluded)
{
traceWriter.Info(string.Format("Function '{0}' is marked as excluded", functionName));
functionMetadata = null;
return true;
}
if (functionMetadata.IsDisabled)
{
traceWriter.Info(string.Format("Function '{0}' is disabled", functionName));
}
// determine the primary script
string[] functionFiles = functionFilesProvider.Value;
if (functionFiles.Length == 0)
{
error = "No function script files present.";
return false;
}
string scriptFile = DeterminePrimaryScriptFile(functionConfig, functionFiles);
if (string.IsNullOrEmpty(scriptFile))
{
error =
"Unable to determine the primary function script. Try renaming your entry point script to 'run' (or 'index' in the case of Node), " +
"or alternatively you can specify the name of the entry point script explicitly by adding a 'scriptFile' property to your function metadata.";
return false;
}
functionMetadata.ScriptFile = scriptFile;
// determine the script type based on the primary script file extension
functionMetadata.ScriptType = ParseScriptType(functionMetadata.ScriptFile);
functionMetadata.EntryPoint = (string)functionConfig["entryPoint"];
var httpTriggerBindingMetadata = functionMetadata.InputBindings.OfType<HttpTriggerBindingMetadata>().SingleOrDefault();
if (httpTriggerBindingMetadata != null)
{
if (string.IsNullOrWhiteSpace(httpTriggerBindingMetadata.Route))
{
// if no explicit route is provided, default to the function name
httpTriggerBindingMetadata.Route = functionName;
}
// disallow custom routes in our own reserved route space
string httpRoute = httpTriggerBindingMetadata.Route.Trim('/').ToLowerInvariant();
if (httpRoute.StartsWith("admin"))
{
error = "The specified route conflicts with one or more built in routes.";
return false;
}
// prevent duplicate/conflicting routes
foreach (var pair in mappedHttpFunctions)
{
if (HttpRoutesConflict(httpTriggerBindingMetadata, pair.Value))
{
error = $"The route specified conflicts with the route defined by function '{pair.Key}'.";
return false;
}
}
mappedHttpFunctions.Add(functionName, httpTriggerBindingMetadata);
}
return true;
}