You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.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());

问题原因

  1. DelegatingHandler使用错误:DelegatingHandler是作为请求处理链中的一环设计的,必须通过InnerHandler指向链的下一个处理器。直接将其设为PrimaryHandler时,InnerHandler未初始化,调用base.SendAsync无法继续传递请求,导致请求头添加逻辑失效。
  2. 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.10 21:09:55