I have implemented custom middleware with Durable Azure functions. You can also refer my SO answer.
Steps followed:
Create a Custom Middleware class:
internal sealed class StampHttpHeaderMiddleware : IFunctionsWorkerMiddleware
{
public async Task Invoke(FunctionContext context, FunctionExecutionDelegate next)
{
var logger = context.GetLogger("StampHttpHeaderMiddleware");
var request = await context.GetHttpRequestDataAsync();
if (request != null && request.Headers != null &&
request.Headers.TryGetValues("x-correlationId", out var values))
{
var correlationId = values.FirstOrDefault();
logger.LogInformation("Correlation ID received: {correlationId}", correlationId);
}
else
{
logger.LogDebug("Skipping correlationId check - not an HTTP-triggered function.");
}
await next(context);
}
}
Register custom middleware with worker in Program.cs:
var builder = FunctionsApplication.CreateBuilder(args);
builder.ConfigureFunctionsWebApplication();
builder.UseMiddleware<StampHttpHeaderMiddleware>();
builder.Build().Run();
Function.cs:
[Function(nameof(Function1))]
public static async Task<List<string>> RunOrchestrator(
[OrchestrationTrigger] TaskOrchestrationContext context)
{
ILogger logger = context.CreateReplaySafeLogger(nameof(Function1));
logger.LogInformation("Saying hello.");
var outputs = new List<string>();
outputs.Add(await context.CallActivityAsync<string>(nameof(SayHello), "Tokyo"));
outputs.Add(await context.CallActivityAsync<string>(nameof(SayHello), "Seattle"));
outputs.Add(await context.CallActivityAsync<string>(nameof(SayHello), "London"));
return outputs;
}
[Function(nameof(SayHello))]
public static string SayHello([ActivityTrigger] string name, FunctionContext executionContext)
{
ILogger logger = executionContext.GetLogger("SayHello");
logger.LogInformation("Saying hello to {name}.", name);
return $"Hello {name}!";
}
[Function("Function1_HttpStart")]
public static async Task<HttpResponseData> HttpStart(
[HttpTrigger(AuthorizationLevel.Function, "get", "post")] HttpRequestData req,
[DurableClient] DurableTaskClient client,
FunctionContext executionContext)
{
var logger = executionContext.GetLogger("Function1_HttpStart");
string instanceId = await client.ScheduleNewOrchestrationInstanceAsync(
nameof(Function1));
logger.LogInformation("Started orchestration with ID = '{instanceId}'.", instanceId);
return await client.CreateCheckStatusResponseAsync(req, instanceId);
}
Output:


Functions:
Function1_HttpStart: [GET,POST] http://localhost:7076/api/Function1_HttpStart
Function1: orchestrationTrigger
SayHello: activityTrigger
For detailed output, run func with --verbose flag.
[2025-04-25T10:17:26.985Z] Executing 'Functions.Function1_HttpStart' (Reason='This function was programmatically called via the host APIs.', Id=13fb0eb3-6a05-4dc0-b934-a8a72ad63c15)
[2025-04-25T10:17:27.595Z] Correlation ID received: 12345
[2025-04-25T10:17:27.684Z] Scheduling new Function1 orchestration with instance ID 'd6b1fc255d4a498c9db759018cf6e683' and 0 bytes of input data.
[2025-04-25T10:17:27.930Z] Started orchestration with ID = 'd6b1fc255d4a498c9db759018cf6e683'.
[2025-04-25T10:17:28.036Z] Executed 'Functions.Function1_HttpStart' (Succeeded, Id=13fb0eb3-6a05-4dc0-b934-a8a72ad63c15, Duration=1084ms)
[2025-04-25T10:17:28.127Z] Executing 'Functions.Function1' (Reason='(null)', Id=44a41f0a-fbd2-44a0-8ad1-21469fe8e2a4)
[2025-04-25T10:17:28.134Z] Host lock lease acquired by instance ID '000000000000000000000000F72731CC'.
[2025-04-25T10:17:28.302Z] Saying hello.
[2025-04-25T10:17:28.359Z] Executed 'Functions.Function1' (Succeeded, Id=44a41f0a-fbd2-44a0-8ad1-21469fe8e2a4, Duration=292ms)
[2025-04-25T10:17:28.447Z] Executing 'Functions.SayHello' (Reason='(null)', Id=5f2917c7-9c75-4c5f-9318-08de480aa1f0)
[2025-04-25T10:17:28.463Z] Saying hello to Tokyo.
[2025-04-25T10:17:28.466Z] Executed 'Functions.SayHello' (Succeeded, Id=5f2917c7-9c75-4c5f-9318-08de480aa1f0, Duration=23ms)
[2025-04-25T10:17:28.543Z] Executing 'Functions.Function1' (Reason='(null)', Id=5363b179-36e1-4445-8141-e68412baea3e)
[2025-04-25T10:17:28.562Z] Executed 'Functions.Function1' (Succeeded, Id=5363b179-36e1-4445-8141-e68412baea3e, Duration=21ms)
[2025-04-25T10:17:28.614Z] Executing 'Functions.SayHello' (Reason='(null)', Id=b23fb88c-5229-483a-99f2-3014dfec33c2)
[2025-04-25T10:17:28.623Z] Saying hello to Seattle.
[2025-04-25T10:17:28.626Z] Executed 'Functions.SayHello' (Succeeded, Id=b23fb88c-5229-483a-99f2-3014dfec33c2, Duration=11ms)
[2025-04-25T10:17:28.666Z] Executing 'Functions.Function1' (Reason='(null)', Id=a34e9c1f-59fc-46da-964e-7264d0abde5f)
[2025-04-25T10:17:28.673Z] Executed 'Functions.Function1' (Succeeded, Id=a34e9c1f-59fc-46da-964e-7264d0abde5f, Duration=8ms)
[2025-04-25T10:17:28.717Z] Executing 'Functions.SayHello' (Reason='(null)', Id=3d7b7445-9881-4f33-b91e-8006ed704353)
[2025-04-25T10:17:28.725Z] Saying hello to London.
[2025-04-25T10:17:28.727Z] Executed 'Functions.SayHello' (Succeeded, Id=3d7b7445-9881-4f33-b91e-8006ed704353, Duration=10ms)
[2025-04-25T10:17:28.769Z] Executing 'Functions.Function1' (Reason='(null)', Id=2cc76746-dd08-4326-86b9-c41cc0c68210)
[2025-04-25T10:17:28.786Z] Executed 'Functions.Function1' (Succeeded, Id=2cc76746-dd08-4326-86b9-c41cc0c68210, Duration=17ms)
builder.UseMiddleware<CustomMiddleware>();