优化代理

This commit is contained in:
wangbo 2025-09-07 18:42:24 +08:00
parent 0646ebc59b
commit 42cb19214f
6 changed files with 137 additions and 5376 deletions

View File

@ -1,13 +1,12 @@
# syntax=docker/dockerfile:1
FROM node:lts-bookworm AS builder
FROM node:lts-bookworm AS builder
WORKDIR /src WORKDIR /src
COPY package*.json ./ COPY package*.json ./
RUN npm install RUN npm install
COPY . . COPY . .
RUN npm run build RUN npm run build
FROM node:lts-bookworm FROM node:lts-bookworm
WORKDIR /app WORKDIR /app
COPY package*.json ./ COPY package*.json ./

View File

@ -2,12 +2,13 @@ version: '3'
services: services:
suno-api: suno-api:
build: image: registry.cn-shanghai.aliyuncs.com/easyaigc/suno-api:latest
context: . # build:
args: # context: .
SUNO_COOKIE: ${SUNO_COOKIE} # args:
# SUNO_COOKIE: ${SUNO_COOKIE}
volumes: volumes:
- ./public:/app/public - ./public:/app/public
ports: ports:
- "3000:3000" - "3013:3000"
env_file: ".env" env_file: ".env"

71
package-lock.json generated
View File

@ -18,6 +18,7 @@
"cookie": "^1.0.2", "cookie": "^1.0.2",
"electron": "^33.2.1", "electron": "^33.2.1",
"ghost-cursor-playwright": "^2.1.0", "ghost-cursor-playwright": "^2.1.0",
"https-proxy-agent": "^7.0.6",
"js-cookie": "^3.0.5", "js-cookie": "^3.0.5",
"next": "14.1.4", "next": "14.1.4",
"next-swagger-doc": "^0.4.0", "next-swagger-doc": "^0.4.0",
@ -27,6 +28,7 @@
"react-dom": "^18", "react-dom": "^18",
"react-markdown": "^9.0.1", "react-markdown": "^9.0.1",
"rebrowser-playwright-core": "^1.49.1", "rebrowser-playwright-core": "^1.49.1",
"socks-proxy-agent": "^8.0.5",
"swagger-ui-react": "^5.18.2", "swagger-ui-react": "^5.18.2",
"tough-cookie": "^4.1.4", "tough-cookie": "^4.1.4",
"user-agents": "^1.1.156", "user-agents": "^1.1.156",
@ -1600,6 +1602,15 @@
"acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0"
} }
}, },
"node_modules/agent-base": {
"version": "7.1.4",
"resolved": "https://registry.npmmirror.com/agent-base/-/agent-base-7.1.4.tgz",
"integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==",
"license": "MIT",
"engines": {
"node": ">= 14"
}
},
"node_modules/ajv": { "node_modules/ajv": {
"version": "6.12.6", "version": "6.12.6",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
@ -4609,6 +4620,19 @@
"node": ">=10.19.0" "node": ">=10.19.0"
} }
}, },
"node_modules/https-proxy-agent": {
"version": "7.0.6",
"resolved": "https://registry.npmmirror.com/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz",
"integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==",
"license": "MIT",
"dependencies": {
"agent-base": "^7.1.2",
"debug": "4"
},
"engines": {
"node": ">= 14"
}
},
"node_modules/ieee754": { "node_modules/ieee754": {
"version": "1.2.1", "version": "1.2.1",
"resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
@ -4729,6 +4753,15 @@
"loose-envify": "^1.0.0" "loose-envify": "^1.0.0"
} }
}, },
"node_modules/ip-address": {
"version": "10.0.1",
"resolved": "https://registry.npmmirror.com/ip-address/-/ip-address-10.0.1.tgz",
"integrity": "sha512-NWv9YLW4PoW2B7xtzaS3NCot75m6nK7Icdv0o3lfMceJVRfSoQwqD4wEH5rLwoKJwUiZ/rfpiVBhnaF0FK4HoA==",
"license": "MIT",
"engines": {
"node": ">= 12"
}
},
"node_modules/is-alphabetical": { "node_modules/is-alphabetical": {
"version": "2.0.1", "version": "2.0.1",
"resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-2.0.1.tgz", "resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-2.0.1.tgz",
@ -8402,6 +8435,44 @@
"node": ">=8" "node": ">=8"
} }
}, },
"node_modules/smart-buffer": {
"version": "4.2.0",
"resolved": "https://registry.npmmirror.com/smart-buffer/-/smart-buffer-4.2.0.tgz",
"integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==",
"license": "MIT",
"engines": {
"node": ">= 6.0.0",
"npm": ">= 3.0.0"
}
},
"node_modules/socks": {
"version": "2.8.7",
"resolved": "https://registry.npmmirror.com/socks/-/socks-2.8.7.tgz",
"integrity": "sha512-HLpt+uLy/pxB+bum/9DzAgiKS8CX1EvbWxI4zlmgGCExImLdiad2iCwXT5Z4c9c3Eq8rP2318mPW2c+QbtjK8A==",
"license": "MIT",
"dependencies": {
"ip-address": "^10.0.1",
"smart-buffer": "^4.2.0"
},
"engines": {
"node": ">= 10.0.0",
"npm": ">= 3.0.0"
}
},
"node_modules/socks-proxy-agent": {
"version": "8.0.5",
"resolved": "https://registry.npmmirror.com/socks-proxy-agent/-/socks-proxy-agent-8.0.5.tgz",
"integrity": "sha512-HehCEsotFqbPW9sJ8WVYB6UbmIMv7kUUORIF2Nncq4VQvBfNBLibW9YZR5dlYCSUhwcD628pRllm7n+E+YTzJw==",
"license": "MIT",
"dependencies": {
"agent-base": "^7.1.2",
"debug": "^4.3.4",
"socks": "^2.8.3"
},
"engines": {
"node": ">= 14"
}
},
"node_modules/sonic-boom": { "node_modules/sonic-boom": {
"version": "3.8.1", "version": "3.8.1",
"resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-3.8.1.tgz", "resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-3.8.1.tgz",

View File

@ -9,7 +9,7 @@
"version": "1.1.0", "version": "1.1.0",
"private": true, "private": true,
"scripts": { "scripts": {
"dev": "next dev", "dev": "PORT=3013 next dev",
"build": "next build", "build": "next build",
"start": "next start", "start": "next start",
"lint": "next lint" "lint": "next lint"
@ -24,6 +24,7 @@
"cookie": "^1.0.2", "cookie": "^1.0.2",
"electron": "^33.2.1", "electron": "^33.2.1",
"ghost-cursor-playwright": "^2.1.0", "ghost-cursor-playwright": "^2.1.0",
"https-proxy-agent": "^7.0.6",
"js-cookie": "^3.0.5", "js-cookie": "^3.0.5",
"next": "14.1.4", "next": "14.1.4",
"next-swagger-doc": "^0.4.0", "next-swagger-doc": "^0.4.0",
@ -33,6 +34,7 @@
"react-dom": "^18", "react-dom": "^18",
"react-markdown": "^9.0.1", "react-markdown": "^9.0.1",
"rebrowser-playwright-core": "^1.49.1", "rebrowser-playwright-core": "^1.49.1",
"socks-proxy-agent": "^8.0.5",
"swagger-ui-react": "^5.18.2", "swagger-ui-react": "^5.18.2",
"tough-cookie": "^4.1.4", "tough-cookie": "^4.1.4",
"user-agents": "^1.1.156", "user-agents": "^1.1.156",

File diff suppressed because it is too large Load Diff

View File

@ -11,6 +11,7 @@ import { BrowserContext, Page, Locator, chromium, firefox } from 'rebrowser-play
import { createCursor, Cursor } from 'ghost-cursor-playwright'; import { createCursor, Cursor } from 'ghost-cursor-playwright';
import { promises as fs } from 'fs'; import { promises as fs } from 'fs';
import path from 'node:path'; import path from 'node:path';
import { SocksProxyAgent } from 'socks-proxy-agent';
// sunoApi instance caching // sunoApi instance caching
const globalForSunoApi = global as unknown as { sunoApiCache?: Map<string, SunoApi> }; const globalForSunoApi = global as unknown as { sunoApiCache?: Map<string, SunoApi> };
@ -86,6 +87,29 @@ class SunoApi {
this.userAgent = new UserAgent(/Macintosh/).random().toString(); // Usually Mac systems get less amount of CAPTCHAs this.userAgent = new UserAgent(/Macintosh/).random().toString(); // Usually Mac systems get less amount of CAPTCHAs
this.cookies = cookie.parse(cookies); this.cookies = cookie.parse(cookies);
this.deviceId = this.cookies.ajs_anonymous_id || randomUUID(); this.deviceId = this.cookies.ajs_anonymous_id || randomUUID();
const proxyUrl = process.env.PROXY_URL;
let extraConfig: Record<string, any> = {};
if (proxyUrl) {
if (proxyUrl.startsWith('socks')) {
// SOCKS5 代理
const agent = new SocksProxyAgent(proxyUrl);
extraConfig = {
httpAgent: agent,
httpsAgent: agent,
proxy: false // 一定要关掉 axios 自带的 proxy
};
} else {
// HTTP/HTTPS 代理
const url = new URL(proxyUrl);
extraConfig = {
proxy: {
protocol: url.protocol.replace(':', ''), // 去掉末尾冒号
host: url.hostname,
port: Number(url.port)
}
};
}
}
this.client = axios.create({ this.client = axios.create({
withCredentials: true, withCredentials: true,
headers: { headers: {
@ -97,7 +121,8 @@ class SunoApi {
'sec-ch-ua-mobile': '?1', 'sec-ch-ua-mobile': '?1',
'sec-ch-ua-platform': '"Android"', 'sec-ch-ua-platform': '"Android"',
'User-Agent': this.userAgent 'User-Agent': this.userAgent
} },
...extraConfig,
}); });
this.client.interceptors.request.use(config => { this.client.interceptors.request.use(config => {
if (this.currentToken && !config.headers.Authorization) if (this.currentToken && !config.headers.Authorization)
@ -273,31 +298,39 @@ class SunoApi {
args.push('--enable-unsafe-swiftshader', args.push('--enable-unsafe-swiftshader',
'--disable-gpu', '--disable-gpu',
'--disable-setuid-sandbox'); '--disable-setuid-sandbox');
const browser = await this.getBrowserType().launch({ try {
args, const browser = await this.getBrowserType().launch({
headless: yn(process.env.BROWSER_HEADLESS, { default: true }) args,
}); headless: yn(process.env.BROWSER_HEADLESS, { default: true }),
const context = await browser.newContext({ userAgent: this.userAgent, locale: process.env.BROWSER_LOCALE, viewport: null }); ...(process.env.PROXY_URL &&{ proxy: {
const cookies = []; server: process.env.PROXY_URL,
const lax: 'Lax' | 'Strict' | 'None' = 'Lax'; }})
cookies.push({ })
name: '__session', const context = await browser.newContext({ userAgent: this.userAgent, locale: process.env.BROWSER_LOCALE, viewport: null });
value: this.currentToken+'', const cookies = [];
domain: '.suno.com', const lax: 'Lax' | 'Strict' | 'None' = 'Lax';
path: '/',
sameSite: lax
});
for (const key in this.cookies) {
cookies.push({ cookies.push({
name: key, name: '__session',
value: this.cookies[key]+'', value: this.currentToken+'',
domain: '.suno.com', domain: '.suno.com',
path: '/', path: '/',
sameSite: lax sameSite: lax
}) });
for (const key in this.cookies) {
cookies.push({
name: key,
value: this.cookies[key]+'',
domain: '.suno.com',
path: '/',
sameSite: lax
})
}
await context.addCookies(cookies);
return context;
}catch ( e){
console.log(e);
throw e;
} }
await context.addCookies(cookies);
return context;
} }
/** /**