简体   繁体   English

使用具有不同配置的自定义 HttpMessageHandler

[英]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.).但是, Service2Service3需要其他配置(不同的 clientId、clientSecret 等)。 How can I achieve it?我怎样才能实现它?

The possible solution that comes to my mind:我想到的可能的解决方案:

  1. Create a new service:创建一个新服务:
public class AccessTokenGetter 
{
    Task<string> GetAccessToken(AccessTokenConfig config) 
    {
        //get the access token...
    }
}
  1. Create separate 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
}
  1. Register my services:注册我的服务:
//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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM