.NET Core中自定义HttpMessageHandler注入服务注册后Header不生效
自定义HttpMessageHandler添加请求头失效问题排查与解决
问题场景
我编写了服务注册类InternalSymbolServiceRegister用于注册ISymbolService,尝试通过注入自定义HttpMessageHandler为请求添加自定义头,但调用API时请求头为空。
服务注册类代码
public static class InternalSymbolServiceRegister { public const string DefaultConfigSectionName = "myService"; public static IServiceCollection AddSymbols( this IServiceCollection services, IConfiguration configuration, HttpMessageHandler customHttpMessageHandler = null, string configSectionName = DefaultConfigSectionName) { services.Configure<SymbolOptions>(configuration.GetSection(configSectionName)); services.AddHttpClient<ISymbolService, InternalSymbolService>((sp, client) => { var options = sp.GetRequiredService<IOptions<SymbolOptions>>().Value; client.BaseAddress = new Uri(options.ServiceUrl); client.Timeout = TimeSpan.FromMilliseconds(options.TimeoutMs); }).AddPolicyHandler(GetCircuitBreakerPolicy()); if (customHttpMessageHandler != null) { services.Configure<HttpClientFactoryOptions>(nameof(ISymbolService), options => { options.HttpMessageHandlerBuilderActions.Add(builder => { builder.PrimaryHandler = customHttpMessageHandler; }); }); } return services; } private static IAsyncPolicy<HttpResponseMessage> GetCircuitBreakerPolicy() => HttpPolicyExtensions .HandleTransientHttpError() .CircuitBreakerAsync(handledEventsAllowedBeforeBreaking: 5, durationOfBreak: TimeSpan.FromSeconds(7)); }
自定义Header处理器代码
public sealed class InternalSymbolHeaderHandler : DelegatingHandler { protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) { request.Headers.Add("admin_header", "_11111"); return await base.SendAsync(request, cancellationToken); } }
Startup注册代码
services.AddSymbols(Configuration, customHttpMessageHandler: new InternalSymbolHeaderHandler());
问题原因
DelegatingHandler使用错误:DelegatingHandler是作为请求处理链中的一环设计的,必须通过InnerHandler指向链的下一个处理器。直接将其设为PrimaryHandler时,InnerHandler未初始化,调用base.SendAsync无法继续传递请求,导致请求头添加逻辑失效。- Handler配置逻辑缺陷:通过
Configure<HttpClientFactoryOptions>替换PrimaryHandler会覆盖默认的HttpClientHandler,但由于DelegatingHandler缺少后续处理节点,整个请求流程被中断。此外,直接传入new InternalSymbolHeaderHandler()会造成实例单例复用,存在线程安全隐患。
解决方案
方案1:将DelegatingHandler作为附加处理器添加(推荐)
保留默认PrimaryHandler,将自定义处理器加入请求链,由HttpClientFactory自动管理处理器间的关联:
修改AddSymbols方法的自定义Handler配置逻辑:
public static IServiceCollection AddSymbols( this IServiceCollection services, IConfiguration configuration, Func<IServiceProvider, DelegatingHandler> customDelegatingHandlerFactory = null, string configSectionName = DefaultConfigSectionName) { services.Configure<SymbolOptions>(configuration.GetSection(configSectionName)); var httpClientBuilder = services.AddHttpClient<ISymbolService, InternalSymbolService>((sp, client) => { var options = sp.GetRequiredService<IOptions<SymbolOptions>>().Value; client.BaseAddress = new Uri(options.ServiceUrl); client.Timeout = TimeSpan.FromMilliseconds(options.TimeoutMs); }).AddPolicyHandler(GetCircuitBreakerPolicy()); // 将自定义DelegatingHandler添加到处理链 if (customDelegatingHandlerFactory != null) { httpClientBuilder.AddHttpMessageHandler(customDelegatingHandlerFactory); } return services; }
Startup注册时传入工厂委托,让容器管理Handler生命周期:
services.AddSymbols(Configuration, customDelegatingHandlerFactory: sp => new InternalSymbolHeaderHandler());
方案2:自定义PrimaryHandler,改用HttpClientHandler
如果必须替换默认PrimaryHandler,则自定义Handler需继承HttpClientHandler而非DelegatingHandler:
修改自定义Handler:
public sealed class InternalSymbolHeaderHandler : HttpClientHandler { protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) { request.Headers.Add("admin_header", "_11111"); return await base.SendAsync(request, cancellationToken); } }
同时优化AddSymbols的配置逻辑,推荐通过容器注入Handler:
// 先注册Handler到容器 services.AddSingleton<HttpMessageHandler, InternalSymbolHeaderHandler>(); // 再注册服务 services.AddSymbols(Configuration, customHttpMessageHandler: sp => sp.GetRequiredService<HttpMessageHandler>());
验证
修改后重新运行程序,调用API时即可看到自定义请求头admin_header被正确添加到请求中。
内容的提问来源于stack exchange,提问作者Ehsan Akbar
相关产品推荐
相关产品推荐

