配置HttpClientFactory以使用当前请求上下文中的数据

Tom*_*han 10 asp.net-core-2.1 httpclientfactory

使用ASP.NET Core 2.1中的新HttpClientFactory,可以很容易地使用基本URL,默认标题等配置自定义HTTP客户端.

但是,我还没有找到一种方法来集中配置,让我从当前请求上下文中注入头文件.例如,考虑使用Authorization标头调用的服务,我希望将其传递给所有底层服务.能够在类中的.AddHttpClient()调用中配置它会很棒,但我无法弄清楚如何从那里获取请求上下文.servicesStartup

有任何想法吗?

Rua*_*urg 15

通过这个答案,我得到了多个答案.我认为第一种方法是你正在寻找的,第二种方法是一个很好的选择.

要配置多个客户端,您可以使用命名客户端.这些客户端注册为瞬态.使用DI获取有权访问请求上下文的服务.

为此,我们需要IHttpContextAccessor.在这种情况下,您不必自己注册,因为Identity已经为您执行此操作.

否则在启动时添加以下行:

services.AddHttpContextAccessor();
Run Code Online (Sandbox Code Playgroud)

接下来我们可以配置命名客户端"github":

services.AddHttpClient("github", c =>
{
    // access the DI container
    var serviceProvider = services.BuildServiceProvider();
    // Find the HttpContextAccessor service
    var httpContextAccessor = serviceProvider.GetService<IHttpContextAccessor>();
    // Get the bearer token from the request context (header)
    var bearerToken = httpContextAccessor.HttpContext.Request
                          .Headers["Authorization"]
                          .FirstOrDefault(h => h.StartsWith("bearer ", StringComparison.InvariantCultureIgnoreCase));

    // Add authorization if found
    if (bearerToken != null)
        c.DefaultRequestHeaders.Add("Authorization", bearerToken);

     // Other settings
    c.BaseAddress = new Uri("https://api.github.com/");
    c.DefaultRequestHeaders.Add("Accept", "application/vnd.github.v3+json"); // Github API versioning
    c.DefaultRequestHeaders.Add("User-Agent", "HttpClientFactory-Sample"); // Github requires a user-agent
});
Run Code Online (Sandbox Code Playgroud)

像这样调用客户端:

public class MyController : ControllerBase
{
    private readonly IHttpClientFactory _clientFactory;

    public MyController(IHttpClientFactory clientFactory)
    {
        _clientFactory = clientFactory;
    }

    public async Task<ActionResult> StartCall()
    {
        var client = _clientFactory.CreateClient("github");
        var response = await client.GetAsync("/repos/aspnet/docs/issues");
    }
}
Run Code Online (Sandbox Code Playgroud)

另一种选择是使用Typed客户端.这是一个简短的例子.有关完整示例,请检查链接.

注册IHttpContextAccessor:

services.AddHttpContextAccessor();
Run Code Online (Sandbox Code Playgroud)

创建一个类型化的客户端.我添加了两个选项来添加设置.一个通过请求上下文,一个通过单例类:

public class GitHubService
{
    public HttpClient Client { get; }

    public GitHubService(HttpClient client, HttpClientSettings httpClientSettings, IHttpContextAccessor httpContextAccessor)
    {
        var bearerToken = httpContextAccessor.HttpContext.Request
                              .Headers["Authorization"]
                              .FirstOrDefault(h => h.StartsWith("bearer ", StringComparison.InvariantCultureIgnoreCase));

        // Add authorization if found
        if (bearerToken != null)
            client.DefaultRequestHeaders.Add("Authorization", bearerToken);

        // Or the value from httpClientSettings:
        client.DefaultRequestHeaders.Add("Authorization", httpClientSettings.BearerToken);

        client.BaseAddress = new Uri("https://api.github.com/");
        client.DefaultRequestHeaders.Add("Accept", "application/vnd.github.v3+json"); // GitHub API versioning
        client.DefaultRequestHeaders.Add("User-Agent", "HttpClientFactory-Sample"); // GitHub requires a user-agent

        Client = client;
    }
}
Run Code Online (Sandbox Code Playgroud)

注册客户:

// The typed client is registered as transient with DI.
services.AddHttpClient<GitHubService>();
Run Code Online (Sandbox Code Playgroud)

请注意,下面的代码只是一个例子.由于令牌无法在客户端中持久化,因此您可以使用共享的HttpClientSettings:

services.AddSingleton<HttpClientSettings>();
Run Code Online (Sandbox Code Playgroud)

HttpClientSettings的位置是:

public class HttpClientSettings
{
    public string BearerToken { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

您可以像这样使用客户端:

public class MyController : ControllerBase
{
    private readonly GitHubService _gitHubService;

    public MyController(GitHubService gitHubService)
    {
        _gitHubService = gitHubService;
    }

    public async Task<ActionResult> StartCall()
    {
        var response = await _gitHubService.Client.GetAsync("/repos/aspnet/docs/issues");

    }
}
Run Code Online (Sandbox Code Playgroud)

  • 我想补充一点,`services.BuildServiceProvider()` 在每次调用时都会创建一个新的“服务池”。因此,您在 AddHttpClient 方法中通过此服务提供程序获得的单例服务将与您在应用程序的其余部分中获得的服务不同。在这种情况下,您将获得“正确的”服务提供者作为 AddHttpClient 方法中的参数,如下所示:`services.AddHttpClient("github", (serviceProvider, c) =&gt;`。 (3认同)

was*_*ast 8

从 .NET Core 3.0 开始,您可以使用 HeaderPropagation。

Startup.cs 中的配置服务

services.AddHeaderPropagation(o =>
        {
            o.Headers.Add("Authorization");
        });
services.AddHttpClient<YourTypedHttpClient>().AddHeaderPropagation();
Run Code Online (Sandbox Code Playgroud)

在Startup.cs中配置

app.UseHeaderPropagation();
Run Code Online (Sandbox Code Playgroud)

这将自动传播授权标头。您也可以将其用于其他标头。