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

时间:2018-07-16 09:42:39

标签: asp.net-core-2.1 httpclientfactory

使用ASP.NET Core 2.1中的新HttpClientFactory,使用基本URL,默认标头等配置自定义HTTP客户端非常容易。

但是,我还没有找到一种集中配置的方法,该方法可以让我从当前请求上下文中插入标头。例如,考虑一个带有Authorization头的服务,我也希望将其传递给所有基础服务。能够在.AddHttpClient()类的services的{​​{1}}调用中进行配置,真是太棒了,但我不知道如何从那里获取请求上下文。

有什么想法吗?

2 个答案:

答案 0 :(得分:7)

研究此答案使我有多个答案。我认为第一种方法是您要寻找的方法,第二种是很好的选择。

要配置多个客户端,可以使用named clients。这些客户端被注册为临时客户端。使用DI获取可以访问请求上下文的服务。

为此,我们需要IHttpContextAccessor。在这种情况下,您不必自己注册,因为身份已经为您完成了。

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

services.AddHttpContextAccessor();

接下来,我们可以配置命名的客户端“ 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
});

像这样致电客户:

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");
    }
}

另一种选择是使用类型化的客户端。这是一个简短的例子。有关完整示例,请检查link

注册IHttpContextAccessor:

services.AddHttpContextAccessor();

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

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;
    }
}

注册客户端:

// The typed client is registered as transient with DI.
services.AddHttpClient<GitHubService>();

请注意,以下代码仅是示例。由于令牌无法持久保存在客户端中,因此您可以使用共享的HttpClientSettings:

services.AddSingleton<HttpClientSettings>();

HttpClientSettings在哪里:

public class HttpClientSettings
{
    public string BearerToken { get; set; }
}

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

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");

    }
}

答案 1 :(得分:1)

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

Startup.cs 中的配置服务

services.AddHeaderPropagation(o =>
        {
            o.Headers.Add("Authorization");
        });
services.AddHttpClient<YourTypedHttpClient>().AddHeaderPropagation();

在 Startup.cs 中配置

app.UseHeaderPropagation();

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