如何在不调用 Configure() 的情况下全局设置 HttpMessageHandler on Flurl 调用

How to set HttpMessageHandler on Flurl calls globally without calling Configure()

我正在构建一个供内部使用的小型库,它依赖于 Flurl 来处理所有传出 HTTP 调用。

我想为该库的使用者提供选择加入我们的 HTTP 调用跟踪基础结构的能力,如下所示:

Startup.cs:

... 

public void ConfigureServices(IServiceCollection services)
{
    ....
    services.AddTracing(options => ...);
    ....
}

...

我当前的 AddTracing() 实现如下所示:

public static class ServiceCollectionExtensions
{
    public static IServiceCollection AddTracing(this IServiceCollection services, Action<TracingOptions> configureOptions)
    {
        var tracingOptions = new TracingOptions();
        configureOptions(tracingOptions);

        // Make these options available in DI container
        services.AddSingleton(tracingOptions);

        FlurlHttp.Configure(settings =>
        {
            settings.HttpClientFactory = new TracingHttpClientFactory(tracingOptions.ApplicationName);
        });

        return services;
    }
}

TracingHttpClientFactory 的当前实现如下所示:

public class TracingHttpClientFactory : DefaultHttpClientFactory
{
    private readonly string _applicationName;

    public TracingHttpClientFactory(string applicationName)
    {
        _applicationName = applicationName;
    }

    // override to customize how HttpMessageHandler is created/configured
    public override HttpMessageHandler CreateMessageHandler()
    {
        var tracingHandler = new TracingHandler(_applicationName, base.CreateMessageHandler());

        return tracingHandler;
    }
}

这有效,但我面临的问题是 Configure() 的文档显示:只应在应用程序启动时调用一次。

因此,我通过添加跟踪(可选)“浪费”了对 Configure() 的调用。在使用tracing的场景下,我之后还需要调用Configure()

我可能需要在之后调用配置的示例在 Startup.cs:

... 

public void ConfigureServices(IServiceCollection services)
{
    ....
    // Configure() is being called inside AddTracing()
    services.AddTracing(options => ...);
    ....
    // This is a second call to Configure()
    FlurlHttp.Configure(settings => {
        var jsonSettings = new JsonSerializerSettings
        {
            ConstructorHandling = ConstructorHandling.AllowNonPublicDefaultConstructor
        };
        settings.JsonSerializer = new NewtonsoftJsonSerializer(jsonSettings);
    });
}
...

要点 - AddTracing() 的每个消费者都应该能够按照他们认为合适的方式配置 Flurl。 AddTracing() 的要点是用一些额外的可选功能简单地“增强”Flurl。它并不意味着接管 Configure() - 它意味着扩展它。

我一直在阅读文档 here,尽管有很多地方可以进行配置,但我无法找到一种方法来获取我的 TracingHandler(这是一个 HttpMessageHander) 进入每个请求而不调用 Configure() 某处。

我描述的场景是否有合适的实现?

“启动时调用一次”建议的原因是它涉及全局范围。如果您开始在许多不同的地方,可能是在不同的线程上(例如,在控制器操作方法中)弄乱全局设置,您最终可能会遇到奇怪的竞争条件和其他不可预测的行为。

在您的情况下,是的,您调用了 Configure 两次,但调用是连续的、不冲突的,并且在“启动”代码属于 ASP.NET 核心应用程序的地方正确完成.最重要的是,它们在使用 Flurl 进行任何调用之前就已完成。所以你在这里做的很好。