tmenier / flurl-site

Flurl Web Site
https://flurl.dev
3 stars 13 forks source link

How to configure Delegating handler in Flurl clientless configuration #31

Closed bjose7 closed 4 months ago

bjose7 commented 4 months ago

Flurl website document shows it has a configuration which allows to pass in Delegating Handlers. https://flurl.dev/docs/configuration/ It would be at the end of the above link.

All code is configured in the Program class. This is azure function app, running on isolated worker model.

While the clientless pattern in static clients format works, the DI pattern doesnt.

FlurlHttp.Clients.WithDefaults(builder => builder
    .AddMiddleware(new MyDelegatingHandler()));

Above config works.

But this pattern below doesnt.

// DI pattern: 
services.AddSingleton<IFlurlClientCache>(sp => new FlurlClientCache()
    .WithDefaults(builder => builder
        .AddMiddleware(sp.GetService<IMyDelegatingHandler>())

I need the DI format, because my CustomDelegationHandler has other classes injected into it and it would have been easier if the DI version worked.

Since I dont have an interface, I used the below format. Wasnt sure about Interfaces for DelegatingHandlers.

Sample DelegationHandler being used:

public class MyDelegationHandler : DelegatingHandler
{
    private static string CorrelationId => "correlation-id";

    private readonly ICorrelationIdQuery _correlationIdQuery;

    public MyDelegationHandler(ICorrelationIdQuery correlationIdQuery)
    {
        _correlationIdQuery = correlationIdQuery ;
    }

    protected async override Task<HttpResponseMessage> SendAsync(
        HttpRequestMessage request, CancellationToken cancellationToken)
    {
        string correlationId = await _correlationIdQuery.Execute();

        if (!request.Headers.Contains(CorrelationId))
        {
            request.Headers.Add(CorrelationId, correlationId);
        }

        return await base.SendAsync(request, cancellationToken);
    }
}

So my code becomes:

ServiceProvider serviceProvider = services.BuildServiceProvider();
FlurlHttp.Clients.WithDefaults(builder => builder
        .AddMiddleware(() => new MyDelegationHandler(serviceProvider.GetService<ICorrelationIdQuery>())));

Above works, but not sure calling service provider like that is good idea in the Program class. This is the hostbuilder.ConfigureServices section and calling BuildServiceProvider in the middle is not good.

What can i be doing wrong in the below DI version of the code.

services.AddSingleton(sp => new FlurlClientCache()
    .WithDefaults(builder => builder
        .AddMiddleware(() => sp.GetService<MyDelegationHandler>())
    ));

https://stackoverflow.com/questions/78653878/how-to-configure-delegating-handler-in-flurl-clientless-configuration Created a stackoverflow version if anyone else had the same question. Thanks

bjose7 commented 4 months ago

wrong place