配置 HttpClientFactory 以使用来自当前请求上下文的数据 [英] Configure HttpClientFactory to use data from the current request context

查看:24
本文介绍了配置 HttpClientFactory 以使用来自当前请求上下文的数据的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

With the new HttpClientFactory in ASP.NET Core 2.1, it's quite easy to configure custom HTTP clients with things like base urls, default headers etc.

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

However, I haven't found a way to centralize configuration that lets me inject headers from the current request context. For example, consider a service called with an Authorization header, which I wish to pass on to all the underlying services as well. It would be awesome to be able to configure this in the .AddHttpClient() call on services in the Startup class, but I can't figure out how to get at the request context from there.

有什么想法吗?

推荐答案

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

Working on this answer lead me to multiple answers. I think the first approach is what you are looking for, the second is a good alternative.

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

In order to configure multiple clients you can use named clients. These clients are registered as transient. Use DI to get the service that has access to the request context.

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

For that we need IHttpContextAccessor. In this case you don't have to register it yourself, because Identity already does that for you.

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

services.AddHttpContextAccessor();

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

Next we can configure the named client "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");
    }
}

<小时>

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


Another option is to use Typed clients. Here's a short example. For a full example check the link.

注册 IHttpContextAccessor:

Register IHttpContextAccessor:

services.AddHttpContextAccessor();

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

Create a typed client. I've added two options to add settings. One through the request context and one through a singleton class:

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 代替:

Please note, the code below is just an example. Since the token can't be persisted in the client, you can use the shared HttpClientSettings instead:

services.AddSingleton<HttpClientSettings>();

HttpClientSettings 在哪里:

Where HttpClientSettings is:

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

您可以这样使用客户端:

You can use the client like this:

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

    }
}

这篇关于配置 HttpClientFactory 以使用来自当前请求上下文的数据的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆