const swagger = require("../../_docs/swagger.json"); const auth = require("../service/biz_auth_verify"); const proxy = require("../service/biz_proxy_service"); /** * 从 ctx 请求头中提取 Token(不含 query) * - Authorization: Bearer * - Authorization: (无 Bearer 前缀时整段作为 token) * - X-Api-Token / X-Token */ function extractToken(ctx) { let x_token = ctx.headers['authorization'] || '' if (x_token.startsWith("Bearer ")) { x_token = x_token.slice(7).trim(); } return x_token; } /** * 提取 swagger tags 第一项作为 feature 名(用于套餐功能点校验) */ function pickFeature(spec) { if (spec.tags && spec.tags.length > 0) { return spec.tags[0]; } return null; } /** 不参与转发的文档路径(与 framework 实际路由重叠或仅为说明) */ function should_skip_proxy_path(route_path) { return ( route_path.startsWith("/admin_api") || route_path.startsWith("/api/auth") ); } /** * 构建转发路由表(供 framework.addRoutes 注册) */ function buildProxyRoutes() { const routes = {}; for (const [path, methods] of Object.entries(swagger.paths)) { if (should_skip_proxy_path(path)) { continue; } for (const [method, spec] of Object.entries(methods)) { const routeKey = `${method.toUpperCase()} ${path}`; routes[routeKey] = async (ctx) => { // 1. 提取 Token const token = extractToken(ctx); if (!token) { ctx.fail("缺少 Token"); return; } // 2. 鉴权:Token + 用户 + 订阅 + 套餐功能点 + 接口权限 + 调用量 const feature = pickFeature(spec); const authResult = await auth.verifyRequest({ token, feature, api_path: path }); if (!authResult.ok) { ctx.fail(authResult.message || "鉴权失败"); return; } // 3. 组装 query const query = { ...ctx.query }; // 4. 转发到上游 const result = await proxy.forwardRequest({ api_path: path, method: method.toUpperCase(), query, body: ctx.getBody(), headers: ctx.headers || {}, auth_ctx: authResult.context, }); // 5. 根据上游 Success 字段决定响应方式 const upstream = result.data; if (upstream && upstream.Code === 200) { ctx.success(upstream); } else { ctx.fail(upstream && upstream.Text ? upstream.Text : "上游请求失败", upstream); } }; } } return routes; } module.exports = { buildProxyRoutes };