Files
wechatWeb/api/controller_custom/proxy_api.js
张成 1f4b39d576 1
2026-03-27 13:30:53 +08:00

90 lines
2.4 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
const swagger = require("../../_docs/swagger.json");
const auth = require("../service/biz_auth_verify");
const proxy = require("../service/biz_proxy_service");
function getRequestBody(ctx) {
if (ctx.request && ctx.request.body && Object.keys(ctx.request.body).length > 0) {
return ctx.request.body;
}
if (typeof ctx.getBody === "function") {
return ctx.getBody() || {};
}
return {};
}
/**
* 从请求中提取 Token
* 支持 Authorization: Bearer xxx 和 query ?token=xxx
*/
function extractToken(ctx) {
const authHeader = ctx.get("Authorization") || "";
if (authHeader.startsWith("Bearer ")) {
return authHeader.slice(7).trim();
}
return ctx.query.token || "";
}
/**
* 提取 swagger tags 第一项作为 feature 名(用于套餐功能点校验)
*/
function pickFeature(spec) {
if (spec.tags && spec.tags.length > 0) {
return spec.tags[0];
}
return null;
}
/**
* 构建转发路由表(供 framework.addRoutes 注册)
*/
function buildProxyRoutes() {
const routes = {};
for (const [path, methods] of Object.entries(swagger.paths)) {
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.status = 401;
ctx.body = { ok: false, error_code: "TOKEN_MISSING", message: "缺少 Token" };
return;
}
// 2. 鉴权Token + 用户 + 订阅 + 套餐功能点 + 接口权限 + 调用量
const feature = pickFeature(spec);
const authResult = await auth.verifyRequest({ token, feature, api_path: path });
if (!authResult.ok) {
ctx.status = 403;
ctx.body = authResult;
return;
}
// 3. 组装 query去掉 token 参数,避免泄露)
const query = { ...ctx.query };
delete query.token;
// 4. 转发到上游
const result = await proxy.forwardRequest({
api_path: path,
method: method.toUpperCase(),
query,
body: getRequestBody(ctx),
headers: ctx.headers || {},
auth_ctx: authResult.context,
});
// 5. 原样返回上游响应
ctx.status = result.status;
ctx.body = result.data;
};
}
}
return routes;
}
module.exports = { buildProxyRoutes };