socket拼接url时, 增加demo注释说明

This commit is contained in:
wkj 2024-04-25 20:03:18 +08:00
parent dfe86166c8
commit a8d4e25e9c
2 changed files with 155 additions and 73 deletions

View File

@ -27,20 +27,32 @@ function concat(...paths) {
}
async function startup(path, connector, omitWatchers, omitTimers, routine) {
const serverConfiguration = require((0, path_1.join)(path, 'lib', 'configuration', 'server')).default;
const corsHeaders = ['Content-Type', 'Content-Length', 'Authorization', 'Accept', 'X-Requested-With', 'oak-cxt', 'oak-aspect'];
const corsHeaders = [
'Content-Type',
'Content-Length',
'Authorization',
'Accept',
'X-Requested-With',
'oak-cxt',
'oak-aspect',
];
const corsMethods = ['PUT', 'POST', 'GET', 'DELETE', 'OPTIONS'];
const koa = new koa_1.default();
// socket
const httpServer = (0, http_1.createServer)(koa.callback());
const socketOption = {
path: connector.getSubscribeRouter(),
cors: process.env.NODE_ENV === 'development' ? {
origin: '*',
allowedHeaders: corsHeaders,
} : (serverConfiguration.cors ? {
origin: serverConfiguration.cors.origin,
allowedHeaders: serverConfiguration.cors.headers,
} : undefined),
cors: process.env.NODE_ENV === 'development'
? {
origin: '*',
allowedHeaders: corsHeaders,
}
: serverConfiguration.cors
? {
origin: serverConfiguration.cors.origin,
allowedHeaders: serverConfiguration.cors.headers,
}
: undefined,
};
const io = new socket_io_1.Server(httpServer, socketOption);
const clusterInfo = (0, oak_backend_base_1.getClusterInfo)();
@ -73,7 +85,10 @@ async function startup(path, connector, omitWatchers, omitTimers, routine) {
catch (err) {
console.error(err);
const { request } = ctx;
const exception = err instanceof types_1.OakException ? err : new types_1.OakException(serverConfiguration?.internalExceptionMask || ExceptionMask);
const exception = err instanceof types_1.OakException
? err
: new types_1.OakException(serverConfiguration?.internalExceptionMask ||
ExceptionMask);
const { body } = connector.serializeException(exception, request.headers, request.body);
ctx.response.body = body;
return;
@ -123,7 +138,7 @@ async function startup(path, connector, omitWatchers, omitTimers, routine) {
});
// 桥接访问外部资源的入口
router.get(connector.getBridgeRouter(), async (ctx) => {
const { request: { querystring }, response } = ctx;
const { request: { querystring }, response, } = ctx;
const { url, headers } = connector.parseBridgeRequestQuery(querystring);
// headers待处理
const res = await fetch(url);
@ -144,7 +159,6 @@ async function startup(path, connector, omitWatchers, omitTimers, routine) {
if (nginx.port) {
url += `:${nginx.port}`;
}
// url = concat(url, `/${nginx.socketPath}`);
}
else if (clusterInfo.usingCluster) {
url += `:${process.env.PM2_PORT || 8080}`;
@ -153,12 +167,21 @@ async function startup(path, connector, omitWatchers, omitTimers, routine) {
url += `:${port}`;
}
url = concat(url, DATA_SUBSCRIBER_NAMESPACE);
// 配置nginx的socketPath 需加在path上
// Example:
// import { io } from "socket.io-client";
// const socket = io('https://example.com/order', {
// path: '/my-custom-path/',
// });
// the Socket instance is attached to the "order" Namespace
// the HTTP requests will look like: GET https://example.com/my-custom-path/?EIO=4&transport=polling&t=ML4jUwU
// 文档 https://socket.io/docs/v4/client-options/
router.get(connector.getSubscribePointRouter(), async (ctx) => {
const { response } = ctx;
response.body = {
url,
path: nginx?.socketPath ? `/${nginx.socketPath}` : '' + connector.getSubscribeRouter(),
path: nginx?.socketPath
? `/${nginx.socketPath}`
: '' + connector.getSubscribeRouter(),
};
return;
});

View File

@ -37,10 +37,21 @@ export async function startup<ED extends EntityDict & BaseEntityDict, FrontCxt e
omitTimers?: boolean,
routine?: (context: AsyncContext<EntityDict & BaseEntityDict>) => Promise<void>,
) {
const serverConfiguration: ServerConfiguration = require(
join(path, 'lib', 'configuration', 'server')
).default;
const corsHeaders = ['Content-Type', 'Content-Length', 'Authorization', 'Accept', 'X-Requested-With', 'oak-cxt', 'oak-aspect'];
const serverConfiguration: ServerConfiguration = require(join(
path,
'lib',
'configuration',
'server'
)).default;
const corsHeaders = [
'Content-Type',
'Content-Length',
'Authorization',
'Accept',
'X-Requested-With',
'oak-cxt',
'oak-aspect',
];
const corsMethods = ['PUT', 'POST', 'GET', 'DELETE', 'OPTIONS'];
const koa = new Koa();
@ -48,13 +59,18 @@ export async function startup<ED extends EntityDict & BaseEntityDict, FrontCxt e
const httpServer = createServer(koa.callback());
const socketOption: Partial<ServerOptions> = {
path: connector.getSubscribeRouter(),
cors: process.env.NODE_ENV === 'development' ? {
origin: '*',
allowedHeaders: corsHeaders,
} : (serverConfiguration.cors ? {
origin: serverConfiguration.cors.origin,
allowedHeaders: serverConfiguration.cors.headers,
} : undefined),
cors:
process.env.NODE_ENV === 'development'
? {
origin: '*',
allowedHeaders: corsHeaders,
}
: serverConfiguration.cors
? {
origin: serverConfiguration.cors.origin,
allowedHeaders: serverConfiguration.cors.headers,
}
: undefined,
};
const io = new Server(httpServer, socketOption);
const clusterInfo = getClusterInfo();
@ -64,14 +80,20 @@ export async function startup<ED extends EntityDict & BaseEntityDict, FrontCxt e
// https://socket.io/zh-CN/docs/v4/pm2/
io.adapter(createAdapter());
setupWorker(io);
console.log(`以集群模式启动,实例总数『${clusterInfo.instanceCount}』,当前实例号『${clusterInfo.instanceId}`);
}
else {
console.log(
`以集群模式启动,实例总数『${clusterInfo.instanceCount}』,当前实例号『${clusterInfo.instanceId}`
);
} else {
console.log('以单实例模式启动');
}
const appLoader = clusterInfo.usingCluster
? new ClusterAppLoader(path, io.of(DATA_SUBSCRIBER_NAMESPACE), io.of(SERVER_SUBSCRIBER_NAMESPACE), connector.getSubscribeRouter())
const appLoader = clusterInfo.usingCluster
? new ClusterAppLoader(
path,
io.of(DATA_SUBSCRIBER_NAMESPACE),
io.of(SERVER_SUBSCRIBER_NAMESPACE),
connector.getSubscribeRouter()
)
: new AppLoader(path, io.of(DATA_SUBSCRIBER_NAMESPACE));
await appLoader.mount();
await appLoader.execStartRoutines();
@ -85,19 +107,30 @@ export async function startup<ED extends EntityDict & BaseEntityDict, FrontCxt e
koa.use(async (ctx, next) => {
try {
await next();
}
catch (err) {
} catch (err) {
console.error(err);
const { request } = ctx;
const exception = err instanceof OakException ? err : new OakException(serverConfiguration?.internalExceptionMask || ExceptionMask);
const { body } = connector.serializeException(exception, request.headers, request.body);
const exception =
err instanceof OakException
? err
: new OakException(
serverConfiguration?.internalExceptionMask ||
ExceptionMask
);
const { body } = connector.serializeException(
exception,
request.headers,
request.body
);
ctx.response.body = body;
return;
}
})
koa.use(KoaBody({
multipart: true,
}));
});
koa.use(
KoaBody({
multipart: true,
})
);
const router = new KoaRouter();
// 如果是开发环境允许options
@ -112,15 +145,20 @@ export async function startup<ED extends EntityDict & BaseEntityDict, FrontCxt e
await next();
}
});
}
else if (serverConfiguration.cors) {
} else if (serverConfiguration.cors) {
koa.use(async (ctx, next) => {
ctx.set('Access-Control-Allow-Origin', serverConfiguration.cors!.origin!);
ctx.set(
'Access-Control-Allow-Origin',
serverConfiguration.cors!.origin!
);
ctx.set('Access-Control-Allow-Headers', [
...corsHeaders,
...(serverConfiguration.cors!.headers || []),
]);
ctx.set('Access-Control-Allow-Methods', serverConfiguration.cors!.methods || corsMethods);
ctx.set(
'Access-Control-Allow-Methods',
serverConfiguration.cors!.methods || corsMethods
);
if (ctx.method == 'OPTIONS') {
ctx.body = 200;
} else {
@ -131,17 +169,35 @@ export async function startup<ED extends EntityDict & BaseEntityDict, FrontCxt e
router.post(connector.getRouter(), async (ctx) => {
const { request } = ctx;
const { contextString, aspectName, data } = connector.parseRequest(request.headers, request.body, request.files);
const { result, opRecords, message } = await appLoader.execAspect(aspectName, request.headers, contextString, data);
const { body, headers } = await connector.serializeResult(result, opRecords, request.headers, request.body, message);
const { contextString, aspectName, data } = connector.parseRequest(
request.headers,
request.body,
request.files
);
const { result, opRecords, message } = await appLoader.execAspect(
aspectName,
request.headers,
contextString,
data
);
const { body, headers } = await connector.serializeResult(
result,
opRecords,
request.headers,
request.body,
message
);
ctx.response.body = body;
return;
});
// 桥接访问外部资源的入口
router.get(connector.getBridgeRouter(), async (ctx) => {
const { request: { querystring }, response } = ctx;
const {
request: { querystring },
response,
} = ctx;
const { url, headers } = connector.parseBridgeRequestQuery(querystring);
// headers待处理
@ -149,7 +205,7 @@ export async function startup<ED extends EntityDict & BaseEntityDict, FrontCxt e
response.body = res.body;
return;
});
// 外部socket接口
/**
* pm2 nginx socket与http同端口
@ -164,45 +220,48 @@ export async function startup<ED extends EntityDict & BaseEntityDict, FrontCxt e
if (nginx.port) {
url += `:${nginx.port}`;
}
// url = concat(url, `/${nginx.socketPath}`);
}
else if (clusterInfo.usingCluster){
} else if (clusterInfo.usingCluster) {
url += `:${process.env.PM2_PORT || 8080}`;
}
else {
} else {
url += `:${port}`;
}
url = concat(url, DATA_SUBSCRIBER_NAMESPACE);
// 配置nginx的socketPath 需加在path上
// Example:
// import { io } from "socket.io-client";
// const socket = io('https://example.com/order', {
// path: '/my-custom-path/',
// });
// the Socket instance is attached to the "order" Namespace
// the HTTP requests will look like: GET https://example.com/my-custom-path/?EIO=4&transport=polling&t=ML4jUwU
// 文档 https://socket.io/docs/v4/client-options/
router.get(connector.getSubscribePointRouter(), async (ctx) => {
const { response } = ctx;
response.body = {
url,
path: nginx?.socketPath ? `/${nginx.socketPath}` : '' + connector.getSubscribeRouter(),
path: nginx?.socketPath
? `/${nginx.socketPath}`
: '' + connector.getSubscribeRouter(),
};
return;
});
// 注入所有的endpoints
const endpoints = appLoader.getEndpoints(connector.getEndpointRouter());
endpoints.forEach(
([name, method, url, fn]) => {
router[method](url, async (ctx) => {
const { req, request, params } = ctx;
const { body, headers } = request;
try {
const result = await fn(params, headers, req, body);
ctx.response.body = result;
return;
}
catch(err) {
ctx.response.status = 500;
return;
}
});
}
);
endpoints.forEach(([name, method, url, fn]) => {
router[method](url, async (ctx) => {
const { req, request, params } = ctx;
const { body, headers } = request;
try {
const result = await fn(params, headers, req, body);
ctx.response.body = result;
return;
} catch (err) {
ctx.response.status = 500;
return;
}
});
});
router.get(connector.getEndpointRouter(), async (ctx) => {
ctx.response.body = endpoints;
});