使用Flurl设置默认的Polly策略

Iai*_*own 2 flurl polly

我目前正在一起使用Polly和Flurl,但是我有一个通用的重试策略,必须添加到每个请求中。我注意到Polly允许您使用AddPolicyHandler(...)设置默认值,但这需要IHttpClientBuilder,而且我看不到任何从Flurl掌握此方法的方法。

我以为可以重载DefaultHttpClientFactory,但这只能使我可以访问HttpClient,而不能访问IHttpClientBuilder。

我知道我可以制作自己的HttpClients并将它们传递给Flurl,但我宁愿避免这种情况,因为我希望Flurl管理它们的生命周期。

目前有什么方法可以做我想做的事吗?

Tod*_*ier 7

好问题。Flurl为您提供了所有必要的钩子。首先定义一个DelegatingHandler采用Polly策略的:

public class PollyHandler : DelegatingHandler
{
    private readonly IAsyncPolicy<HttpResponseMessage> _policy;

    public PollyHandler(IAsyncPolicy<HttpResponseMessage> policy) {
        _policy = policy;
    }

    protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) {
        return _policy.ExecuteAsync(ct => base.SendAsync(request, ct), cancellationToken);
    }
}
Run Code Online (Sandbox Code Playgroud)

然后创建一个自定义IHttpClientFactory,以默认处理程序作为返回的自定义处理程序InnerHandler

public class PollyFactory : DefaultHttpClientFactory
{
    private readonly IAsyncPolicy<HttpResponseMessage> _policy;

    public PollyFactory(IAsyncPolicy<HttpResponseMessage> policy) {
        _policy = policy;
    }

    public override HttpMessageHandler CreateMessageHandler() {
        return new PollyHandler(_policy) {
            InnerHandler = base.CreateMessageHandler()
        };
    }
}
Run Code Online (Sandbox Code Playgroud)

最后,在应用启动时,定义您的策略并向Flurl注册:

var policy = Policy
    .Handle<HttpRequestException>()
    .OrResult<HttpResponseMessage>(r => !r.IsSuccessStatusCode)
    .RetryAsync(5);

FlurlHttp.Configure(settings => settings.HttpClientFactory = new PollyFactory(policy));
Run Code Online (Sandbox Code Playgroud)

一个重要的注意事项是,该方法不适用于处理FlurlHttpException的策略。那是因为您要在HttpMessageHandler此处拦截呼叫。Flurl将响应和错误转换为FlurlHttpException更高的堆栈,因此使用这种方法不会陷入或重试这些响应和错误。上例中的策略会陷阱HttpRequestExceptionHttpResponseMessage(使用非2XX状态代码),该策略将起作用。