georgepwall1991/HttpClient.Resilience.Analyzers
GitHub: georgepwall1991/HttpClient.Resilience.Analyzers
一款基于 Roslyn 的 .NET HttpClient 出站 HTTP 弹性与生命周期分析器,在编译时检测 socket 耗尽、不安全重试、响应未释放等生产环境故障模式。
Stars: 0 | Forks: 0
# HttpClient.Resilience.Analyzers
[](https://github.com/georgepwall1991/HttpClient.Resilience.Analyzers/actions/workflows/ci.yml)
[](https://www.nuget.org/packages/HttpClient.Resilience.Analyzers)
[](LICENSE)
面向生产环境的 Roslyn 分析器,用于分析 .NET `HttpClient`、`IHttpClientFactory`、typed clients、Polly 和 `Microsoft.Extensions.Http.Resilience`。
`HttpClient.Resilience.Analyzers` 能够在编译时捕获出站 HTTP 错误:socket 耗尽风险、过期的 DNS 客户端、typed-client 生命周期泄漏、不安全的重试、响应释放错误、sync-over-async 调用、缺失 cancellation token、无限制的扇出以及脆弱的 named-client 字符串。
## 安装
```
dotnet add package HttpClient.Resilience.Analyzers
```
如需显式包引用:
```
```
该包仅包含分析器。它不会为您的应用程序增加任何运行时依赖。
## 为什么开发此工具
.NET 为团队提供了多种有效的出站 HTTP 使用方式:factory clients、typed clients、named clients、长期存活的手动创建的 clients、resilience handlers、流式响应以及自定义 handlers。高昂的故障成本通常来自于难以在代码审查中发现的小的生命周期或所有权错误。
此分析器直接针对这些故障模式:
- `HttpClient` 生命周期错误,可能导致 socket 耗尽、DNS 过期或连接抖动。
- `IHttpClientFactory` 和 typed-client DI 模式意外地将短生命周期的 clients 提升为 singleton 状态。
- resilience handler 配置中重试了不安全的 HTTP 方法(例如 `POST`、`PUT`、`PATCH`、`DELETE` 或 `CONNECT`)。
- 围绕 `ResponseHeadersRead`、`HttpContent` 和流式 API 的响应与流所有权错误。
- 请求正确性问题,例如缺失 cancellation token、共享 `DefaultRequestHeaders` 以及 sync-over-async 调用。
- 运维风险模式,例如无限制的出站扇出以及针对每个请求构建 resilience pipeline。
## 快速示例
```
services.AddHttpClient
()
.AddStandardResilienceHandler();
public sealed class PaymentsClient(HttpClient httpClient)
{
public Task CreateAsync(CancellationToken cancellationToken)
{
return httpClient.PostAsync("/payments", null, cancellationToken);
}
}
```
`HCR041` 会报告此问题,因为标准的 resilience handler 可能会重试不安全的 HTTP 方法。除非 endpoint 被明确指定为可安全重试,否则重试非幂等的 `POST` 可能会导致重复写入。
```
services.AddHttpClient()
.AddStandardResilienceHandler(options =>
{
options.Retry.DisableForUnsafeHttpMethods();
});
```
## 规则目录
默认配置文件将生产安全规则作为警告保持可见,并将基于启发式的扇出规则作为建议。每条规则都有一个专门的文档页面,包含错误代码示例、改进后的代码示例、当前检测详情、抑制指南和参考资料。
| 规则 | 类别 | 捕获内容 | 默认配置文件 | 修复支持 |
|---|---|---|---:|---|
| [`HCR001`](docs/rules/HCR001.md) | 生命周期 | 在请求路径中创建并释放 `HttpClient` | 警告 | 部分 |
| [`HCR002`](docs/rules/HCR002.md) | 生命周期 | 没有 `PooledConnectionLifetime` 的长期存活的手动 `HttpClient` | 警告 | 是 |
| [`HCR003`](docs/rules/HCR003.md) | 生命周期 | 缓存的 `IHttpClientFactory.CreateClient()` 结果 | 警告 | 指南 |
| [`HCR004`](docs/rules/HCR004.md) | typed clients | 注入到 singleton 服务中的 typed clients | 警告 | 指南 |
| [`HCR005`](docs/rules/HCR005.md) | typed clients | 重复的 typed-client 注册 | 警告 | 是 |
| [`HCR020`](docs/rules/HCR020.md) | handlers | 捕获了 scoped 请求数据的 `DelegatingHandler` | 警告 | 指南 |
| [`HCR040`](docs/rules/HCR040.md) | resilience | client pipeline 中重复的 resilience handlers | 警告 | 是 |
| [`HCR041`](docs/rules/HCR041.md) | resilience | 在没有显式配置的情况下重试不安全的 HTTP 方法 | 警告 | 是 |
| [`HCR060`](docs/rules/HCR060.md) | 响应生命周期 | 未释放的 `ResponseHeadersRead` 响应 | 警告 | 是 |
| [`HCR061`](docs/rules/HCR061.md) | 响应生命周期 | 在检查成功状态之前读取响应内容 | 警告 | 部分 |
| [`HCR062`](docs/rules/HCR062.md) | 响应生命周期 | 将针对单个请求的 header 写入 `DefaultRequestHeaders` | 警告 | 指南 |
| [`HCR063`](docs/rules/HCR063.md) | 响应生命周期 | 出站 HTTP 周围的 sync-over-async 调用 | 警告 | 部分 |
| [`HCR064`](docs/rules/HCR064.md) | 响应生命周期 | 省略了可用 `CancellationToken` 的 HTTP 调用 | 警告 | 是 |
| [`HCR080`](docs/rules/HCR080.md) | 并发 | 明显无限制的 `Task.WhenAll` HTTP 扇出 | 建议 | 指南 |
| [`HCR081`](docs/rules/HCR081.md) | 响应生命周期 | 从 HTTP 内容返回且未释放的流 | 警告 | 部分 |
| [`HCR082`](docs/rules/HCR082.md) | resilience | 针对每个请求构建 resilience pipeline | 警告 | 指南 |
| [`HCR083`](docs/rules/HCR083.md) | typed clients | 在没有 `BaseAddress` 的情况下使用相对 URL 的 typed clients | 警告 | 指南 |
| [`HCR084`](docs/rules/HCR084.md) | typed clients | 用于 named `HttpClient` 名称的重复字符串字面量 | 警告 | 指南 |
请查看完整的[规则索引](docs/rules/README.md)以了解推广优先级、类别和链接。
## 采用配置文件
使用内置的 `.editorconfig` 配置文件,使分析器适应您的团队和代码库:
| 配置文件 | 用途 |
|---|---|
| [`profiles/default.editorconfig`](profiles/default.editorconfig) | 准备好处理生产安全警告的新服务或团队。 |
| [`profiles/brownfield-adoption.editorconfig`](profiles/brownfield-adoption.editorconfig) | 需要低噪音首轮筛查的现有应用程序。 |
| [`profiles/strict-ci.editorconfig`](profiles/strict-ci.editorconfig) | 希望 CI 在出现生产安全警告时直接失败的代码库。 |
| [`profiles/library-author.editorconfig`](profiles/library-author.editorconfig) | 需要对响应和流所有权进行更严格控制的库。 |
推荐的推广步骤:
1. 添加该包。
2. 如果代码库中已经包含大量出站 HTTP 代码,请从 brownfield 配置文件开始。
3. 首先修复或有意抑制高置信度的发现。
4. 一旦新的警告能够被有效处理,即可切换到 default 配置文件。
5. 仅在当前基线完全干净后,再提升至 strict CI 配置文件。
更多细节:[采用指南](docs/adoption.md)、[配置指南](docs/configuration.md)和[误报策略](docs/false-positive-policy.md)。
## 文档
- [文档中心](docs/README.md)
- [规则索引](docs/rules/README.md)
- [实现状态](docs/implementation-status.md)
- [配置](docs/configuration.md)
- [采用](docs/adoption.md)
- [误报策略](docs/false-positive-policy.md)
- [发布](docs/releasing.md)
- [贡献](CONTRIBUTING.md)
- [支持](SUPPORT.md)
- [安全性](SECURITY.md)
## 项目状态
这是一个预览版包。已实现的分析器集涵盖了 MVP 诊断以及通过 `HCR084` 进行的首次未来规则扩展。
质量标准有意保持保守:规则应报告具体的出站 HTTP 风险,避免嘈杂的猜测,并在项目存在特例情况时提供安全的应急出口文档。标签:HttpClient, Roslyn, SOC Prime, 代码分析器, 多人体追踪, 开发工具