使用工厂方法创建类型化 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>)
中还有另一种扩展方法,它正是我需要的!
我正在关注 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>)
中还有另一种扩展方法,它正是我需要的!