Skip to content

Commit eab2e94

Browse files
committed
Fix SyncTriggers Null Ref #5635
1 parent 1ed2a54 commit eab2e94

File tree

3 files changed

+90
-42
lines changed

3 files changed

+90
-42
lines changed

src/WebJobs.Script.WebHost/Extensions/FunctionMetadataExtensions.cs

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -77,14 +77,18 @@ public static async Task<JObject> ToFunctionTrigger(this FunctionMetadata functi
7777
// Read function.json as a JObject
7878
var functionConfig = await GetFunctionConfig(functionMetadataFilePath);
7979

80-
// Find the trigger and add functionName to it
81-
foreach (JObject binding in (JArray)functionConfig["bindings"])
80+
if (functionConfig.TryGetValue("bindings", out JToken value) &&
81+
value is JArray)
8282
{
83-
var type = (string)binding["type"];
84-
if (type.EndsWith("Trigger", StringComparison.OrdinalIgnoreCase))
83+
// Find the trigger and add functionName to it
84+
foreach (JObject binding in (JArray)value)
8585
{
86-
binding.Add("functionName", functionMetadata.Name);
87-
return binding;
86+
var type = (string)binding["type"];
87+
if (type != null && type.EndsWith("Trigger", StringComparison.OrdinalIgnoreCase))
88+
{
89+
binding.Add("functionName", functionMetadata.Name);
90+
return binding;
91+
}
8892
}
8993
}
9094

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
// Copyright (c) .NET Foundation. All rights reserved.
2+
// Licensed under the MIT License. See License.txt in the project root for license information.
3+
4+
using System;
5+
using System.IO;
6+
using System.Linq;
7+
using System.Threading.Tasks;
8+
using Microsoft.Azure.WebJobs.Script.Description;
9+
using Microsoft.Azure.WebJobs.Script.WebHost.Extensions;
10+
using Newtonsoft.Json.Linq;
11+
using Xunit;
12+
13+
namespace Microsoft.Azure.WebJobs.Script.Tests.Extensions
14+
{
15+
public class FunctionMetadataExtensionsTests
16+
{
17+
private readonly string _testRootScriptPath;
18+
19+
public FunctionMetadataExtensionsTests()
20+
{
21+
_testRootScriptPath = Path.GetTempPath();
22+
}
23+
24+
[Theory]
25+
[InlineData("invalid")]
26+
[InlineData("{ bindings: [ {} ] }")]
27+
[InlineData("{ bindings: 'not an array' }")]
28+
public async Task ToFunctionTrigger_InvalidConfig_ReturnsNull(string functionConfig)
29+
{
30+
var functionMetadata = new FunctionMetadata
31+
{
32+
Name = "TestFunction"
33+
};
34+
var options = new ScriptJobHostOptions
35+
{
36+
RootScriptPath = _testRootScriptPath
37+
};
38+
var functionPath = Path.Combine(_testRootScriptPath, functionMetadata.Name);
39+
var functionMetadataFilePath = Path.Combine(functionPath, ScriptConstants.FunctionMetadataFileName);
40+
FileUtility.EnsureDirectoryExists(functionPath);
41+
File.WriteAllText(functionMetadataFilePath, functionConfig);
42+
43+
var result = await functionMetadata.ToFunctionTrigger(options);
44+
Assert.Null(result);
45+
}
46+
47+
[Fact]
48+
public void GetFunctionInvokeUrlTemplate_ReturnsExpectedResult()
49+
{
50+
string baseUrl = "https://localhost";
51+
var functionMetadata = new FunctionMetadata
52+
{
53+
Name = "TestFunction"
54+
};
55+
var httpTriggerBinding = new BindingMetadata
56+
{
57+
Name = "req",
58+
Type = "httpTrigger",
59+
Direction = BindingDirection.In,
60+
Raw = new JObject()
61+
};
62+
functionMetadata.Bindings.Add(httpTriggerBinding);
63+
var uri = FunctionMetadataExtensions.GetFunctionInvokeUrlTemplate(baseUrl, functionMetadata, "api");
64+
Assert.Equal("https://localhost/api/testfunction", uri.ToString());
65+
66+
// with empty route prefix
67+
uri = FunctionMetadataExtensions.GetFunctionInvokeUrlTemplate(baseUrl, functionMetadata, string.Empty);
68+
Assert.Equal("https://localhost/testfunction", uri.ToString());
69+
70+
// with a custom route
71+
httpTriggerBinding.Raw.Add("route", "catalog/products/{category:alpha?}/{id:int?}");
72+
uri = FunctionMetadataExtensions.GetFunctionInvokeUrlTemplate(baseUrl, functionMetadata, "api");
73+
Assert.Equal("https://localhost/api/catalog/products/{category:alpha?}/{id:int?}", uri.ToString());
74+
75+
// with empty route prefix
76+
uri = FunctionMetadataExtensions.GetFunctionInvokeUrlTemplate(baseUrl, functionMetadata, string.Empty);
77+
Assert.Equal("https://localhost/catalog/products/{category:alpha?}/{id:int?}", uri.ToString());
78+
}
79+
}
80+
}

test/WebJobs.Script.Tests/Managment/WebFunctionsManagerTests.cs

Lines changed: 0 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -11,18 +11,15 @@
1111
using System.Threading;
1212
using System.Threading.Tasks;
1313
using Microsoft.Azure.WebJobs.Host.Executors;
14-
using Microsoft.Azure.WebJobs.Script.Description;
1514
using Microsoft.Azure.WebJobs.Script.Management.Models;
1615
using Microsoft.Azure.WebJobs.Script.WebHost;
17-
using Microsoft.Azure.WebJobs.Script.WebHost.Extensions;
1816
using Microsoft.Azure.WebJobs.Script.WebHost.Management;
1917
using Microsoft.Azure.WebJobs.Script.Workers.Rpc;
2018
using Microsoft.Extensions.Configuration;
2119
using Microsoft.Extensions.Logging;
2220
using Microsoft.Extensions.Logging.Abstractions;
2321
using Microsoft.Extensions.Options;
2422
using Moq;
25-
using Newtonsoft.Json.Linq;
2623
using Xunit;
2724

2825
namespace Microsoft.Azure.WebJobs.Script.Tests.Managment
@@ -142,39 +139,6 @@ public async Task GetRoutePrefix_Succeeds(string content, string expected)
142139
Assert.Equal(expected, prefix);
143140
}
144141

145-
[Fact]
146-
public void GetFunctionInvokeUrlTemplate_ReturnsExpectedResult()
147-
{
148-
string baseUrl = "https://localhost";
149-
var functionMetadata = new FunctionMetadata
150-
{
151-
Name = "TestFunction"
152-
};
153-
var httpTriggerBinding = new BindingMetadata
154-
{
155-
Name = "req",
156-
Type = "httpTrigger",
157-
Direction = BindingDirection.In,
158-
Raw = new JObject()
159-
};
160-
functionMetadata.Bindings.Add(httpTriggerBinding);
161-
var uri = FunctionMetadataExtensions.GetFunctionInvokeUrlTemplate(baseUrl, functionMetadata, "api");
162-
Assert.Equal("https://localhost/api/testfunction", uri.ToString());
163-
164-
// with empty route prefix
165-
uri = FunctionMetadataExtensions.GetFunctionInvokeUrlTemplate(baseUrl, functionMetadata, string.Empty);
166-
Assert.Equal("https://localhost/testfunction", uri.ToString());
167-
168-
// with a custom route
169-
httpTriggerBinding.Raw.Add("route", "catalog/products/{category:alpha?}/{id:int?}");
170-
uri = FunctionMetadataExtensions.GetFunctionInvokeUrlTemplate(baseUrl, functionMetadata, "api");
171-
Assert.Equal("https://localhost/api/catalog/products/{category:alpha?}/{id:int?}", uri.ToString());
172-
173-
// with empty route prefix
174-
uri = FunctionMetadataExtensions.GetFunctionInvokeUrlTemplate(baseUrl, functionMetadata, string.Empty);
175-
Assert.Equal("https://localhost/catalog/products/{category:alpha?}/{id:int?}", uri.ToString());
176-
}
177-
178142
[Theory]
179143
[InlineData(null, null, "https://localhost")]
180144
[InlineData(null, "testhost", "https://testhost.azurewebsites.net")]

0 commit comments

Comments
 (0)