使用工厂方法创建类型化 HTTP 客户端,ASP.NET Core 2.1

Using factory method to create typed HTTP client, ASP.NET Core 2.1

我正在关注 guides/docs 在我的应用程序中注册 HTTP 客户端。我需要调用几个服务,所以我决定使用 "Typed clients".

为了调用另一个服务,我需要使用 OAuth - 因为这是 service-to-service 调用,所以当我获得访问令牌时,我缓存它 + 我设置了令牌的定期刷新。这意味着还有另一个组件 IAccessTokenCache 为我提供服务访问令牌。

我正在努力弄清楚的是如何注册和配置我的类型化 HTTP 客户端,前提是它还依赖于 IAccessTokenCache

我正在使用 ASP.NET Core 2.1(关键细节,请继续阅读)。

HTTP 客户端包装器看起来像这样(来自:HttpClientFactory in ASP.NET Core 2.1 (Part 2) ):

public class ServiceFooClient
{
    public ServiceFooClient(HttpClient client)
    {
        Client = client;
    }

    public HttpClient Client { get; }
}

这就是我注册和配置客户端的方式:

services
    .AddHttpClient<ServiceFooClient>(
        c =>
        {
            c.BaseAddress = new Uri("https://www.foo.svc");

            // TODO: grab particular access token from cache
            c.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", "...");
        })
    .AddHttpMessageHandler<ResponseMonitorHandler>()
    .ConfigureHttpMessageHandlerBuilder(
        b =>
        {
            var handler =
                b.AdditionalHandlers.OfType<ResponseMonitorHandler>().FirstOrDefault();

            if (handler != null)
            {
                handler.ServiceName = "Foo Service";
            }
        });

...我已经在配置 HTTP 客户端,甚至添加了我的自定义 HTTP 处理程序。您可以看到我想要访问的确切位置 IAccessTokenCache,但我不能。

我能想到的可能的解决方案:

ServiceFooClient 包装器中配置基础 HttpClient,例如:

// ctor
public ServiceFooClient(HttpClient httpClient, IAccessTokenCache tokenCache)
{
    Client = httpClient;
    Client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", tokenCache.GetToken("Foo"));
}

这可以很好地工作,除了我不配置解耦 - 突然专用 HTTP 客户端在 Startup 中有部分配置(基本 URI,附加 HTTP 处理程序)和包装中的另一部分 class (设置权限header).

不使用 AddHttpClient 扩展方法(和其他方法)

我真的不需要打电话给 HttpClientFactoryServiceCollectionExtensions.AddHttpClient<T>(...) - 我可以自己做所有这些事情。但是作为一个懒惰的开发者……我什至不想把这句话说完。里面有很多注册,所以这对我来说是个大问题。

升级到 ASP.NET Core 2.2

与上一点相关 - 在 2.1 中,没有 AddHttpClient (2.2: AddHttpClient<TClient>(this IServiceCollection services, Action<IServiceProvider, HttpClient> configureClient)) 的重载可以接受服务提供商的回调。升级到 2.2 可能是最好的解决方案,但我必须非常确定没有其他东西被破坏(而且我已经知道 is/was BC break with getting/setting request tracing ID on HTTP context) .这可能有潜在风险,所以我首先尝试在 2.1 范围内解决我的问题。

比较 2.1 和 2.2 的分支:HttpClientFactoryServiceCollectionExtensions

自定义 HTTP 处理程序设置请求 headers

与我现在注册 ResponseMonitorHandler 的方式相同,我可以注册可以访问 IAccessTokenCache 的 HTTP 处理程序并设置请求授权 header。

但是,与第一种情况一样,这又分离了 HTTP 客户端的配置。此外,如果我有多个不同的访问令牌,我将需要实现多个 HTTP 处理程序或执行一些逻辑,根据请求属性决定使用缓存中的哪个令牌。

最后一个问题:还有没有其他我没有考虑的方法?在 ASP.NET 2.1 中有简单的解决方案吗? (...当然,除了来自 2.2 的 copy-pasting 方法)

显然,2.1 ConfigureHttpClient(IHttpClientBuilder, Action<IServiceProvider,HttpClient>) 中还有另一种扩展方法,它正是我需要的!