110 lines
2.6 KiB
JavaScript
110 lines
2.6 KiB
JavaScript
import http from 'node:http';
|
|
|
|
const moduleId = 'custom-templates-core';
|
|
const port = Number.parseInt(process.env.PORT || '8787', 10);
|
|
const capabilities = ['customTemplates'];
|
|
const allowedActions = new Set([
|
|
'customTemplates:use',
|
|
'customTemplates:create',
|
|
'customTemplates:update',
|
|
'customTemplates:delete',
|
|
'customTemplates:migrate',
|
|
'customTemplates:read',
|
|
'customTemplates:list',
|
|
'customTemplates:validate',
|
|
'customTemplates:filter',
|
|
]);
|
|
|
|
function sendJson(res, statusCode, payload) {
|
|
const body = JSON.stringify(payload);
|
|
res.writeHead(statusCode, {
|
|
'Content-Type': 'application/json; charset=utf-8',
|
|
'Content-Length': Buffer.byteLength(body),
|
|
});
|
|
res.end(body);
|
|
}
|
|
|
|
function readJsonBody(req) {
|
|
return new Promise((resolve, reject) => {
|
|
let body = '';
|
|
|
|
req.on('data', (chunk) => {
|
|
body += chunk;
|
|
if (body.length > 1024 * 1024) {
|
|
req.destroy();
|
|
reject(new Error('request_body_too_large'));
|
|
}
|
|
});
|
|
|
|
req.on('end', () => {
|
|
if (!body.trim()) {
|
|
resolve({});
|
|
return;
|
|
}
|
|
|
|
try {
|
|
resolve(JSON.parse(body));
|
|
} catch {
|
|
reject(new Error('invalid_json'));
|
|
}
|
|
});
|
|
|
|
req.on('error', reject);
|
|
});
|
|
}
|
|
|
|
function sendAuthorization(res, action) {
|
|
const allowed = typeof action === 'string' && allowedActions.has(action);
|
|
sendJson(res, allowed ? 200 : 403, {
|
|
moduleId,
|
|
allowed,
|
|
action,
|
|
capabilities,
|
|
});
|
|
}
|
|
|
|
const server = http.createServer((req, res) => {
|
|
const url = new URL(req.url || '/', `http://${req.headers.host || '127.0.0.1'}`);
|
|
|
|
if (req.method === 'GET' && url.pathname === '/health') {
|
|
sendJson(res, 200, { moduleId, status: 'healthy' });
|
|
return;
|
|
}
|
|
|
|
if (req.method === 'GET' && url.pathname === '/status') {
|
|
sendJson(res, 200, {
|
|
moduleId,
|
|
status: 'authorization_contract_ready',
|
|
capabilities,
|
|
note: '此模块先承接自定义模板授权执行层;后续再迁移 CRUD、筛选和数据处理链路',
|
|
});
|
|
return;
|
|
}
|
|
|
|
if (req.method === 'GET' && url.pathname === '/capabilities') {
|
|
sendJson(res, 200, {
|
|
moduleId,
|
|
capabilities,
|
|
actions: Array.from(allowedActions),
|
|
});
|
|
return;
|
|
}
|
|
|
|
if (req.method === 'POST' && url.pathname === '/authorize') {
|
|
readJsonBody(req)
|
|
.then((body) => {
|
|
sendAuthorization(res, body.action);
|
|
})
|
|
.catch((error) => {
|
|
sendJson(res, 400, { moduleId, allowed: false, error: error.message });
|
|
});
|
|
return;
|
|
}
|
|
|
|
sendJson(res, 404, { moduleId, error: '接口不存在' });
|
|
});
|
|
|
|
server.listen(port, '0.0.0.0', () => {
|
|
console.log(`${moduleId} listening on ${port}`);
|
|
});
|