24

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

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

有任何想法吗?

4

2 回答 2

35

处理这个答案让我得到了多个答案。我认为第一种方法是您正在寻找的方法,第二种方法是一个不错的选择。

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

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

否则在 startup 中添加以下行:

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

另一种选择是使用Typed clients。这是一个简短的例子。有关完整示例,请查看链接

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

    }
}
于 2018-07-21T21:12:19.973 回答
5

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

Startup.cs 中的配置服务

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

在 Startup.cs 中配置

app.UseHeaderPropagation();

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

于 2021-07-21T16:34:27.303 回答