starnet/README.md
starainrt 2f4c7158cf
feat: 增加请求级 trace 摘要与诊断能力
- 新增 TraceRecorder 和 TraceSummary,汇总 DNS、连接、TLS、写请求、首包等关键事件
  - 为请求执行链接入结构化 trace hooks,补充标准路径与动态路径的 TLS 元信息
  - 增加 Request.TraceSummary() 和 Response.TraceSummary(),提供请求级与响应级摘要快照
  - 修复共享 TraceRecorder 在 Client 默认选项、Clone 和请求复用场景下的状态串扰问题
  - 修复 Response.TraceSummary() 回读 Request 最近状态导致的非快照语义
  - 收口自定义 DialFunc 下的 TLS trace 元数据,避免伪造连接地址
  - 补充 trace 相关回归测试,覆盖 HTTPS、DNS/Connect、连接复用、共享 recorder、响应快照和自定义拨号场景
  - 更新 README,补充 trace、Host 与 TLSServerName 的行为说明
2026-04-20 17:54:43 +08:00

123 lines
4.8 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# starnet
`starnet` 是一个面向 Go 的网络工具库,提供 HTTP 请求控制、TLS 嗅探和 ICMP Ping 能力。
## 功能概览
- 基于 `context` 的请求级超时控制,不修改共享 `http.Client` 的全局超时
- 请求级网络控制:代理、自定义 IP / DNS、拨号超时、TLS 配置
- 支持请求级 `Host` 覆盖、显式 `TLSServerName/SNI` 控制,以及结构化 trace 回调 / 摘要
- 内置重试机制,支持重试次数、退避、抖动、状态码白名单和自定义错误判定
- 响应体大小限制,避免一次性读取过大内容
- 错误分类辅助:`ClassifyError``IsTimeout``IsDNS``IsTLS``IsProxy``IsCanceled`
- TLS 嗅探监听 / 拨号工具,适用于 TLS 与明文混合场景
- ICMP Ping支持 IPv4 / IPv6 目标和选项化探测
## 主要能力
### HTTP 客户端与请求构建
- 同时提供 `WithXxx` 选项和 `SetXxx` 链式调用两套接口
- 支持 `Get``Post``Put``Delete``Head``Patch``Options``Trace``Connect`
- 支持 JSON、表单、`multipart/form-data`、流式请求体等常见请求体形态
- 支持显式 `Host` 覆盖与 `TLSServerName` 设置,便于直连 IP、虚拟主机和证书校验场景分离控制
- Header、Cookie、Query 等输入在关键路径上做防御性拷贝,降低外部可变状态污染风险
- `Request.Clone()` 可用于并发场景或同一基础请求的变体构造
### Trace 与诊断
- 支持 `TraceHooks`,可接收 DNS、建连、TLS 握手、写请求、首包等结构化事件
- 支持 `TraceRecorder` / `TraceSummary`,用于汇总一次请求的关键网络过程和 TLS 摘要
- `Request.TraceSummary()` 返回该请求最近一次执行的摘要快照,`Response.TraceSummary()` 返回当前响应对应的摘要快照
- 若多个请求共享同一个 `TraceRecorder`,其 `Summary()` 表示最近一次完成请求的摘要
### 超时与重试
- 请求超时通过 `context` 截止时间控制,不污染共享客户端配置
- 重试支持:
- 最大尝试次数
- 基础退避、最大退避和退避因子
- 抖动比例
- 可重试状态码集合
- 仅幂等方法重试
- 自定义错误判定函数
- 重试成功后返回的 `Response` 仍保持对原始 `Request` 的引用
### 响应处理
- 提供 `Bytes``String``JSON``Reader` 等响应体读取接口
- 支持自动预取响应体
- 支持按字节数限制响应体读取上限
### Ping 模块
- 提供 `Ping``PingWithContext``Pingable` 以及兼容函数 `IsIpPingable`
- `PingOptions` 支持次数、超时、间隔、截止时间、地址族偏好、源地址、负载长度等参数
- 对权限不足、协议不支持、超时、解析失败等情况提供明确错误语义
## 安装
```bash
go get b612.me/starnet
```
## 快速示例
```go
package main
import (
"fmt"
"net/http"
"time"
"b612.me/starnet"
)
func main() {
resp, err := starnet.Get(
"https://example.com",
starnet.WithTimeout(2*time.Second),
starnet.WithRetry(2,
starnet.WithRetryBackoff(100*time.Millisecond, 1*time.Second, 2),
starnet.WithRetryJitter(0.1),
),
starnet.WithMaxRespBodyBytes(1<<20),
)
if err != nil {
fmt.Println("request failed:", starnet.ClassifyError(err), err)
return
}
defer resp.Close()
fmt.Println("status:", resp.StatusCode)
_, _ = resp.Body().Bytes()
ok, pingErr := starnet.Pingable("example.com", &starnet.PingOptions{
Count: 2,
Timeout: 2 * time.Second,
})
fmt.Println("pingable:", ok, pingErr == nil)
_ = http.MethodGet
}
```
## 行为说明
- `NewClient``NewRequest` 以及请求构造相关接口在遇到非法选项时会直接返回错误,例如格式不合法的代理地址。
- `NewClientNoErr` 是便利构造函数;如果选项校验失败,仍可能返回一个占位 `Client`,需要严格校验配置时应优先使用 `NewClient`
- `SetHost` / `WithHost` 只覆盖 HTTP 请求的 `Host`;如需单独控制 TLS SNI 或证书校验名,应配合 `SetTLSServerName` / `WithTLSServerName` 使用。
- 重试默认仅对幂等方法生效。即使显式关闭“仅幂等方法重试”,通过 `SetBodyReader``WithBodyReader` 构造的请求在非幂等方法上仍不会自动重试。
- 当同时使用 `proxy + custom IP/DNS` 且解析出多个目标地址时,自动目标回退仅对幂等请求生效,以避免重复写入。
- 绑定到请求上的 `TraceRecorder` 用于发布已完成请求的摘要;请求执行中的中间状态不保证通过共享 recorder 实时可见。
## 稳定性说明
- 原始 ICMP Ping 在部分系统上需要额外权限。
- 依赖外部网络环境的集成测试结果可能受运行环境影响。
## 许可证
本项目采用 Apache License 2.0,详见 [LICENSE](./LICENSE)。