feat: 适配新connector定义,支持ExposeHeaders,connector的自定义Aspect(用于实现前后台的connector初始化逻辑)

This commit is contained in:
Pan Qiancheng 2025-12-17 15:04:57 +08:00
parent 22289f04d4
commit 09d14be5e7
2 changed files with 84 additions and 13 deletions

View File

@ -236,6 +236,10 @@ async function startup(path, connector, omitWatchers, omitTimers, routine) {
ctx.set('Access-Control-Allow-Origin', '*'); ctx.set('Access-Control-Allow-Origin', '*');
ctx.set('Access-Control-Allow-Headers', corsHeaders.concat(connector.getCorsHeader())); ctx.set('Access-Control-Allow-Headers', corsHeaders.concat(connector.getCorsHeader()));
ctx.set('Access-Control-Allow-Methods', corsMethods); ctx.set('Access-Control-Allow-Methods', corsMethods);
if (connector.getCorsExposeHeaders) {
const exposeHeaders = connector.getCorsExposeHeaders();
ctx.set('Access-Control-Expose-Headers', exposeHeaders);
}
if (ctx.method == 'OPTIONS') { if (ctx.method == 'OPTIONS') {
ctx.body = 200; ctx.body = 200;
} }
@ -269,12 +273,39 @@ async function startup(path, connector, omitWatchers, omitTimers, routine) {
} }
}); });
} }
const connectorCustomAspects = connector.registerCustomAspect ? connector.registerCustomAspect() : null;
router.post(connector.getRouter(), async (ctx) => { router.post(connector.getRouter(), async (ctx) => {
const { request } = ctx; const { request } = ctx;
const { contextString, aspectName, data } = connector.parseRequest(request.headers, request.body, request.files); const { contextString, aspectName, data } = await connector.parseRequest(request.headers, request.body, request.files);
const { result, opRecords, message } = await appLoader.execAspect(aspectName, request.headers, contextString, data); let result;
let opRecords = [];
let message = undefined;
if (connectorCustomAspects &&
connectorCustomAspects.findIndex(a => a.name === aspectName) >= 0) {
// 自定义aspect处理
console.log(`调用Connector自定义Aspect: ${aspectName}`);
const aspect = connectorCustomAspects.find(a => a.name === aspectName);
const res = await aspect.handler({
headers: request.headers,
contextString,
params: data,
});
result = res.result;
opRecords = res.opRecords || [];
message = res.message;
}
else {
const res = await appLoader.execAspect(aspectName, request.headers, contextString, data);
result = res.result;
opRecords = res.opRecords || [];
message = res.message;
}
const { body, headers } = await connector.serializeResult(result, opRecords, request.headers, request.body, message); const { body, headers } = await connector.serializeResult(result, opRecords, request.headers, request.body, message);
ctx.response.body = body; ctx.response.body = body;
// headers 要拼上
Object.keys(headers || {}).forEach(key => {
ctx.set(key, headers?.[key]);
});
return; return;
}); });
// 桥接访问外部资源的入口 // 桥接访问外部资源的入口

View File

@ -9,7 +9,7 @@ import KoaBody from 'koa-body';
import { AppLoader, getClusterInfo, ClusterAppLoader } from 'oak-backend-base'; import { AppLoader, getClusterInfo, ClusterAppLoader } from 'oak-backend-base';
import { BackendRuntimeContext } from 'oak-frontend-base/lib/context/BackendRuntimeContext'; import { BackendRuntimeContext } from 'oak-frontend-base/lib/context/BackendRuntimeContext';
import { OakException, Connector, EntityDict, ClusterInfo } from 'oak-domain/lib/types'; import { OakException, Connector, EntityDict, ClusterInfo, OpRecord } from 'oak-domain/lib/types';
import { EntityDict as BaseEntityDict } from 'oak-domain/lib/base-app-domain'; import { EntityDict as BaseEntityDict } from 'oak-domain/lib/base-app-domain';
import { AsyncRowStore, AsyncContext } from 'oak-domain/lib/store/AsyncRowStore'; import { AsyncRowStore, AsyncContext } from 'oak-domain/lib/store/AsyncRowStore';
import { SyncContext } from 'oak-domain/lib/store/SyncRowStore'; import { SyncContext } from 'oak-domain/lib/store/SyncRowStore';
@ -260,11 +260,13 @@ export async function startup<ED extends EntityDict & BaseEntityDict, FrontCxt e
return; return;
} }
}); });
koa.use( koa.use(
KoaBody(Object.assign({ KoaBody(Object.assign({
multipart: true, multipart: true,
}, serverConfiguration.koaBody)) }, serverConfiguration.koaBody))
); );
// 注册自定义中间件 // 注册自定义中间件
if (serverConfiguration.middleware) { if (serverConfiguration.middleware) {
if (Array.isArray(serverConfiguration.middleware)) { if (Array.isArray(serverConfiguration.middleware)) {
@ -290,6 +292,10 @@ export async function startup<ED extends EntityDict & BaseEntityDict, FrontCxt e
ctx.set('Access-Control-Allow-Origin', '*'); ctx.set('Access-Control-Allow-Origin', '*');
ctx.set('Access-Control-Allow-Headers', corsHeaders.concat(connector.getCorsHeader())); ctx.set('Access-Control-Allow-Headers', corsHeaders.concat(connector.getCorsHeader()));
ctx.set('Access-Control-Allow-Methods', corsMethods); ctx.set('Access-Control-Allow-Methods', corsMethods);
if (connector.getCorsExposeHeaders) {
const exposeHeaders = connector.getCorsExposeHeaders();
ctx.set('Access-Control-Expose-Headers', exposeHeaders);
}
if (ctx.method == 'OPTIONS') { if (ctx.method == 'OPTIONS') {
ctx.body = 200; ctx.body = 200;
} else { } else {
@ -328,20 +334,48 @@ export async function startup<ED extends EntityDict & BaseEntityDict, FrontCxt e
}); });
} }
const connectorCustomAspects = connector.registerCustomAspect ? connector.registerCustomAspect() : null;
router.post(connector.getRouter(), async (ctx) => { router.post(connector.getRouter(), async (ctx) => {
const { request } = ctx; const { request } = ctx;
const { contextString, aspectName, data } = connector.parseRequest( const { contextString, aspectName, data } = await connector.parseRequest(
request.headers, request.headers,
request.body, request.body,
request.files request.files
); );
const { result, opRecords, message } = await appLoader.execAspect( let result: any;
aspectName, let opRecords: OpRecord<ED>[] = [];
request.headers, let message: string | undefined = undefined;
contextString,
data if (connectorCustomAspects &&
); connectorCustomAspects.findIndex(a => a.name === aspectName) >= 0
) {
// 自定义aspect处理
console.log(`调用Connector自定义Aspect: ${aspectName}`);
const aspect = connectorCustomAspects!.find(a => a.name === aspectName)!;
const res = await aspect.handler(
{
headers: request.headers,
contextString,
params: data,
}
);
result = res.result;
opRecords = res.opRecords || [];
message = res.message;
} else {
const res = await appLoader.execAspect(
aspectName,
request.headers,
contextString,
data
);
result = res.result;
opRecords = res.opRecords || [];
message = res.message;
}
const { body, headers } = await connector.serializeResult( const { body, headers } = await connector.serializeResult(
result, result,
opRecords, opRecords,
@ -350,6 +384,12 @@ export async function startup<ED extends EntityDict & BaseEntityDict, FrontCxt e
message message
); );
ctx.response.body = body; ctx.response.body = body;
// headers 要拼上
Object.keys(headers || {}).forEach(key => {
ctx.set(key, headers?.[key])
})
return; return;
}); });
@ -519,15 +559,15 @@ export async function startup<ED extends EntityDict & BaseEntityDict, FrontCxt e
return; return;
} }
shutdownStarted = true; shutdownStarted = true;
console.log(`\n收到 ${signal} 信号,准备关闭服务器...`); console.log(`\n收到 ${signal} 信号,准备关闭服务器...`);
// 移除所有信号处理器,防止重复触发 // 移除所有信号处理器,防止重复触发
process.removeAllListeners('SIGINT'); process.removeAllListeners('SIGINT');
process.removeAllListeners('SIGTERM'); process.removeAllListeners('SIGTERM');
process.removeAllListeners('SIGQUIT'); process.removeAllListeners('SIGQUIT');
process.removeAllListeners('SIGHUP'); process.removeAllListeners('SIGHUP');
try { try {
await shutdown(); await shutdown();
process.exit(0); process.exit(0);