启动后如何创建命名客户端?

How to create named client after startup?

对于我的应用程序,我需要为 HttpRequests 创建一个命名的客户端。我可以在 Startup 中创建一个命名的客户端。为了访问它,我注入了一个“IHttpClientFactory”并从中创建了一个客户端。但是客户端需要有一个访问令牌作为授权 header,而我无法在 Startup 中创建令牌。因此,我需要一种在 Startup class 之外创建命名客户端的方法。我已经尝试将“IServiceCollection”注入控制器。但这不起作用。

或者是否有一种方法可以在启动时创建命名客户端后对其进行编辑?

您可以使用 Polly 向您的客户端添加策略处理程序。如果请求 returns a 401 Unauthorized,则可以添加逻辑。因此,例如获取使用客户端刷新不记名令牌并为当前请求设置它的服务。这只是一个快速的解决方案,也许还有更优雅的解决方案。但如果您的令牌过期,这也会派上用场。因为然后它会自动刷新。

services.AddHttpClient("YourClient")
            .AddPolicyHandler((provider, request) =>
            {
                return Policy.HandleResult<HttpResponseMessage>(r => r.StatusCode == HttpStatusCode.Unauthorized)
                    .RetryAsync(1, async (response, retryCount, context) =>
                    {
                        var service = provider.GetRequiredService<IYourService>();
                        request.Headers.Authorization = new AuthenticationHeaderValue("Bearer",  await service.RefreshToken());
                    });
            });

与@Ruben-J 发布的解决方案类似的解决方案是创建一个自定义 HttpMessageHandler,它为通过 request-time.[=14 处的 HttpClient 发出的请求分配授权 header =]

您可以创建一个自定义的 HttpMessageHandler,它可以在 Startup 中分配给命名的 HttpClient,如下所示:

public class YourHttpMessageHandler : DelegatingHandler
{
    private readonly IYourTokenProviderService _yourTokenProviderService;

    public YourHttpMessageHandler(IYourTokenProviderService yourTokenProviderService) 
        : base()
    {
        _yourTokenProviderService = yourTokenProviderService;
    }

    protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
    {
        var response = SendAsyncWithAuthToken(request, cancellationToken);

        if (response.StatusCode == HttpStatusCode.Unauthorized)
        {
            await _yourTokenProviderService.RefreshTokenAsync();

            response = SendAsyncWithAuthToken(request, cancellationToken);
        }

        return response;
    }

    private async Task<HttpResponseMessage> SendWithAuthTokenAsync(HttpRequestMessage request, CancellationToken cancellationToken)
    {
        request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", _yourTokenProviderService.Token);

        return await base.SendAsync(request, cancellationToken);
    }
}

然后您在启动中配置您的服务并命名为​​ HttpClient:

public virtual void ConfigureServices(IServiceCollection services) 
{
    ...
    services.AddTransient<IYourTokenProviderService, YourTokenProviderService>();
    services.AddTransient<YourHttpMessageHandler>();

    services.AddHttpClient<IYourNamedHttpClient, YourNamedHttpClient>()
        .AddHttpMessageHandler<YourHttpMessageHandler>();
    ...
}

值得注意的是,Polly 的当前实现 AddPolicyHandler 也在添加自己的 DelegatingHandler。 有关更多背景信息,请参阅 Microsoft documentation on adding DelegatingHandler's. Here is also great series of articles from Steve Gordon.