[英]Use custom HttpMessageHandler with different configurations
I have a custom HttpMessageHandler
implementation:我有一个自定义的
HttpMessageHandler
实现:
public class MyHandler : DelegatingHandler
{
private readonly HttpClient _httpClient;
private readonly MyHandlerOptions _config;
public MyHandler(
HttpClient httpClient,
IOptions<MyHandlerOptions> options)
{
_httpClient = httpClient;
_config = options.Value;
}
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
request.Headers.Authorization = await GetAccessToken()
return await base.SendAsync(request, cancellationToken);
}
private async Task<string> GetAccessToken()
{
//some logic to get access token using _httpClient and _config
}
}
It requires confiuration object MyHandlerOptions
.它需要配置 object
MyHandlerOptions
。 Its form is not so important here.它的形式在这里并不重要。 It basically contains clientId, clientSecret, etc. that are needed for the handler to know how to get the access token.
它基本上包含处理程序知道如何获取访问令牌所需的 clientId、clientSecret 等。
I have a few services (typed http clients) that need to use MyHandler
:我有一些需要使用
MyHandler
的服务(键入 http 客户端):
//registration of MyHandler itself
builder.Services.AddHttpClient<MyHandler>();
//configuration of MyHandler
builder.Services.AddOptions<MyHandlerOptions>()
.Configure<IConfiguration>((config, configuration) =>
{
configuration.GetSection("MyHandlerOptions").Bind(config);
});
//Services that need to use MyHandler:
services.AddHttpClient<Service1>()
.AddHttpMessageHandler<MyHandler>();
services.AddHttpClient<Service2>()
.AddHttpMessageHandler<MyHandler>();
services.AddHttpClient<Service3>()
.AddHttpMessageHandler<MyHandler>();
The problem is that the MyHandlerOptions
instance that I registered is valid only when used with Service1
.问题是我注册的
MyHandlerOptions
实例仅在与Service1
一起使用时才有效。 However, Service2
and Service3
require other configuration (different clientId, clientSecret, etc.).但是,
Service2
和Service3
需要其他配置(不同的 clientId、clientSecret 等)。 How can I achieve it?我怎样才能实现它?
The possible solution that comes to my mind:我想到的可能的解决方案:
public class AccessTokenGetter
{
Task<string> GetAccessToken(AccessTokenConfig config)
{
//get the access token...
}
}
HttpMessageHandler
s for each case where configuration is different:HttpMessageHandler
:public class MyHandler1 : DelegatingHandler
{
private readonly MyHandler1Options _config;
private readonly AccessTokenGetter _accessTokenGetter;
public MyHandler(AccessTokenGetter accessTokenGetter, IOptions<MyHandlerOptions1> options)
{
_accessTokenGetter = accessTokenGetter;
_config = options.Value;
}
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
//somehow convert _config to AccessTokenConfig
request.Headers.Authorization = await _accessTokenGetter.GetAccessToken(_config)
return await base.SendAsync(request, cancellationToken);
}
}
public class MyHandler2 : DelegatingHandler
{
//same implementation as MyHandler1, just use MyHandler2Options instead
}
//configurations
builder.Services.AddOptions<MyHandler1Options>()
.Configure<IConfiguration>((config, configuration) =>
{
configuration.GetSection("MyHandler1Options").Bind(config);
});
builder.Services.AddOptions<MyHandler2Options>()
.Configure<IConfiguration>((config, configuration) =>
{
configuration.GetSection("MyHandler2Options").Bind(config);
});
//AccessTokenGetter
services.AddHttpClient<AccessTokenGetter>()
//Services that need to use MyHandlers:
services.AddHttpClient<Service1>()
.AddHttpMessageHandler<MyHandler1>();
services.AddHttpClient<Service2>()
.AddHttpMessageHandler<MyHandler2>();
services.AddHttpClient<Service3>()
.AddHttpMessageHandler<MyHandler2>();
Is there a better solution?有更好的解决方案吗? I am not a great fan of my idea, it is not very flexible.
我不是我的想法的忠实拥护者,它不是很灵活。
services.AddHttpClient<Service1>()
.AddHttpMessageHandler(sp =>
{
var handler = sp.GetRequiredService<MyHandler>();
handler.Foo = "Bar";
return handler;
});
services.AddHttpClient<Service2>()
.AddHttpMessageHandler(sp =>
{
var handler = sp.GetRequiredService<MyHandler>();
handler.Foo = "Baz";
return handler;
});
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.