【问题标题】:Add HTTP message handler to all HTTP clients将 HTTP 消息处理程序添加到所有 HTTP 客户端
【发布时间】:2020-09-28 13:39:58
【问题描述】:

我有一个名为 AddHeadersHandler 的 HTTP 消息处理程序,它扩展了 System.Net.Http.DelegatingHandler,我需要将它添加到所有当前和未来的 HttpClient 实例,包括类型化、命名和非命名客户端。

我知道我可以使用.AddHttpMessageHandler<AddHeadersHandler>() 为特定客户端添加处理程序,但如何将其添加到所有客户端?

// AddHeadersHandler.cs
public class AddHeadersHandler: DelegatingHandler
{
    protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
    {
        request.Headers.TryAddWithoutValidation("X-Correlation-Id", Guid.NewGuid.ToString());

        return base.SendAsync(request, cancellationToken);
    }
}
// Startup.cs
services
    .AddHttpContextAccessor()
    .AddTransient<AddHeadersHandler>();
services
    .AddHttpClient<MyClient>()
    .AddHttpMessageHandler<AddHeadersHandler>(); // I don't want to specify this for each client.
// MyClient.cs
public class MyClient
{
    public HttpClient HttpClient { get; }

    public MyClient(HttpClient httpClient)
    {
        HttpClient = httpClient;
    }

    public async Task GetTest()
    {
        await HttpClient.GetAsync("https://localhost:5001/test"); // This should have headers attached.
    }
}

【问题讨论】:

    标签: c# asp.net-core .net-core dotnet-httpclient


    【解决方案1】:

    可以通过为所有命名选项配置HttpClientFactoryOptions来完成。我们需要在HttpMessageHandlerBuilderActions 中提供一个委托,它会将您的处理程序包含到AdditionalHandlers 属性列表中。

    使用Options 模式有多种方法。

    1。使用 .AddSingleton() ❌

    如果您的处理程序有任何依赖项(例如,IHttpContextAccessor 获取当前关联 ID),我们希望使用依赖项注入来解决它。

    我们可以使用OptionsBuilder API 来使用依赖注入获取所需的处理程序。不幸的是,OptionsBuilder API 没有像.ConfigureAll 那样提供为所有命名的 实例配置选项的方法。

    幸运的是,我们可以通过为IConfigureOptions&lt;HttpClientFactoryOptions&gt; 注册一个工厂方法来获得我们需要的东西,如下所示:

    // Startup.cs
    services.AddSingleton<IConfigureOptions<HttpClientFactoryOptions>>(provider =>
    {
        // When name is null, it will be used for all configurations.
        return new ConfigureNamedOptions<HttpClientFactoryOptions>(name: null, options =>
        {
            options.HttpMessageHandlerBuilderActions.Add(builder =>
            {
                // Here we have access to ServiceProvider to get an instance of the handler.
                builder.AdditionalHandlers.Add(provider.GetRequiredService<AddHeadersHandler>());
            });
        });
    });
    

    2。使用 .ConfigureAll() ✔️

    以下改进答案的灵感来自LostInComputer

    在您的Startup.cs 中添加.ConfigureAll 并通过构建器对象使用IServiceProvider,如下所示:

    services.ConfigureAll<HttpClientFactoryOptions>(options =>
    {
        options.HttpMessageHandlerBuilderActions.Add(builder =>
        {
            builder.AdditionalHandlers.Add(builder.Services.GetRequiredService<AddHeadersHandler>());
        });
    });
    

    【讨论】:

    • 这个配置应该在AddHttpClient方法之前还是之后添加?
    • @LuizBicalho,只要在同一个ServiceCollection 内,顺序就不重要了。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-04-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-02-23
    • 2013-09-24
    • 1970-01-01
    相关资源
    最近更新 更多