【问题标题】:Share HttpClient between services在服务之间共享 HttpClient
【发布时间】:2020-04-20 11:20:47
【问题描述】:

我正在开发一个 Blazor 项目,为了让我更容易理解这个问题,我们可以说我正在使用两种不同的服务来处理身份验证部分。它们与命名的 httpclient 一起注册在 configureservices 启动方法中。

services.AddHttpClient("XBOWServicesApi", c =>
{
c.BaseAddress = new Uri(XBOWServicesApi);
});

services.AddSingleton<IService1, Service1>();
services.AddSingleton<IService2, Service2>();

服务 1:包装 REST Api 中可用的所有功能。它使用通过实例化的 httpclientfactory 在构造函数中设置的 http 客户端。这需要使用 baseurl 和 Auth-header 设置才能工作。

public Service1(IHttpClientFactory clientFactory)
{
this.httpClient = clientFactory.CreateClient("XBOWServicesApi");
}

服务 2:使用自定义 AuthenticationStateProvider 处理登录/注销功能。它有自己的httpclient,所以我可以为http客户端设置Auth Header。构造函数的工作方式与服务 1 相同。

public Service2(IHttpClientFactory clientFactory)
{
this.httpClient = clientFactory.CreateClient("XBOWServicesApi");
}

这样建立的原因当然是我喜欢共享同一个http客户端,所以在登录/注销方法中设置时,服务1在与api通信时将具有正确的auth header。

但是,客户端工厂每次都提供一个新实例,所以这永远行不通。

任何想法如何处理这个?

/亨里克

【问题讨论】:

    标签: c# asp.net-core service httpclient blazor


    【解决方案1】:

    你可以使用named client:

    services.AddHttpClient("github", c =>
    {
        c.BaseAddress = new Uri("https://api.github.com/");
        // Github API versioning
        c.DefaultRequestHeaders.Add("Accept", "application/vnd.github.v3+json");
        // Github requires a user-agent
        c.DefaultRequestHeaders.Add("User-Agent", "HttpClientFactory-Sample");
    });
    

    之后,只需调用 CreateClient 方法并带有相应的 name 参数。

    var client = _clientFactory.CreateClient("github");
    

    每次调用CreateClient:

    • 创建了一个新的 HttpClient 实例。
    • 配置动作是 调用。

    您可以在 Microsoft 文档here 中找到更多详细信息。

    【讨论】:

      【解决方案2】:

      当我读完Microsoft IHttpClientFactory docs:

      每次从 IHttpClientFactory 获得一个 HttpClient 对象时, 返回新实例。但是每个 HttpClient 使用一个 由 IHttpClientFactory 汇集和重用的 HttpMessageHandler 减少资源消耗,只要 HttpMessageHandler 的 生命周期尚未过期。

      这能回答你的问题吗?

      【讨论】:

      • 但这是否意味着如果我在一个函数中设置了 Authorization 标头,然后在另一个函数中创建了一个新的 httpclient,auth 标头还会在那里吗?
      【解决方案3】:

      您可以使用 HttpMessageHandlers 在瞬态 HttpClient 之间共享作用域服务。

      IHttpClient.CreateClient每次都会返回一个新的实例,但是你可以注册一个HttpMessageHandler,如下图:

      services.AddScoped<HandlerData>();
      services.AddTransient<HeaderHandler>();
      services.AddHttpClient("XBOWServicesApi", c =>
      {
      c.BaseAddress = new Uri(XBOWServicesApi);
      }).AddHttpMessageHandler<HeaderHandler>();
      

      HeaderHandler 类:

      public class HeaderHandler : DelegatingHandler
      {
          private readonly IHttpContextAccessor httpContextAccessor;
          public HeaderHandler(IHttpContextAccessor httpContextAccessor)
          {
              this.httpContextAccessor = httpContextAccessor;
          }
      
          protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken )
          {
              var Data= this.httpContextAccessor.HttpContext.RequestServices.GetRequiredService<HandlerData>();
              request.Headers.Add(Data.HeaderName, Data.HeaderValue);
              return base.SendAsync(request, cancellationToken);
          }
      }
      

      HandlerData 类:

      public class HandlerData
      {
          public string HeaderName { get; set; }
          public string HeaderValue { get; set; }
      }
      

      服务代码:

      public Service1(IHttpClientFactory clientFactory, HandlerData data)
      {
          data.HeaderName = "Header1";
          data.HeaderValue = "Value";
          this.httpClient = clientFactory.CreateClient("XBOWServicesApi");
      }
      public Service2(IHttpClientFactory clientFactory)
      {
          //This will contain the same headers as Service1 as HandlerData is Scoped Service
          this.httpClient = clientFactory.CreateClient("XBOWServicesApi");
      }
      

      或者,如果您需要创建与您请求相同的 DI 范围内的处理程序,您也可以使用新的 IHttpMessageHandlerFactory:

      参考:https://github.com/aspnet/HttpClientFactory/issues/166

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-02-25
        • 2017-05-27
        • 1970-01-01
        • 2016-07-30
        • 2016-11-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多