c# - 将 HTTP 消息处理程序添加到所有 HTTP 客户端
问题描述
我有一个名为 的 HTTP 消息处理程序AddHeadersHandler
,它扩展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.
}
}
解决方案
可以通过配置所有命名选项HttpClientFactoryOptions
来完成。我们需要提供一个委托,其中将包括您的处理程序到属性列表。HttpMessageHandlerBuilderActions
AdditionalHandlers
使用选项模式有多种方法可以做到这一点。
1. 使用 .AddSingleton() ❌</h1>
如果您的处理程序有任何依赖项(例如IHttpContextAccessor
,获取当前相关 id),我们希望使用依赖项注入来解决它。
我们可以使用OptionsBuilder API通过依赖注入来获取所需的处理程序。不幸的是,OptionsBuilder API 并没有像这样提供为所有命名实例配置选项的方法.ConfigureAll
。
幸运的是,我们可以通过注册一个工厂方法来获得我们需要的东西IConfigureOptions<HttpClientFactoryOptions>
:
// 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的启发。
添加.ConfigureAll
您的Startup.cs
并IServiceProvider
通过构建器对象使用,如下所示:
services.ConfigureAll<HttpClientFactoryOptions>(options =>
{
options.HttpMessageHandlerBuilderActions.Add(builder =>
{
builder.AdditionalHandlers.Add(builder.Services.GetRequiredService<AddHeadersHandler>());
});
});
推荐阅读
- xpath - 使用 wso2 esb 更改原始有效负载
- logstash - docker 中的 logstash 错误“无法执行操作”
- arrays - MIPS 32 - 可以计算阶乘的子程序(使用 sll 和 add)
- javascript - 使用 React.createElement 时,对象不是有效的反应子级吗?
- string - 如何仅在 Ocaml 中的第一个空格上拆分字符串
- javascript - 从 3 个对象数组创建对象数组
- java - 如何获取数组列表中索引的大小?
- node.js - 如何在 React Native 中从数据库中删除帖子?
- ios - 如何防止 Apple 表单根据屏幕尺寸拒绝我的应用程序?
- css - 有没有更优雅的方式来为按钮创建高光?