移除前端proxy逻辑

This commit is contained in:
mtvpls
2026-02-01 20:07:41 +08:00
parent 46220ee927
commit e915a97a70
2 changed files with 178 additions and 252 deletions

View File

@@ -50,6 +50,86 @@ async function proxyRequest(
}
}
// 获取方法配置并执行请求
async function executeMethod(
baseUrl: string,
platform: string,
func: string,
variables: Record<string, string> = {}
): Promise<any> {
// 1. 获取方法配置
const cacheKey = `method-config-${platform}-${func}`;
let config: any;
const cached = serverCache.methodConfigs.get(cacheKey);
if (cached && Date.now() - cached.timestamp < serverCache.CACHE_DURATION) {
config = cached.data.data;
} else {
const response = await proxyRequest(`${baseUrl}/v1/methods/${platform}/${func}`);
const data = await response.json();
serverCache.methodConfigs.set(cacheKey, { data, timestamp: Date.now() });
config = data.data;
}
if (!config) {
throw new Error('无法获取方法配置');
}
// 2. 替换模板变量
let url = config.url;
const params: Record<string, string> = {};
if (config.params) {
for (const [key, value] of Object.entries(config.params)) {
let processedValue = String(value);
// 替换所有模板变量
for (const [varName, varValue] of Object.entries(variables)) {
processedValue = processedValue.replace(`{{${varName}}}`, varValue);
}
params[key] = processedValue;
}
}
// 3. 构建完整 URL
if (config.method === 'GET' && Object.keys(params).length > 0) {
const urlObj = new URL(url);
for (const [key, value] of Object.entries(params)) {
urlObj.searchParams.append(key, value);
}
url = urlObj.toString();
}
// 4. 发起请求
const requestOptions: RequestInit = {
method: config.method || 'GET',
headers: config.headers || {},
};
if (config.method === 'POST' && config.body) {
requestOptions.body = JSON.stringify(config.body);
requestOptions.headers = {
...requestOptions.headers,
'Content-Type': 'application/json',
};
}
const response = await proxyRequest(url, requestOptions);
let data = await response.json();
// 5. 执行 transform 函数(如果有)
if (config.transform) {
try {
// eslint-disable-next-line no-eval
const transformFn = eval(`(${config.transform})`);
data = transformFn(data);
} catch (err) {
console.error('Transform 函数执行失败:', err);
}
}
return data;
}
// GET 请求处理
export async function GET(request: NextRequest) {
try {
@@ -74,29 +154,8 @@ export async function GET(request: NextRequest) {
// 处理不同的 action
switch (action) {
case 'methods': {
// 获取所有平台方法
const cacheKey = 'methods-all';
const cached = serverCache.methodConfigs.get(cacheKey);
if (cached && Date.now() - cached.timestamp < serverCache.CACHE_DURATION) {
console.log('使用缓存: methods');
return NextResponse.json(cached.data);
}
const response = await proxyRequest(`${baseUrl}/v1/methods`);
const data = await response.json();
serverCache.methodConfigs.set(cacheKey, {
data,
timestamp: Date.now(),
});
return NextResponse.json(data);
}
case 'platform-methods': {
// 获取指定平台的方法
case 'toplists': {
// 获取排行榜列表
const platform = searchParams.get('platform');
if (!platform) {
return NextResponse.json(
@@ -105,95 +164,96 @@ export async function GET(request: NextRequest) {
);
}
const cacheKey = `platform-methods-${platform}`;
const cached = serverCache.methodConfigs.get(cacheKey);
if (cached && Date.now() - cached.timestamp < serverCache.CACHE_DURATION) {
console.log(`使用缓存: platform-methods-${platform}`);
return NextResponse.json(cached.data);
}
const response = await proxyRequest(`${baseUrl}/v1/methods/${platform}`);
const data = await response.json();
serverCache.methodConfigs.set(cacheKey, {
data,
timestamp: Date.now(),
});
return NextResponse.json(data);
}
case 'method-config': {
// 获取指定平台指定方法的配置
const platform = searchParams.get('platform');
const func = searchParams.get('function');
if (!platform || !func) {
return NextResponse.json(
{ error: '缺少 platform 或 function 参数' },
{ status: 400 }
);
}
const cacheKey = `method-config-${platform}-${func}`;
const cached = serverCache.methodConfigs.get(cacheKey);
if (cached && Date.now() - cached.timestamp < serverCache.CACHE_DURATION) {
console.log(`使用缓存: method-config-${platform}-${func}`);
return NextResponse.json(cached.data);
}
const response = await proxyRequest(
`${baseUrl}/v1/methods/${platform}/${func}`
);
const data = await response.json();
serverCache.methodConfigs.set(cacheKey, {
data,
timestamp: Date.now(),
});
return NextResponse.json(data);
}
case 'proxy': {
// 代理上游平台请求(用于方法下发后的实际请求)
const targetUrl = searchParams.get('url');
if (!targetUrl) {
return NextResponse.json(
{ error: '缺少 url 参数' },
{ status: 400 }
);
}
// 使用完整 URL 作为缓存键
const cacheKey = `proxy-${targetUrl}`;
const cacheKey = `toplists-${platform}`;
const cached = serverCache.proxyRequests.get(cacheKey);
if (cached && Date.now() - cached.timestamp < serverCache.CACHE_DURATION) {
console.log(`使用缓存: proxy request`);
return NextResponse.json(cached.data);
}
// 获取其他查询参数
const params = new URLSearchParams();
searchParams.forEach((value, key) => {
if (key !== 'action' && key !== 'url') {
params.append(key, value);
}
});
const fullUrl = params.toString()
? `${targetUrl}?${params.toString()}`
: targetUrl;
const response = await proxyRequest(fullUrl);
const data = await response.json();
serverCache.proxyRequests.set(cacheKey, {
data,
timestamp: Date.now(),
const data = await executeMethod(baseUrl, platform, 'toplists');
serverCache.proxyRequests.set(cacheKey, { data, timestamp: Date.now() });
return NextResponse.json(data);
}
case 'toplist': {
// 获取排行榜详情
const platform = searchParams.get('platform');
const id = searchParams.get('id');
if (!platform || !id) {
return NextResponse.json(
{ error: '缺少 platform 或 id 参数' },
{ status: 400 }
);
}
const cacheKey = `toplist-${platform}-${id}`;
const cached = serverCache.proxyRequests.get(cacheKey);
if (cached && Date.now() - cached.timestamp < serverCache.CACHE_DURATION) {
return NextResponse.json(cached.data);
}
const data = await executeMethod(baseUrl, platform, 'toplist', { id });
serverCache.proxyRequests.set(cacheKey, { data, timestamp: Date.now() });
return NextResponse.json(data);
}
case 'playlist': {
// 获取歌单详情
const platform = searchParams.get('platform');
const id = searchParams.get('id');
if (!platform || !id) {
return NextResponse.json(
{ error: '缺少 platform 或 id 参数' },
{ status: 400 }
);
}
const cacheKey = `playlist-${platform}-${id}`;
const cached = serverCache.proxyRequests.get(cacheKey);
if (cached && Date.now() - cached.timestamp < serverCache.CACHE_DURATION) {
return NextResponse.json(cached.data);
}
const data = await executeMethod(baseUrl, platform, 'playlist', { id });
serverCache.proxyRequests.set(cacheKey, { data, timestamp: Date.now() });
return NextResponse.json(data);
}
case 'search': {
// 搜索歌曲
const platform = searchParams.get('platform');
const keyword = searchParams.get('keyword');
const page = searchParams.get('page') || '0';
const pageSize = searchParams.get('pageSize') || '20';
if (!platform || !keyword) {
return NextResponse.json(
{ error: '缺少 platform 或 keyword 参数' },
{ status: 400 }
);
}
const cacheKey = `search-${platform}-${keyword}-${page}-${pageSize}`;
const cached = serverCache.proxyRequests.get(cacheKey);
if (cached && Date.now() - cached.timestamp < serverCache.CACHE_DURATION) {
return NextResponse.json(cached.data);
}
const data = await executeMethod(baseUrl, platform, 'search', {
keyword,
page,
pageSize,
});
serverCache.proxyRequests.set(cacheKey, { data, timestamp: Date.now() });
return NextResponse.json(data);
}
@@ -301,29 +361,6 @@ export async function POST(request: NextRequest) {
}
}
case 'proxy-post': {
// 代理 POST 请求到上游平台
const { url, data: postData, headers } = body;
if (!url) {
return NextResponse.json(
{ error: '缺少 url 参数' },
{ status: 400 }
);
}
const response = await proxyRequest(url, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
...headers,
},
body: JSON.stringify(postData),
});
const responseData = await response.json();
return NextResponse.json(responseData);
}
default:
return NextResponse.json(
{ error: '不支持的 action' },

View File

@@ -207,41 +207,10 @@ export default function MusicPage() {
setLoading(true);
try {
const response = await fetch(
`/api/music?action=method-config&platform=${source}&function=toplists`
`/api/music?action=toplists&platform=${source}`
);
const configData = await response.json();
if (configData.code === 0 && configData.data) {
const config = configData.data;
const url = new URL(config.url);
// 添加参数
if (config.params) {
Object.entries(config.params).forEach(([key, value]) => {
url.searchParams.append(key, String(value));
});
}
// 通过后端代理请求
const proxyResponse = await fetch(
`/api/music?action=proxy&url=${encodeURIComponent(url.toString())}`
);
const data = await proxyResponse.json();
// 使用 transform 函数处理数据
if (config.transform) {
try {
const transformFn = eval(`(${config.transform})`);
const transformed = transformFn(data);
setPlaylists(transformed || []);
} catch (err) {
console.error('Transform 函数执行失败:', err);
setPlaylists(data.list || data.data || []);
}
} else {
setPlaylists(data.list || data.data || []);
}
}
const data = await response.json();
setPlaylists(data || []);
} catch (error) {
console.error('加载排行榜失败:', error);
} finally {
@@ -254,47 +223,12 @@ export default function MusicPage() {
setLoading(true);
try {
const response = await fetch(
`/api/music?action=method-config&platform=${currentSource}&function=toplist`
`/api/music?action=toplist&platform=${currentSource}&id=${playlistId}`
);
const configData = await response.json();
if (configData.code === 0 && configData.data) {
const config = configData.data;
let url = config.url;
// 替换模板变量
if (config.params) {
const params = new URLSearchParams();
Object.entries(config.params).forEach(([key, value]) => {
const processedValue = String(value).replace('{{id}}', playlistId);
params.append(key, processedValue);
});
url = `${url}?${params.toString()}`;
}
// 通过后端代理请求
const proxyResponse = await fetch(
`/api/music?action=proxy&url=${encodeURIComponent(url)}`
);
const data = await proxyResponse.json();
// 使用 transform 函数处理数据
if (config.transform) {
try {
const transformFn = eval(`(${config.transform})`);
const transformed = transformFn(data);
setSongs(transformed || []);
} catch (err) {
console.error('Transform 函数执行失败:', err);
setSongs(data.songs || data.data || []);
}
} else {
setSongs(data.songs || data.data || []);
}
setCurrentPlaylistTitle(playlistName);
setCurrentView('songs');
}
const data = await response.json();
setSongs(data || []);
setCurrentPlaylistTitle(playlistName);
setCurrentView('songs');
} catch (error) {
console.error('加载歌单失败:', error);
} finally {
@@ -309,57 +243,12 @@ export default function MusicPage() {
setLoading(true);
try {
const response = await fetch(
`/api/music?action=method-config&platform=${currentSource}&function=search`
`/api/music?action=search&platform=${currentSource}&keyword=${encodeURIComponent(searchKeyword)}&page=1&pageSize=20`
);
const configData = await response.json();
if (configData.code === 0 && configData.data) {
const config = configData.data;
let url = config.url;
// 替换模板变量
if (config.params) {
const params = new URLSearchParams();
Object.entries(config.params).forEach(([key, value]) => {
let processedValue = String(value)
.replace('{{keyword}}', searchKeyword)
.replace('{{page}}', '1')
.replace('{{limit}}', '20')
.replace('{{pageSize}}', '20');
// 处理复杂表达式
if (processedValue.includes('{{')) {
processedValue = processedValue.replace(/\{\{.*?\}\}/g, '0');
}
params.append(key, processedValue);
});
url = `${url}?${params.toString()}`;
}
// 通过后端代理请求
const proxyResponse = await fetch(
`/api/music?action=proxy&url=${encodeURIComponent(url)}`
);
const data = await proxyResponse.json();
// 使用 transform 函数处理数据
if (config.transform) {
try {
const transformFn = eval(`(${config.transform})`);
const transformed = transformFn(data);
setSongs(transformed || []);
} catch (err) {
console.error('Transform 函数执行失败:', err);
setSongs(data.songs || data.data || []);
}
} else {
setSongs(data.songs || data.data || []);
}
setCurrentPlaylistTitle(`搜索: ${searchKeyword}`);
setCurrentView('songs');
}
const data = await response.json();
setSongs(data || []);
setCurrentPlaylistTitle(`搜索: ${searchKeyword}`);
setCurrentView('songs');
} catch (error) {
console.error('搜索失败:', error);
} finally {