Files
sub2api/backend/internal/service/grok_upstream_headers.go
T

75 lines
2.6 KiB
Go
Raw Normal View History

package service
import (
"net/http"
"strings"
"github.com/gin-gonic/gin"
"github.com/Wei-Shaw/sub2api/internal/pkg/tlsfingerprint"
"github.com/Wei-Shaw/sub2api/internal/pkg/xai"
)
// grokUpstreamUserAgent is kept for compatibility with older Grok request
// tests. Current requests use the pinned default UA from this package.
const grokUpstreamUserAgent = "sub2api-grok/1.0"
// Fixed CLI identity aliases — single source of truth is internal/pkg/xai.
const (
grokClientVersionHeader = xai.CLIStableVersion
grokClientIdentifierHeader = xai.CLIClientIdentifier
grokClientModeHeader = xai.CLIClientMode
)
// defaultGrokUpstreamUserAgent is the pinned Grok CLI / workspace UA.
// Grok upstream must not forward Claude Code / Codex / browser client UAs.
func defaultGrokUpstreamUserAgent() string {
return xai.CLIUserAgent(xai.ResolveCLIVersion())
}
func applyDefaultGrokUpstreamHeaders(req *http.Request) {
if req == nil {
return
}
// Always stamp CLI identity. Do not preserve inbound client UA (Claude Code,
// Codex, curl, etc.) — xAI chat/CLI surfaces fingerprint the client string.
req.Header.Set("User-Agent", defaultGrokUpstreamUserAgent())
req.Header.Set("x-grok-client-version", xai.ResolveCLIVersion())
req.Header.Set("x-grok-client-identifier", grokClientIdentifierHeader)
}
func applyGrokTLSProfileHeaders(req *http.Request, profile *tlsfingerprint.Profile) {
// HEAD Profile is TLS-only (no HTTP UserAgent/Originator fields). Always stamp CLI identity.
applyDefaultGrokUpstreamHeaders(req)
_ = profile
}
// openAITLSFingerprintRuntime is the resolved TLS fingerprint routing result
// used by OpenAI/Grok outbound header application. Defined here so Grok header
// helpers compile even when the full OpenAI TLS router is not present on HEAD.
type openAITLSFingerprintRuntime struct {
Profile *tlsfingerprint.Profile
UpstreamUserAgent string
UpstreamOriginator string
Matched bool
}
func applyGrokRuntimeHeaders(req *http.Request, runtime openAITLSFingerprintRuntime) {
applyDefaultGrokUpstreamHeaders(req)
if req == nil {
return
}
// Apply Originator only; force CLI UA after so router overrides cannot
// leak Codex/Claude Code identity onto Grok upstream.
if originator := strings.TrimSpace(runtime.UpstreamOriginator); originator != "" {
req.Header.Set("Originator", originator)
}
req.Header.Set("User-Agent", defaultGrokUpstreamUserAgent())
}
// resolveGrokUpstreamUserAgent always returns the pinned Grok CLI User-Agent.
// Inbound client UAs (Claude Code, Codex, browsers, libraries) are never forwarded.
func resolveGrokUpstreamUserAgent(_ *gin.Context) string {
return defaultGrokUpstreamUserAgent()
}