120 lines
3.0 KiB
Go
120 lines
3.0 KiB
Go
package request
|
|
|
|
import (
|
|
"crypto/tls"
|
|
"encoding/json"
|
|
"net/http"
|
|
"time"
|
|
|
|
"ckwk/pkg/log"
|
|
|
|
"go.uber.org/zap/zapcore"
|
|
"resty.dev/v3"
|
|
)
|
|
|
|
var (
|
|
NoRedirectClient *resty.Client
|
|
RestyClient *resty.Client
|
|
)
|
|
|
|
const (
|
|
DefaultUserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/140.0.0.0 Safari/537.36 Edg/140.0.0.0"
|
|
DefaultTimeout = 10 * time.Second
|
|
DefaultDebugBody = 4 * 1024
|
|
)
|
|
|
|
type Config struct {
|
|
Timeout time.Duration
|
|
Proxy string
|
|
Debug bool
|
|
UserAgent string
|
|
VerifySSL bool
|
|
}
|
|
|
|
func DefaultConfg() *Config {
|
|
return &Config{
|
|
Timeout: DefaultTimeout,
|
|
UserAgent: DefaultUserAgent,
|
|
VerifySSL: true,
|
|
Debug: false,
|
|
}
|
|
}
|
|
|
|
// NewClient 创建一个标准的 Resty 客户端
|
|
func NewClient(cfg *Config) *resty.Client {
|
|
defaults := DefaultConfg()
|
|
if cfg == nil {
|
|
cfg = defaults
|
|
} else {
|
|
// 合并零值,避免调用方只覆盖部分字段时丢失默认超时和 User-Agent。
|
|
if cfg.Timeout <= 0 {
|
|
cfg.Timeout = defaults.Timeout
|
|
}
|
|
if cfg.UserAgent == "" {
|
|
cfg.UserAgent = defaults.UserAgent
|
|
}
|
|
}
|
|
|
|
client := resty.New()
|
|
client.SetHeader("User-Agent", cfg.UserAgent)
|
|
client.SetTimeout(cfg.Timeout)
|
|
client.SetRetryCount(3)
|
|
|
|
client.SetTLSClientConfig(&tls.Config{
|
|
InsecureSkipVerify: !cfg.VerifySSL,
|
|
})
|
|
|
|
if cfg.Proxy != "" {
|
|
client.SetProxy(cfg.Proxy)
|
|
}
|
|
if cfg.Debug {
|
|
client.SetDebug(true)
|
|
client.SetDebugBodyLimit(DefaultDebugBody)
|
|
client.OnDebugLog(func(debugLog *resty.DebugLog) {
|
|
fields := map[string]any{
|
|
"request": map[string]any{
|
|
"host": debugLog.Request.Host,
|
|
"uri": debugLog.Request.URI,
|
|
"method": debugLog.Request.Method,
|
|
"proto": debugLog.Request.Proto,
|
|
"header": log.SanitizeHeaders(debugLog.Request.Header),
|
|
"attempt": debugLog.Request.Attempt,
|
|
"body": log.SanitizeBody(debugLog.Request.Header.Get("Content-Type"), debugLog.Request.Body),
|
|
},
|
|
"response": map[string]any{
|
|
"statusCode": debugLog.Response.StatusCode,
|
|
"status": debugLog.Response.Status,
|
|
"proto": debugLog.Response.Proto,
|
|
"receivedAt": debugLog.Response.ReceivedAt.Format(time.RFC3339Nano),
|
|
"durationMs": debugLog.Response.Duration.Milliseconds(),
|
|
"size": debugLog.Response.Size,
|
|
"header": log.SanitizeHeaders(debugLog.Response.Header),
|
|
"body": log.SanitizeBody(debugLog.Response.Header.Get("Content-Type"), debugLog.Response.Body),
|
|
},
|
|
}
|
|
if debugLog.TraceInfo != nil {
|
|
if traceJSON, err := json.Marshal(debugLog.TraceInfo); err == nil {
|
|
fields["trace"] = json.RawMessage(traceJSON)
|
|
}
|
|
}
|
|
log.Capture(zapcore.DebugLevel, "resty", "outbound exchange", fields)
|
|
})
|
|
client.SetDebugLogFormatter(nil)
|
|
}
|
|
|
|
return client
|
|
}
|
|
|
|
// NewNoRedirectClient 创建一个禁止重定向的客户端
|
|
func NewNoRedirectClient(cfg *Config) *resty.Client {
|
|
client := NewClient(cfg)
|
|
|
|
client.SetRedirectPolicy(
|
|
resty.RedirectPolicyFunc(func(req *http.Request, via []*http.Request) error {
|
|
return http.ErrUseLastResponse
|
|
}),
|
|
)
|
|
|
|
return client
|
|
}
|