使用 ASP.NET Core 2.1 中的新HttpClientFactory,使用基本 url、默认标头等配置自定义 HTTP 客户端非常容易。
但是,我还没有找到一种集中配置的方法,可以让我从当前请求上下文中注入标头。例如,考虑一个使用Authorization
标头调用的服务,我也希望将其传递给所有底层服务。能够在类的.AddHttpClient()
调用中配置它会很棒,但我不知道如何从那里获取请求上下文。services
Startup
有任何想法吗?
使用 ASP.NET Core 2.1 中的新HttpClientFactory,使用基本 url、默认标头等配置自定义 HTTP 客户端非常容易。
但是,我还没有找到一种集中配置的方法,可以让我从当前请求上下文中注入标头。例如,考虑一个使用Authorization
标头调用的服务,我也希望将其传递给所有底层服务。能够在类的.AddHttpClient()
调用中配置它会很棒,但我不知道如何从那里获取请求上下文。services
Startup
有任何想法吗?
处理这个答案让我得到了多个答案。我认为第一种方法是您正在寻找的方法,第二种方法是一个不错的选择。
为了配置多个客户端,您可以使用命名客户端。这些客户端被注册为瞬态。使用 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");
}
}
从 .NET Core 3.0 开始,您可以使用 HeaderPropagation。
Startup.cs 中的配置服务
services.AddHeaderPropagation(o =>
{
o.Headers.Add("Authorization");
});
services.AddHttpClient<YourTypedHttpClient>().AddHeaderPropagation();
在 Startup.cs 中配置
app.UseHeaderPropagation();
这将自动传播 Authorization 标头。您也可以将其用于其他标题。