Attach HttpRequestMessage to Polly Context in PolicyHttpMessageHandler for access by policy callbacks
- Dominant language
- C#
- Stars
- 38.4k
- Forks
- 10.9k
- Avg merge
- 2d 6h
- Merged PRs (30d)
- 290
Description
### Is there an existing issue for this?
- [X] I have searched the existing issues
### Is your feature request related to a problem? Please describe the problem.
This is related to https://github.com/App-vNext/Polly/issues/2244
It's a common scenario to get access to the `HttpRequestMessage` object in Polly policy callbacks, most often for logging/monitoring purposes but there are likely other valid scenarios as well.
For stateless policies such as retry, this can be done like the following:
IAsyncPolicy GetPollyPolicy(HttpRequestMessage request)
{
var retryPolicy = Policy
.Handle()
// can access request here via closure
.RetryAsync((result, count) => logger.LogInformation($"Request: {request}"));
return retryPolicy;
}
var handler = new PolicyHttpMessageHandler(GetPollyPolicy) { InnerHandler = new HttpClientHandler() };
var httpClient = new HttpClient(handler);
But this does not work with a stateful policy such as circuit breaker or bulkhead:
IAsyncPolicy GetPollyPolicy(HttpRequestMessage request)
{
var retryPolicy = Policy
.Handle()
// this doesn't work as intended because circuit breaker is stateful so one policy instance should be used across requests
.CircuitBreakerAsync(5, TimeSpan.FromSeconds(30),
(result, time) => logger.LogInformation($"Request: {request}"),
() => {});
return retryPolicy;
}
var handler = new PolicyHttpMessageHandler(GetPollyPolicy) { InnerHandler = new HttpClientHandler() };
var httpClient = new HttpClient(handler);
because by definition, a stateful policy needs to track state across requests so creating a new instance for every request will not work as intended.
For such cases, there's currently no good way to access `HttpRequestMessage` from policy callbacks except to write our own `DelegatingHandler` and flow state manually (i.e. attach `HttpRequestMessage` to `Polly.Context` in the custom `DelegatingHandler`, and then retrieving it from `Polly.Context` in the callbacks). But this seems like a sufficiently routine case that writing a custom handler to flow state should not be necessary.
### Describe the solution you'd like
A possible enhancement is as follows:
1. `PolicyHttpMessageHandler` can attach `HttpRequestMessage` to `Polly.Context`, which can then flow with Polly to the policy callbacks. At the end of the request processing, it can be cleaned up from context to avoid leaking memory or underlying resources (since `HttpRequestMessage` is `IDisposable`).
2. Provide some helper methods to get `HttpRequestMessage` from `Polly.Context`.
### Additional context
_No response_
Contributor guide
Assessment
This issue has not been assessed yet.