Production-focused Roslyn analyzers for .NET HttpClient, IHttpClientFactory, typed clients, Polly, and Microsoft.Extensions.Http.Resilience.
HttpClient.Resilience.Analyzers catches outbound HTTP bugs at compile time: socket exhaustion risks, stale DNS clients, typed-client lifetime leaks, unsafe retries, response disposal mistakes, sync-over-async calls, missing cancellation tokens, unbounded fan-out, and fragile named-client strings.
dotnet add package HttpClient.Resilience.AnalyzersFor explicit package references:
<PackageReference Include="HttpClient.Resilience.Analyzers" Version="0.1.0-preview.2" PrivateAssets="all" />The package is analyzer-only. It adds no runtime dependency to your application.
.NET gives teams several valid ways to use outbound HTTP: factory clients, typed clients, named clients, long-lived manual clients, resilience handlers, streaming responses, and custom handlers. The expensive failures usually come from small lifetime or ownership mistakes that are hard to spot in review.
This analyzer targets those failure modes directly:
HttpClientlifetime mistakes that can cause socket exhaustion, DNS staleness, or connection churn.IHttpClientFactoryand typed-client DI patterns that accidentally promote short-lived clients into singleton state.- Resilience handler configuration that retries unsafe HTTP methods such as
POST,PUT,PATCH,DELETE, orCONNECT. - Response and stream ownership mistakes around
ResponseHeadersRead,HttpContent, and streaming APIs. - Request correctness issues such as missing cancellation tokens, shared
DefaultRequestHeaders, and sync-over-async calls. - Operational risk patterns such as unbounded outbound fan-out and per-request resilience pipeline construction.
services.AddHttpClient<PaymentsClient>()
.AddStandardResilienceHandler();
public sealed class PaymentsClient(HttpClient httpClient)
{
public Task<HttpResponseMessage> CreateAsync(CancellationToken cancellationToken)
{
return httpClient.PostAsync("/payments", null, cancellationToken);
}
}HCR041 reports this because the standard resilience handler may retry unsafe HTTP methods. Retrying a non-idempotent POST can duplicate writes unless the endpoint is explicitly safe to retry.
services.AddHttpClient<PaymentsClient>()
.AddStandardResilienceHandler(options =>
{
options.Retry.DisableForUnsafeHttpMethods();
});The default profile keeps production-safety rules visible as warnings and leaves the heuristic fan-out rule as a suggestion. Every rule has a dedicated documentation page with bad code, better code, current detection details, suppression guidance, and references.
| Rule | Category | Catches | Default profile | Fix support |
|---|---|---|---|---|
HCR001 |
Lifetime | Creating and disposing HttpClient in request paths |
Warning | Partial |
HCR002 |
Lifetime | Long-lived manual HttpClient without PooledConnectionLifetime |
Warning | Yes |
HCR003 |
Lifetime | Cached IHttpClientFactory.CreateClient() results |
Warning | Guide |
HCR004 |
Typed clients | Typed clients injected into singleton services | Warning | Guide |
HCR005 |
Typed clients | Duplicate typed-client registrations | Warning | Yes |
HCR020 |
Handlers | DelegatingHandler capturing scoped request data |
Warning | Guide |
HCR040 |
Resilience | Duplicate resilience handlers in a client pipeline | Warning | Yes |
HCR041 |
Resilience | Unsafe HTTP methods retried without explicit configuration | Warning | Yes |
HCR060 |
Response lifetime | Undisposed ResponseHeadersRead responses |
Warning | Yes |
HCR061 |
Response lifetime | Reading response content before checking success | Warning | Guide |
HCR062 |
Response lifetime | Per-request headers written to DefaultRequestHeaders |
Warning | Guide |
HCR063 |
Response lifetime | Sync-over-async around outbound HTTP | Warning | Guide |
HCR064 |
Response lifetime | HTTP calls that omit an available CancellationToken |
Warning | Guide |
HCR080 |
Concurrency | Obvious unbounded Task.WhenAll HTTP fan-out |
Suggestion | Guide |
HCR081 |
Response lifetime | Undisposed streams returned from HTTP content | Warning | Guide |
HCR082 |
Resilience | Per-request resilience pipeline construction | Warning | Guide |
HCR083 |
Typed clients | Typed clients using relative URLs without BaseAddress |
Warning | Guide |
HCR084 |
Typed clients | Duplicated string literals for named HttpClient names |
Warning | Guide |
See the full rules index for rollout priority, categories, and links.
Use the included .editorconfig profiles to match the analyzer to your team and codebase:
| Profile | Use it for |
|---|---|
profiles/default.editorconfig |
New services or teams ready to act on production-safety warnings. |
profiles/brownfield-adoption.editorconfig |
Existing applications that need a low-noise first pass. |
profiles/strict-ci.editorconfig |
Repositories that want CI to fail on production-safety warnings. |
profiles/library-author.editorconfig |
Libraries where response and stream ownership should be stricter. |
Recommended rollout:
- Add the package.
- Start with the brownfield profile if the repository already has significant outbound HTTP code.
- Fix or intentionally suppress high-confidence findings first.
- Move to the default profile once new warnings are actionable.
- Promote to strict CI only after the current baseline is clean.
More detail: adoption guide, configuration guide, and false-positive policy.
- Documentation hub
- Rules index
- Implementation status
- Configuration
- Adoption
- False-positive policy
- Releasing
- Contributing
- Support
- Security
This is a preview package. The implemented analyzer set covers the MVP diagnostics and the first future-rule expansion through HCR084.
The quality bar is intentionally conservative: rules should report concrete outbound HTTP risks, avoid noisy guesses, and document the safe escape hatches when a project has a deliberate exception.
