From 96f1a59d2043b67fedf652dc54f5f96f2623a7ab Mon Sep 17 00:00:00 2001 From: MoeFurina Date: Mon, 28 Jul 2025 18:58:22 +0800 Subject: [PATCH] =?UTF-8?q?=E7=94=A8ai=E8=AF=95=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- api/index.js | 23 --------- edgeone.config.json | 26 ++++++++++ edgeone.json | 33 ------------- functions/api/[[default]].js | 96 ++++++++++++++++++++++++++++++++++++ 4 files changed, 122 insertions(+), 56 deletions(-) delete mode 100644 api/index.js create mode 100644 edgeone.config.json delete mode 100644 edgeone.json create mode 100644 functions/api/[[default]].js diff --git a/api/index.js b/api/index.js deleted file mode 100644 index e7b2b36..0000000 --- a/api/index.js +++ /dev/null @@ -1,23 +0,0 @@ -const { serveNcmApi } = require('../server') - -export default async function handler(req, res) { - // EdgeOne Pages 环境配置 - process.env.NODE_ENV = 'production' - - // 初始化服务 - const app = await serveNcmApi({ - port: process.env.PORT || 3000, - host: '0.0.0.0' - }) - - // 将请求转发给 Express 应用 - return new Promise((resolve, reject) => { - app.handle(req, res, (err) => { - if (err) { - reject(err) - } else { - resolve() - } - }) - }) -} diff --git a/edgeone.config.json b/edgeone.config.json new file mode 100644 index 0000000..3675a57 --- /dev/null +++ b/edgeone.config.json @@ -0,0 +1,26 @@ +{ + "functions": { + "*": { + "memory": 1024, + "runtime": "nodejs18", + "timeout": 30 + } + }, + "routes": [ + { + "src": "/(.*)", + "dest": "/api/[...default]", + "headers": { + "Access-Control-Allow-Credentials": "true", + "Access-Control-Allow-Origin": "*", + "Access-Control-Allow-Methods": "GET,POST,PUT,DELETE,OPTIONS", + "Access-Control-Allow-Headers": "X-CSRF-Token, X-Requested-With, Accept, Accept-Version, Content-Length, Content-MD5, Content-Type, Date, X-Api-Version" + } + } + ], + "buildCommand": "cp -r module functions/api/ && cp -r util functions/api/ && cp -r plugins functions/api/ && cp -r public functions/api/ && cp -r data functions/api/ && cp server.js functions/api/ && cp package.json functions/api/ && cd functions/api && npm install --only=production", + "outputDirectory": "functions/api", + "dev": { + "command": "npm install && npm start" + } +} diff --git a/edgeone.json b/edgeone.json deleted file mode 100644 index 4a148d1..0000000 --- a/edgeone.json +++ /dev/null @@ -1,33 +0,0 @@ -{ - "functions": { - "*": { - "memory": 1024, - "runtime": "nodejs18" - } - }, - "routes": [ - { - "src": "/(.*)", - "dest": "/api/index.js", - "headers": { - "Access-Control-Allow-Credentials": "true", - "Access-Control-Allow-Methods": "GET,POST,PUT,DELETE,OPTIONS", - "Access-Control-Allow-Headers": "X-CSRF-Token, X-Requested-With, Accept, Accept-Version, Content-Length, Content-MD5, Content-Type, Date, X-Api-Version" - } - } - ], - "build": { - "command": "pnpm install --registry=https://registry.npmmirror.com", - "include": [ - "api", - "module", - "util", - "plugins", - "public", - "data", - "server.js", - "package.json", - ".env" - ] - } -} diff --git a/functions/api/[[default]].js b/functions/api/[[default]].js new file mode 100644 index 0000000..a05ffeb --- /dev/null +++ b/functions/api/[[default]].js @@ -0,0 +1,96 @@ +const { serveNcmApi } = require('../../server') + +// 默认配置 +const defaultEnv = { + ENABLE_GENERAL_UNBLOCK: 'true', + ENABLE_FLAC: 'true', + SELECT_MAX_BR: 'true', + UNBLOCK_SOURCE: 'pyncmd,qq,kuwo,migu,kugou', + FOLLOW_SOURCE_ORDER: 'true', + CORS_ALLOW_ORIGIN: '*', + ENABLE_PROXY: 'false', + PROXY_URL: '', + NETEASE_COOKIE: '', + JOOX_COOKIE: '', + MIGU_COOKIE: '', + QQ_COOKIE: '', + YOUTUBE_KEY: '' +} + +let app = null + +export async function onRequest(context) { + const { request, env } = context + + // 合并默认配置和环境变量 + Object.keys(defaultEnv).forEach(key => { + process.env[key] = env[key] || defaultEnv[key] + }) + + if (!app) { + app = await serveNcmApi({ + checkVersion: false // 禁用版本检查,避免在边缘函数环境中发起不必要的网络请求 + }) + } + + return new Promise((resolve) => { + let body = [] + request.arrayBuffer().then(buffer => { + if (buffer.byteLength > 0) { + body = Buffer.from(buffer) + } + + // 构造 Express 兼容的请求对象 + const req = new Proxy(request, { + get: (target, prop) => { + switch(prop) { + case 'body': + return body + case 'query': + return Object.fromEntries(new URL(request.url).searchParams) + case 'cookies': + return Object.fromEntries( + request.headers.get('cookie')?.split(';') + .map(cookie => cookie.trim().split('=')) + .map(([key, value]) => [key, decodeURIComponent(value)]) || [] + ) + default: + return target[prop] + } + } + }) + + // 构造 Express 兼容的响应对象 + const res = { + status: (code) => { + res.statusCode = code + return res + }, + set: (headers) => { + Object.entries(headers).forEach(([key, value]) => { + res.headers[key] = value + }) + return res + }, + send: (body) => { + const response = new Response( + typeof body === 'string' ? body : JSON.stringify(body), + { + status: res.statusCode || 200, + headers: { + 'Content-Type': 'application/json;charset=utf-8', + ...res.headers + } + } + ) + resolve(response) + }, + statusCode: 200, + headers: {} + } + + // 处理请求 + app.handle(req, res) + }) + }) +}