我想调用第三方API,该API为我们提供了两个不同的授权令牌值。因此,通过调用相同的端点URL,我们可以得到两组不同的结果。
EndpointUrl: https://mail.yahoo.com/
Authorization: Token User123
//Do something with the response for User123
Authorization: Token User345
//Do something with the response for User345
在我的客户服务中,包装函数应通过使用不同的令牌值两次调用此API来调用此API。获取结果并将其合并。
这是我的服务。
public class MailService : IMailService
{
private readonly HttpClient _httpClient;
public MailService(HttpClient httpClient)
{
_httpClient = httpClient;
}
public async Task<UserResponse> GetUserResponse()
{
var uri = new Uri(_httpClient.BaseAddress.AbsoluteUri + "/user-data/");
var response = await _httpClient.GetAsync(uri);
return response;
}
}
我正在使用Typed Client:
services.AddHttpClient<IMailService,MailService>(client =>
{
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Token", "User123");
client.BaseAddress = new Uri("https://mail.yahoo.com/");
})
问题陈述:
检索结果的最佳方法是什么?我不确定是否应该创建HttpClient
的两个单独实例?如果要使用两个包含自己的HttpClient
的不同类,则要避免重复代码。
也许我的解决方案位于Named Client中。我只是不知道如何优雅地实现它。
任何帮助将不胜感激。
答案 0 :(得分:0)
我要回答,这或多或少是基于意见的。我希望将DI服务与项目中的其他所有服务分离。基本上,您是在startup.cs
中将配置放入另一个服务。我喜欢将所有这些东西都保留在使用HttpClient
的服务中。
因此,当我注入IHttpClientFactory
时,我可以通过简单地调用:
services.AddHttpClient();
继续前进。
现在,在您的MailService
中,您应这样注入它:
public class MailService : IMailService
{
// or store this in your applications external configuration
const Uri BaseUri = new Uri("https://mail.yahoo.com/");
const string UserDataPath = "/user-data/";
private readonly IHttpClientFactory _httpClientFactory;
public MailService(IHttpClientFactory httpClientFactory)
{
_httpClientFactory = httpClientFactory;
}
public async Task<UserResponse> GetUserResponse(string token)
{
var client = _httpClientFactory.CreateClient();
var uri = new UriBuilder(BaseUri){ Path = UserDataPath }.Uri;
using (var msg = new HttpRequestMessage(HttpMethod.Get, uri))
{
msg.Headers.Authorization = new AuthenticationHeaderValue("Token", token);
using (var resp = await _client.SendAsync(msg).ConfigureAwait(false))
{
resp.EnsureSuccessStatusCode();
return await resp.Content.ReadAsAsync<UserResponse>().ConfigureAwait(false);
}
}
}
}
请记住,您应该使用HttpRequestMessage
模式,而不要修改Default...
的任何HttpClient
属性。那时,它可能正在应用程序中的其他地方使用。
使用HttpRequestMessage
可确保您获得一组新的标头,其他人都无法修改。总结一下:HttpClient.Headers
are not thread-safe。
ETA:
现在我考虑一下...这确实是您的问题。您想使用一个HttpClient
使用两个不同的标题。在您介绍的场景中将无法使用。您将必须拥有两个HttpClient
,它们具有各自不同的标题。
因此,如果您不想采用我介绍的老式方法,则应考虑“命名”客户端...每个配置都有不同的名称。
答案 1 :(得分:0)
检索结果的最佳方法是什么?
命名客户端是一种解决方案,如果确定您将始终具有两个身份验证标头。不过,这对我来说似乎很奇怪。
SendAsync
是另一种解决方案。通过调用SendAsync
而不是GetAsync
,可以提供可以包含自定义标头的HttpRequestMessage
。为了方便起见,GetAsync
实际上是SendAsync
的包装,并且您可以使用较低级别的SendAsync
,因为需要更多的自定义功能。