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

E*Trade适配场景下,如何访问HttpClient的自定义HttpMessageHandlers?

问题描述

我正在为E*Trade连接构建一个HttpClient适配器。该HttpClient需要一个自定义消息处理器(HttpMessageHandler),用于处理OAuth相关的连接参数,例如访问令牌(access token)、消费者密钥(consumer key)、消费者密钥密钥(consumer secret)和令牌密钥(token secret)等。

我的配置代码如下:

// Configure the E*Trade adapter.
serviceCollection
    .AddHttpClient<ETradeAdapter>(httpClient => httpClient.BaseAddress = new Uri(baseAddress, UriKind.Absolute))
    .AddHttpMessageHandler<ETradeMessageHandler>();

在运行时,我会根据用户身份收集OAuth参数,并尝试将其注入到ETradeMessageHandler中。请问使用上述模式时,如何找到与我的HttpClient关联的消息处理器,以便设置这些参数?

补充说明:我可以通过以下方式实现需求,但该方式较为繁琐,我认为一定有更优方案:

var eTradeMessageHandler = this.serviceProvider.GetRequiredService<ETradeMessageHandler>();
eTradeMessageHandler.AccessToken = "some token";
eTradeMessageHandler.TokenSecret = "some secret";
var httpClient = new HttpClient(eTradeMessageHandler);
var eTradeHttpAdapter = new ETradeAdapter(httpClient);
解决方案

方案1:用Scoped服务封装动态OAuth参数(推荐用于用户上下文场景)

  1. 定义存储OAuth参数的类:
public class ETradeOAuthParameters
{
    public string AccessToken { get; set; }
    public string TokenSecret { get; set; }
    public string ConsumerKey { get; set; }
    public string ConsumerSecret { get; set; }
}
  1. 将参数类注册为Scoped服务(每个请求上下文独立实例):
services.AddScoped<ETradeOAuthParameters>();
  1. 修改ETradeMessageHandler,通过构造函数注入参数类:
public class ETradeMessageHandler : DelegatingHandler
{
    private readonly ETradeOAuthParameters _oauthParams;

    public ETradeMessageHandler(ETradeOAuthParameters oauthParams)
    {
        _oauthParams = oauthParams;
    }

    protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
    {
        // 这里直接使用_oauthParams中的动态参数处理OAuth逻辑
        // 例如生成签名、添加Authorization请求头
        return await base.SendAsync(request, cancellationToken);
    }
}
  1. 运行时赋值并使用:
// 示例:在Controller或中间件中
var oauthParams = HttpContext.RequestServices.GetRequiredService<ETradeOAuthParameters>();
oauthParams.AccessToken = "当前用户的access token";
oauthParams.TokenSecret = "当前用户的token secret";

// 直接获取已配置好的ETradeAdapter即可,其关联的Handler会自动使用当前上下文的参数
var adapter = HttpContext.RequestServices.GetRequiredService<ETradeAdapter>();
await adapter.ExecuteTradeOperation();

方案2:通过HttpClient工厂委托配置Handler(适合静态/启动时可确定的参数)

如果OAuth参数在启动阶段就能确定,可在注册时直接配置Handler:

serviceCollection.AddHttpClient<ETradeAdapter>(httpClient => 
{
    httpClient.BaseAddress = new Uri(baseAddress, UriKind.Absolute);
})
.AddHttpMessageHandler(sp => 
{
    var handler = new ETradeMessageHandler();
    // 直接在这里赋值静态参数
    handler.ConsumerKey = "固定的consumer key";
    handler.ConsumerSecret = "固定的consumer secret";
    return handler;
});

方案3:让Adapter持有Handler实例(适合单实例Adapter场景)

  1. 注册Handler为Transient(避免多实例共享导致参数冲突):
services.AddTransient<ETradeMessageHandler>();
  1. 修改ETradeAdapter的构造函数,注入Handler:
public class ETradeAdapter
{
    private readonly HttpClient _httpClient;
    private readonly ETradeMessageHandler _handler;

    public ETradeAdapter(HttpClient httpClient, ETradeMessageHandler handler)
    {
        _httpClient = httpClient;
        _handler = handler;
    }

    public void SetOAuthParameters(string accessToken, string tokenSecret)
    {
        _handler.AccessToken = accessToken;
        _handler.TokenSecret = tokenSecret;
    }

    // 业务方法实现...
}
  1. 使用时直接调用设置方法:
var adapter = serviceProvider.GetRequiredService<ETradeAdapter>();
adapter.SetOAuthParameters("用户token", "用户secret");
await adapter.DoETradeRequest();

内容的提问来源于stack exchange,提问作者user365462

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 21:12:44