如何解决新的 HttpClient 实例和 HttpClientFactory 实例之间的未知差异

问题描述 投票:0回答:1

当前我正在构建一个解决方案,它基本上是多个外部 REST 服务之间的集成。由于解决方案具有多个外部服务,因此我想在需要时使用 .NET ClientFactory 创建 HttpClient。不幸的是,从 ClientFactory 创建的 HttpClient 实例始终会导致未经授权。这有点奇怪,因为直接创建一个新的 HttpClient 就会成功。我红色了有关 HttpClientFactory 的 Microsoft 文档,以确定差异和可能的用例。

我通过提取整个对象来比较两个不同的 HttpClient 实例,并进行融合比较,没有任何差异。另外,通过邮递员,对服务的调用也会成功。

提取并创建 HttpClient 实例(失败)的代码如下所示:

程序.cs

 ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;

 services.AddHttpClient("ClientName", client =>
 {
     client.BaseAddress = new Uri("https://my.domain.com");
     var credentials = Convert.ToBase64String(Encoding.UTF8.GetBytes("username:password"));
     client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", credentials);
     client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
 });

TicketRepository.cs

public class TicketsRepository(
    IHttpClientFactory _httpClientFactory) : ITicketsRepository
{
    private readonly HttpClient _httpClient = _httpClientFactory.CreateClient("ClientName");

    public async Task<Tickets> GetTicketByNumber(
        int ticket,
        CancellationToken cancellationToken)
    {
        HttpResponseMessage response = await _httpClient.GetAsync(
            $"{Constants.TicketsUrlTemplate}/{ticket}",
            cancellationToken);

        if (!response.IsSuccessStatusCode)
        {
            _logger.LogError("Could not successfully retrieve data. Invalid response data is: {response}", response.ToString());

            throw new HttpRequestException($"Server did not respond with an http response status 200: {response}");
        }

        return new Tickets();
    }
}

在每个方法调用上创建 HttpClient 实例并成功提取数据的代码如下所示:

public async Task GetTicketByNumber(
    int ticket,
    CancellationToken cancellationToken)
{
    using (HttpClient client = new HttpClient())
    {

        client.BaseAddress = new Uri("https://my.domain.com");
        var credentials = Convert.ToBase64String(Encoding.UTF8.GetBytes("username:password"));
        client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", credentials);
        client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

        try
        {
            HttpResponseMessage response = await client.GetAsync($"/urlTemplate/{ticket}/", cancellationToken);

            string responseContent = await response.Content.ReadAsStringAsync();
            Console.WriteLine("Response Content: " + responseContent);
        }
        catch (HttpRequestException e)
        {
            Console.WriteLine("Request error: " + e.Message);
        }
    }
}

我与具有相同标头、版本、主机等的响应对象和 HttpClient 对象进行了空白比较...我一定忽略了一些愚蠢的事情,因为 ClientFactory 适用于启动时配置的其他 Rest 服务。很难监视服务器端的东西,因为我没有对该 REST 服务的任何物理访问权限,也无法访问它的源代码。希望有人能指出我正确的方向。

c# .net rest https httpclientfactory
1个回答
0
投票

随着我的调查在周末继续进行(之前出现的问题),我不得不承认我应该进一步研究。当我比较新创建的 HttpClient 和 ClientFactory 中的 HttpResponseMessages 时,我注意到后续调用返回的标头

WwwAuthenticate
为空,而 HttpClientFactory 中的标头具有以下标头值
Basic realm="api"
。因此,我进行了更多搜索并找到了这个解决方案,使用 HttpClientFactory 对每个请求进行身份验证,它向我指出了如何将 HttpClientHandler 与 IHttpClientFactory 一起使用。事实证明,ClientFactory 上的以下附加配置成功执行,因为返回的 WwwAuthenticate 标头必须为空:

ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;

services.AddHttpClient("Server", client =>
{
    client.BaseAddress = new Uri("https://my.domain.com");
    var credentials = Convert.ToBase64String(Encoding.UTF8.GetBytes("username:password"));
    client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", credentials);
    client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
}).ConfigurePrimaryHttpMessageHandler(() =>
{
    return new HttpClientHandler()
    {
        UseDefaultCredentials = true,
        Credentials = new NetworkCredential("", ""),
    };
});

虽然这有效,但我也必须承认,我需要在这样的服务器上调查更多有关基本身份验证的信息,并且请求仍然必须与直接创建的 HttpClient 实例不同,因为我想了解更多信息。 Soo,不幸的是对我来说还不是一个真正正确的答案,但对于 POC 来说这是一个可行的解决方案。对于使用附加

ConfigurePrimaryHttpMessageHandler
(包括默认凭据)的更多技术部门的任何评论,我们表示赞赏。

© www.soinside.com 2019 - 2024. All rights reserved.