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

查看:322
本文介绍了配置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.

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

Otherwise add the following line in startup:

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天全站免登陆