移除前端proxy逻辑
This commit is contained in:
@@ -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' },
|
||||
|
||||
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user