Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix for ISO string modification during function metadata binding parsing #10735

Merged
merged 14 commits into from
Jan 24, 2025
1 change: 1 addition & 0 deletions release_notes.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,4 @@
- [Added net9 prelaunch app.](https://github.com/Azure/azure-functions-dotnet-worker/pull/2898)
- Update the `DefaultHttpProxyService` to better handle client disconnect scenarios (#10688)
- Replaced `InvalidOperationException` with `HttpForwardingException` when there is a ForwarderError
- Fix the accidental modification of ISO strings during function metadata binding parsing. This fixes the listener errors related to the CosmosDB trigger's `StartFromTime` parameter. (#10735)
satvu marked this conversation as resolved.
Show resolved Hide resolved
18 changes: 17 additions & 1 deletion src/WebJobs.Script/Host/WorkerFunctionMetadataProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.IO;
using System.IO.Abstractions;
using System.Linq;
using System.Reactive.Linq;
Expand All @@ -13,6 +14,7 @@
using Microsoft.Azure.WebJobs.Script.Workers.Rpc;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

namespace Microsoft.Azure.WebJobs.Script
Expand All @@ -28,6 +30,7 @@ internal class WorkerFunctionMetadataProvider : IWorkerFunctionMetadataProvider
private readonly IScriptHostManager _scriptHostManager;
private string _workerRuntime;
private ImmutableArray<FunctionMetadata> _functions;
private static JsonSerializerSettings _jsonSerializerSettings = new JsonSerializerSettings { DateParseHandling = DateParseHandling.None };
satvu marked this conversation as resolved.
Show resolved Hide resolved
satvu marked this conversation as resolved.
Show resolved Hide resolved

public WorkerFunctionMetadataProvider(
IOptionsMonitor<ScriptApplicationHostOptions> scriptOptions,
Expand Down Expand Up @@ -244,13 +247,26 @@ internal IEnumerable<FunctionMetadata> ValidateMetadata(IEnumerable<RawFunctionM
return validatedMetadata;
}

private static BindingMetadata GetBindingMetadata(string binding)
satvu marked this conversation as resolved.
Show resolved Hide resolved
{
using (StringReader stringReader = new StringReader(binding))
using (JsonTextReader jsonTextReader = new JsonTextReader(stringReader))
{
JsonSerializer serializer = JsonSerializer.Create(_jsonSerializerSettings);
satvu marked this conversation as resolved.
Show resolved Hide resolved

JObject parsedBinding = serializer.Deserialize<JObject>(jsonTextReader);

return BindingMetadata.Create(parsedBinding);
}
}

internal static FunctionMetadata ValidateBindings(IEnumerable<string> rawBindings, FunctionMetadata function)
{
HashSet<string> bindingNames = new HashSet<string>(StringComparer.OrdinalIgnoreCase);

foreach (string binding in rawBindings)
{
var functionBinding = BindingMetadata.Create(JObject.Parse(binding));
var functionBinding = GetBindingMetadata(binding);
satvu marked this conversation as resolved.
Show resolved Hide resolved

Utility.ValidateBinding(functionBinding);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,8 @@
using System.Linq;
using System.Threading.Tasks;
using Microsoft.Azure.WebJobs.Script.Description;
using Microsoft.Azure.WebJobs.Script.Grpc.Messages;
using Microsoft.Azure.WebJobs.Script.Workers;
using Microsoft.Azure.WebJobs.Script.Workers.Rpc;
using Microsoft.Extensions.Logging;
using Moq;
using NuGet.ContentModel;
using Xunit;

namespace Microsoft.Azure.WebJobs.Script.Tests
Expand Down Expand Up @@ -180,5 +176,19 @@ public async void ValidateFunctionMetadata_Logging()
Assert.Equal("Reading functions metadata (Worker)", traces[1].FormattedMessage);
// The third log is Host is running without any initialized channels, restarting the JobHost. This is not relevant to this test.
}

[Fact]
public void ValidateFunctionMetadata_IsoStringNotAltered()
{
FunctionMetadata functionMetadata = new FunctionMetadata();
List<string> rawBindings = new List<string>();
var isoString = "2025-02-10T22:45:33Z";
rawBindings.Add("{\"type\": \"cosmosDBTrigger\",\"name\": \"cosmosTrigger\",\"direction\": \"in\",\"databaseName\":\"databaseName\"," +
satvu marked this conversation as resolved.
Show resolved Hide resolved
"\"containerName\":\"containerNameFoo\",\"leaseContainerName\":\"leaseContanerFoo\",\"createLeaseContainerIfNotExists\":true," +
"\"connection\":\"CosmosConnection\",\"startFromTime\":\"" + isoString + "\",\"dataType\":\"String\"}");

var function = WorkerFunctionMetadataProvider.ValidateBindings(rawBindings, functionMetadata);
Assert.Equal(isoString, function.Bindings.FirstOrDefault().Raw["startFromTime"].ToString());
}
}
}
Loading