cursor / utils /headers.go
cacode's picture
Upload 48 files
1766992 verified
// Copyright (c) 2025-2026 libaxuan
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
package utils
import (
"fmt"
"math/rand"
"runtime"
"time"
)
// BrowserProfile 浏览器配置文件
type BrowserProfile struct {
Platform string
PlatformVersion string
Architecture string
Bitness string
ChromeVersion int
UserAgent string
Mobile bool
}
var (
// 常见的浏览器版本 (Chrome)
chromeVersions = []int{120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130}
// Windows 平台配置
windowsProfiles = []BrowserProfile{
{Platform: "Windows", PlatformVersion: "10.0.0", Architecture: "x86", Bitness: "64"},
{Platform: "Windows", PlatformVersion: "11.0.0", Architecture: "x86", Bitness: "64"},
{Platform: "Windows", PlatformVersion: "15.0.0", Architecture: "x86", Bitness: "64"},
}
// macOS 平台配置
macosProfiles = []BrowserProfile{
{Platform: "macOS", PlatformVersion: "13.0.0", Architecture: "arm", Bitness: "64"},
{Platform: "macOS", PlatformVersion: "14.0.0", Architecture: "arm", Bitness: "64"},
{Platform: "macOS", PlatformVersion: "15.0.0", Architecture: "arm", Bitness: "64"},
{Platform: "macOS", PlatformVersion: "13.0.0", Architecture: "x86", Bitness: "64"},
{Platform: "macOS", PlatformVersion: "14.0.0", Architecture: "x86", Bitness: "64"},
}
// Linux 平台配置
linuxProfiles = []BrowserProfile{
{Platform: "Linux", PlatformVersion: "", Architecture: "x86", Bitness: "64"},
}
)
// HeaderGenerator 动态 header 生成器
type HeaderGenerator struct {
profile BrowserProfile
chromeVersion int
rng *rand.Rand
}
// NewHeaderGenerator 创建新的 header 生成器
func NewHeaderGenerator() *HeaderGenerator {
// 使用当前时间作为随机种子
rng := rand.New(rand.NewSource(time.Now().UnixNano()))
// 根据当前操作系统选择合适的配置文件
var profiles []BrowserProfile
switch runtime.GOOS {
case "darwin":
profiles = macosProfiles
case "linux":
profiles = linuxProfiles
default:
profiles = windowsProfiles
}
// 随机选择一个配置文件
profile := profiles[rng.Intn(len(profiles))]
// 随机选择 Chrome 版本
chromeVersion := chromeVersions[rng.Intn(len(chromeVersions))]
profile.ChromeVersion = chromeVersion
// 生成 User-Agent
profile.UserAgent = generateUserAgent(profile)
return &HeaderGenerator{
profile: profile,
chromeVersion: chromeVersion,
rng: rng,
}
}
// generateUserAgent 生成 User-Agent 字符串
func generateUserAgent(profile BrowserProfile) string {
switch profile.Platform {
case "Windows":
return fmt.Sprintf("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/%d.0.0.0 Safari/537.36", profile.ChromeVersion)
case "macOS":
if profile.Architecture == "arm" {
return fmt.Sprintf("Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/%d.0.0.0 Safari/537.36", profile.ChromeVersion)
}
return fmt.Sprintf("Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/%d.0.0.0 Safari/537.36", profile.ChromeVersion)
case "Linux":
return fmt.Sprintf("Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/%d.0.0.0 Safari/537.36", profile.ChromeVersion)
default:
return fmt.Sprintf("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/%d.0.0.0 Safari/537.36", profile.ChromeVersion)
}
}
// GetChatHeaders 获取聊天请求的 headers
func (g *HeaderGenerator) GetChatHeaders(xIsHuman string) map[string]string {
// 随机选择语言
languages := []string{
"en-US,en;q=0.9",
"zh-CN,zh;q=0.9,en;q=0.8",
"en-GB,en;q=0.9",
}
lang := languages[g.rng.Intn(len(languages))]
// 随机选择 referer
referers := []string{
"https://cursor.com/en-US/learn/how-ai-models-work",
"https://cursor.com/cn/learn/how-ai-models-work",
"https://cursor.com/",
}
referer := referers[g.rng.Intn(len(referers))]
headers := map[string]string{
"sec-ch-ua-platform": fmt.Sprintf(`"%s"`, g.profile.Platform),
"x-path": "/api/chat",
"Referer": referer,
"sec-ch-ua": g.getSecChUa(),
"x-method": "POST",
"sec-ch-ua-mobile": "?0",
"x-is-human": xIsHuman,
"User-Agent": g.profile.UserAgent,
"content-type": "application/json",
"accept-language": lang,
}
// 添加可选的 headers
if g.profile.Architecture != "" {
headers["sec-ch-ua-arch"] = fmt.Sprintf(`"%s"`, g.profile.Architecture)
}
if g.profile.Bitness != "" {
headers["sec-ch-ua-bitness"] = fmt.Sprintf(`"%s"`, g.profile.Bitness)
}
if g.profile.PlatformVersion != "" {
headers["sec-ch-ua-platform-version"] = fmt.Sprintf(`"%s"`, g.profile.PlatformVersion)
}
return headers
}
// GetScriptHeaders 获取脚本请求的 headers
func (g *HeaderGenerator) GetScriptHeaders() map[string]string {
// 随机选择语言
languages := []string{
"en-US,en;q=0.9",
"zh-CN,zh;q=0.9,en;q=0.8",
"en-GB,en;q=0.9",
}
lang := languages[g.rng.Intn(len(languages))]
// 随机选择 referer
referers := []string{
"https://cursor.com/cn/learn/how-ai-models-work",
"https://cursor.com/en-US/learn/how-ai-models-work",
"https://cursor.com/",
}
referer := referers[g.rng.Intn(len(referers))]
headers := map[string]string{
"User-Agent": g.profile.UserAgent,
"sec-ch-ua-arch": fmt.Sprintf(`"%s"`, g.profile.Architecture),
"sec-ch-ua-platform": fmt.Sprintf(`"%s"`, g.profile.Platform),
"sec-ch-ua": g.getSecChUa(),
"sec-ch-ua-bitness": fmt.Sprintf(`"%s"`, g.profile.Bitness),
"sec-ch-ua-mobile": "?0",
"sec-fetch-site": "same-origin",
"sec-fetch-mode": "no-cors",
"sec-fetch-dest": "script",
"referer": referer,
"accept-language": lang,
}
if g.profile.PlatformVersion != "" {
headers["sec-ch-ua-platform-version"] = fmt.Sprintf(`"%s"`, g.profile.PlatformVersion)
}
return headers
}
// getSecChUa 生成 sec-ch-ua header
func (g *HeaderGenerator) getSecChUa() string {
// 生成随机的品牌版本
notABrand := 24 + g.rng.Intn(10) // 24-33
return fmt.Sprintf(`"Google Chrome";v="%d", "Chromium";v="%d", "Not(A:Brand";v="%d"`,
g.chromeVersion, g.chromeVersion, notABrand)
}
// GetUserAgent 获取 User-Agent
func (g *HeaderGenerator) GetUserAgent() string {
return g.profile.UserAgent
}
// GetProfile 获取浏览器配置文件
func (g *HeaderGenerator) GetProfile() BrowserProfile {
return g.profile
}
// Refresh 刷新配置文件(生成新的随机配置)
func (g *HeaderGenerator) Refresh() {
// 根据当前操作系统选择合适的配置文件
var profiles []BrowserProfile
switch runtime.GOOS {
case "darwin":
profiles = macosProfiles
case "linux":
profiles = linuxProfiles
default:
profiles = windowsProfiles
}
// 随机选择一个配置文件
profile := profiles[g.rng.Intn(len(profiles))]
// 随机选择 Chrome 版本
chromeVersion := chromeVersions[g.rng.Intn(len(chromeVersions))]
profile.ChromeVersion = chromeVersion
// 生成 User-Agent
profile.UserAgent = generateUserAgent(profile)
g.profile = profile
g.chromeVersion = chromeVersion
}
// GetRandomReferer 获取随机 referer
func GetRandomReferer() string {
referers := []string{
"https://cursor.com/en-US/learn/how-ai-models-work",
"https://cursor.com/cn/learn/how-ai-models-work",
"https://cursor.com/",
"https://cursor.com/features",
}
rng := rand.New(rand.NewSource(time.Now().UnixNano()))
return referers[rng.Intn(len(referers))]
}
// GetRandomLanguage 获取随机语言设置
func GetRandomLanguage() string {
languages := []string{
"en-US,en;q=0.9",
"zh-CN,zh;q=0.9,en;q=0.8",
"en-GB,en;q=0.9",
"ja-JP,ja;q=0.9,en;q=0.8",
}
rng := rand.New(rand.NewSource(time.Now().UnixNano()))
return languages[rng.Intn(len(languages))]
}