使用HttpClientFactory配置客户端时触发请求已启动错误的排查
问题原因与解决方案
核心问题
你遇到的错误根源是在AddHttpClient的配置委托中使用了async/await。AddHttpClient的第二个参数预期是同步的Action<HttpClient>,如果传入异步委托(Func<HttpClient, Task>),框架会以"fire-and-forget"的方式执行它——在你await jwtTokenProvider.GetTokenAsync()的间隙,HttpClient实例已经被框架内部初始化甚至返回给调用方,后续再修改DefaultRequestHeaders、BaseAddress等属性时,就会触发实例已启动请求的错误。
解决方案
方案1:用自定义DelegatingHandler注入Token(推荐)
把异步获取Token的逻辑移到请求发送前的拦截器中,避免在客户端初始化阶段执行异步操作:
public class TokenHandler : DelegatingHandler { private readonly IJwtTokenProvider _jwtTokenProvider; private readonly IConfigurationSection _appSettingsSectionIdentity; public TokenHandler(IJwtTokenProvider jwtTokenProvider, IConfigurationSection appSettingsSectionIdentity) { _jwtTokenProvider = jwtTokenProvider; _appSettingsSectionIdentity = appSettingsSectionIdentity; } protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) { var tokenData = await _jwtTokenProvider.GetTokenAsync(_appSettingsSectionIdentity); if (tokenData is null || !tokenData.IsValid) throw new TechnicalErrorException("Can't get a token xxx"); // 替换为实际的Token格式,比如 $"Bearer {tokenData.Token}" request.Headers.TryAddWithoutValidation("Authorization", "xx"); return await base.SendAsync(request, cancellationToken); } }
然后注册Handler和HttpClient:
services.AddTransient<TokenHandler>(); services.AddHttpClient("xxx") .ConfigureHttpClient(client => { client.BaseAddress = new Uri(baseAddress); }) .AddHttpMessageHandler<TokenHandler>() .AddPolicyHandler(PollyPolicys.xxx());
方案2:使用HttpClient时手动配置Token
如果不想自定义Handler,也可以在每次获取客户端后,先异步获取Token再配置请求头:
var httpClient = _httpClientFactory.CreateClient("xxx"); var tokenData = await jwtTokenProvider.GetTokenAsync(appSettingsSectionIdentity); if (tokenData is null || !tokenData.IsValid) throw new TechnicalErrorException("Can't get a token xxx"); httpClient.DefaultRequestHeaders.TryAddWithoutValidation("Authorization", "xx"); // 后续执行请求逻辑
额外说明
- 你之前尝试的
CancelPendingRequests()、移除Polly策略无效,因为根本问题是异步配置委托导致客户端提前初始化。 BaseAddress建议放在同步的ConfigureHttpClient委托中设置,避免在异步逻辑中修改客户端属性。
内容的提问来源于stack exchange,提问作者steb
相关产品推荐
相关产品推荐

