aurora / internal /headerbuilder /builder.go
qwen2api's picture
Upload 113 files
6bc074c verified
Raw
History Blame Contribute Delete
6.46 kB
package headerbuilder
import (
"aurora/httpclient"
"aurora/internal/accounts"
"aurora/internal/browserfp"
"aurora/util"
"strings"
)
// Builder HTTP header 构造器,封装鉴权、cookie、team account 等公共逻辑。
type Builder struct {
header httpclient.AuroraHeaders
}
// New 创建一个新的 header builder。
func New() *Builder {
return &Builder{
header: make(httpclient.AuroraHeaders),
}
}
// Build 返回构造好的 header。
func (b *Builder) Build() httpclient.AuroraHeaders {
return b.header
}
// ── 基础 header ──
// WithBaseHeaders 设置浏览器基础 header(Accept, Origin, sec-ch-ua 等)。
func (b *Builder) WithBaseHeaders(conversationID string) *Builder {
b.header.Set("Accept", "*/*")
b.header.Set("Accept-Language", "en-US,en;q=0.9")
b.header.Set("Oai-Language", "en-US")
b.header.Set("Origin", "https://chatgpt.com")
if conversationID != "" {
b.header.Set("Referer", "https://chatgpt.com/c/"+conversationID)
} else {
b.header.Set("Referer", "https://chatgpt.com/")
}
b.header.Set("Sec-Ch-Ua", `"Chromium";v="148", "Google Chrome";v="148", "Not/A)Brand";v="99"`)
b.header.Set("Sec-Ch-Ua-Mobile", "?0")
b.header.Set("Sec-Ch-Ua-Platform", `"Windows"`)
b.header.Set("Priority", "u=1, i")
b.header.Set("Sec-Fetch-Dest", "empty")
b.header.Set("Sec-Fetch-Mode", "cors")
b.header.Set("Sec-Fetch-Site", "same-origin")
b.header.Set("User-Agent", util.FixedUserAgent)
b.header.Set("Oai-Client-Build-Number", "7823760")
if fp := browserfp.Get(); fp != nil {
b.header.Set("Oai-Client-Version", fp.BuildID)
} else {
b.header.Set("Oai-Client-Version", browserfp.DefaultBuildID)
}
return b
}
// WithUserAgent 设置 User-Agent。
func (b *Builder) WithUserAgent(ua string) *Builder {
if ua != "" {
b.header.Set("User-Agent", ua)
}
return b
}
// WithDeviceID 设置设备 ID。
func (b *Builder) WithDeviceID(deviceID string) *Builder {
if deviceID != "" {
b.header.Set("Oai-Device-Id", deviceID)
}
return b
}
// WithSessionID 设置 session ID。
func (b *Builder) WithSessionID(sessionID string) *Builder {
if sessionID != "" {
b.header.Set("Oai-Session-Id", sessionID)
}
return b
}
// ── 鉴权 header ──
// WithAuth 根据 account 设置鉴权 header(Bearer token 或 Oai-Device-Id)。
func (b *Builder) WithAuth(account *accounts.Account) *Builder {
if account == nil {
return b
}
if account.Type == accounts.TypeNoAuth && account.Token != "" {
b.header.Set("Oai-Device-Id", account.Token)
}
if account.Type != accounts.TypeNoAuth && account.Token != "" {
b.header.Set("Authorization", "Bearer "+account.Token)
}
return b
}
// WithCookies 根据 account 设置 cookie header。
func (b *Builder) WithCookies(account *accounts.Account) *Builder {
if account == nil {
return b
}
cookieStr := ""
if account.PUID != "" {
cookieStr = "_puid=" + account.PUID
}
if account.Type == accounts.TypeNoAuth && account.Token != "" {
if cookieStr != "" {
cookieStr += "; "
}
cookieStr += "oai-did=" + account.Token
}
if cookieStr != "" {
b.header["Cookie"] = cookieStr
}
return b
}
// WithTeamAccount 根据 account 设置 team account header。
func (b *Builder) WithTeamAccount(account *accounts.Account) *Builder {
if account != nil && strings.TrimSpace(account.TeamUserID) != "" {
b.header.Set("Chatgpt-Account-Id", strings.TrimSpace(account.TeamUserID))
}
return b
}
// ── Content-Type / Accept ──
// WithContentType 设置 Content-Type。
func (b *Builder) WithContentType(ct string) *Builder {
b.header.Set("Content-Type", ct)
return b
}
// WithAccept 设置 Accept。
func (b *Builder) WithAccept(accept string) *Builder {
b.header.Set("Accept", accept)
return b
}
// ── Target Path ──
// WithTargetPath 设置 X-Openai-Target-Path 和 X-Openai-Target-Route。
func (b *Builder) WithTargetPath(path string) *Builder {
b.header.Set("X-Openai-Target-Path", path)
b.header.Set("X-Openai-Target-Route", path)
return b
}
// ── Sentinel Token ──
// WithSentinelTokens 设置 sentinel 相关的 token header。
type SentinelTokens struct {
TurnStileToken string
ChatRequirementsPrepareToken string
ProofOfWorkToken string
TurnstileToken string
SOToken string
}
// WithSentinelTokens 设置 sentinel token header。
func (b *Builder) WithSentinelTokens(tokens SentinelTokens) *Builder {
if tokens.TurnStileToken != "" {
b.header.Set("Openai-Sentinel-Chat-Requirements-Token", tokens.TurnStileToken)
}
if tokens.ChatRequirementsPrepareToken != "" {
b.header.Set("Openai-Sentinel-Chat-Requirements-Prepare-Token", tokens.ChatRequirementsPrepareToken)
}
if tokens.ProofOfWorkToken != "" {
b.header.Set("Openai-Sentinel-Proof-Token", tokens.ProofOfWorkToken)
}
if tokens.TurnstileToken != "" {
b.header.Set("Openai-Sentinel-Turnstile-Token", tokens.TurnstileToken)
}
if tokens.SOToken != "" {
b.header.Set("Openai-Sentinel-So-Token", tokens.SOToken)
}
return b
}
// ── Conduit Token ──
// WithConduitToken 设置 X-Conduit-Token(即使为空也设置)。
func (b *Builder) WithConduitToken(token string) *Builder {
b.header.Set("X-Conduit-Token", token)
return b
}
// ── Turn Trace ID ──
// WithTurnTraceID 设置 X-Oai-Turn-Trace-Id。
func (b *Builder) WithTurnTraceID(id string) *Builder {
if id != "" {
b.header.Set("X-Oai-Turn-Trace-Id", id)
}
return b
}
// ── Conversation 特有 header ──
// WithConversationHeaders 设置 conversation 请求特有的 header。
func (b *Builder) WithConversationHeaders(targetPath string) *Builder {
if strings.HasSuffix(targetPath, "/f/conversation") && !strings.HasSuffix(targetPath, "/prepare") {
b.header.Set("Oai-Echo-Logs", "0,943,1,65876,0,68124,1,68930")
b.header.Set("Oai-Telemetry", "[1,null]")
}
return b
}
// ── 便捷构造函数 ──
// NewBaseHeader 创建基础 header(无 state)。
func NewBaseHeader() httpclient.AuroraHeaders {
return New().WithBaseHeaders("").Build()
}
// NewBaseHeaderWithState 创建带 state 的基础 header。
func NewBaseHeaderWithState(conversationID, deviceID, sessionID, userAgent string) httpclient.AuroraHeaders {
b := New().WithBaseHeaders(conversationID)
if deviceID != "" {
b.WithDeviceID(deviceID)
}
if sessionID != "" {
b.WithSessionID(sessionID)
}
if userAgent != "" {
b.header.Set("User-Agent", userAgent)
}
return b.Build()
}