starnet/types.go
starainrt 732e81316c
fix(starnet): 重构请求执行链路并补齐代理/重试/trace边界
- 分离 Request 的配置态与执行态,修复二次 Do、raw 模式网络配置失效和 body 来源互斥问题
  - 新增 starnet trace 抽象,补齐 DNS/连接/TLS/重试事件,并优化动态 transport 缓存与代理解析路径
  - 收紧非法代理为 fail-fast,多目标目标回退仅限幂等请求,修复 Host/TLS/SNI 等语义边界
  - 补充防御性拷贝、专项回归测试、本地代理/TLS 用例与 README 行为说明
2026-04-19 15:39:51 +08:00

150 lines
4.4 KiB
Go
Raw 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.

package starnet
import (
"context"
"crypto/tls"
"io"
"net"
"net/http"
"time"
)
// HTTP Content-Type 常量
const (
ContentTypeFormURLEncoded = "application/x-www-form-urlencoded"
ContentTypeFormData = "multipart/form-data"
ContentTypeJSON = "application/json"
ContentTypeXML = "application/xml"
ContentTypePlain = "text/plain"
ContentTypeHTML = "text/html"
ContentTypeOctetStream = "application/octet-stream"
)
// 默认配置
const (
DefaultDialTimeout = 5 * time.Second
DefaultTimeout = 10 * time.Second
DefaultUserAgent = "Starnet/1.0.0"
DefaultFetchRespBody = false
)
// RequestFile 表示要上传的文件
type RequestFile struct {
FormName string // 表单字段名
FileName string // 文件名
FilePath string // 文件路径(如果从文件读取)
FileData io.Reader // 文件数据流
FileSize int64 // 文件大小
FileType string // MIME 类型
}
// UploadProgressFunc 文件上传进度回调函数
type UploadProgressFunc func(filename string, uploaded int64, total int64)
// NetworkConfig 网络配置
type NetworkConfig struct {
Proxy string // 代理地址
DialTimeout time.Duration // 连接超时
Timeout time.Duration // 总超时
DialFunc func(ctx context.Context, network, addr string) (net.Conn, error)
}
// TLSConfig TLS 配置
type TLSConfig struct {
Config *tls.Config // TLS 配置
SkipVerify bool // 跳过证书验证
ServerName string // 显式 TLS ServerName/SNI 覆盖
}
// DNSConfig DNS 配置
type DNSConfig struct {
CustomIP []string // 直接指定 IP最高优先级
CustomDNS []string // 自定义 DNS 服务器
LookupFunc func(ctx context.Context, host string) ([]net.IPAddr, error) // 自定义解析函数
}
type bodyMode uint8
const (
bodyModeUnset bodyMode = iota
bodyModeBytes
bodyModeReader
bodyModeForm
bodyModeMultipart
)
// BodyConfig 请求体配置
type BodyConfig struct {
Mode bodyMode // 当前 body 来源模式
Bytes []byte // 原始字节
Reader io.Reader // 数据流
FormData map[string][]string // 表单数据
Files []RequestFile // 文件列表
}
// RequestConfig 请求配置(内部使用)
type RequestConfig struct {
Network NetworkConfig
TLS TLSConfig
DNS DNSConfig
Body BodyConfig
Headers http.Header
Cookies []*http.Cookie
Queries map[string][]string
// 其他配置
BasicAuth [2]string // Basic 认证
Host string // 显式 Host 头覆盖
ContentLength int64 // 手动设置的 Content-Length
AutoCalcContentLength bool // 自动计算 Content-Length
MaxRespBodyBytes int64 // 响应体最大读取字节数(<=0 表示不限制)
UploadProgress UploadProgressFunc // 上传进度回调
// Transport 配置
CustomTransport bool // 是否使用自定义 Transport
Transport *http.Transport // 自定义 Transport
}
// Clone 克隆配置
func (c *RequestConfig) Clone() *RequestConfig {
return &RequestConfig{
Network: NetworkConfig{
Proxy: c.Network.Proxy,
DialTimeout: c.Network.DialTimeout,
Timeout: c.Network.Timeout,
DialFunc: c.Network.DialFunc,
},
TLS: TLSConfig{
Config: cloneTLSConfig(c.TLS.Config),
SkipVerify: c.TLS.SkipVerify,
ServerName: c.TLS.ServerName,
},
DNS: DNSConfig{
CustomIP: cloneStringSlice(c.DNS.CustomIP),
CustomDNS: cloneStringSlice(c.DNS.CustomDNS),
LookupFunc: c.DNS.LookupFunc,
},
Body: BodyConfig{
Mode: c.Body.Mode,
Bytes: cloneBytes(c.Body.Bytes),
Reader: c.Body.Reader, // Reader 不可克隆
FormData: cloneStringMapSlice(c.Body.FormData),
Files: cloneFiles(c.Body.Files),
},
Headers: cloneHeader(c.Headers),
Cookies: cloneCookies(c.Cookies),
Queries: cloneStringMapSlice(c.Queries),
BasicAuth: c.BasicAuth,
Host: c.Host,
ContentLength: c.ContentLength,
AutoCalcContentLength: c.AutoCalcContentLength,
MaxRespBodyBytes: c.MaxRespBodyBytes,
UploadProgress: c.UploadProgress,
CustomTransport: c.CustomTransport,
Transport: c.Transport, // Transport 共享
}
}
// RequestOpt 请求选项函数
type RequestOpt func(*Request) error