使用ASP.NET Core 2.1中的新HttpClientFactory,使用基本URL,默认标头等配置自定义HTTP客户端非常容易。
但是,我还没有找到一种集中配置的方法,该方法可以让我从当前请求上下文中插入标头。例如,考虑一个带有Authorization
头的服务,我也希望将其传递给所有基础服务。能够在.AddHttpClient()
类的services
的{{1}}调用中进行配置,真是太棒了,但我不知道如何从那里获取请求上下文。
有什么想法吗?
答案 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 标头。您也可以将其用于其他标题。