@enkaku/server 0.12.2 → 0.13.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/access-control.d.ts +8 -1
- package/lib/access-control.d.ts.map +1 -1
- package/lib/access-control.js +31 -5
- package/lib/error.d.ts +10 -0
- package/lib/error.d.ts.map +1 -1
- package/lib/handlers/channel.d.ts.map +1 -1
- package/lib/handlers/channel.js +26 -4
- package/lib/handlers/event.d.ts.map +1 -1
- package/lib/handlers/event.js +13 -4
- package/lib/handlers/request.d.ts.map +1 -1
- package/lib/handlers/request.js +2 -1
- package/lib/handlers/stream.d.ts.map +1 -1
- package/lib/handlers/stream.js +17 -2
- package/lib/index.d.ts +3 -1
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +3 -1
- package/lib/limits.d.ts +26 -0
- package/lib/limits.d.ts.map +1 -0
- package/lib/limits.js +56 -0
- package/lib/server.d.ts +10 -3
- package/lib/server.d.ts.map +1 -1
- package/lib/server.js +215 -37
- package/lib/types.d.ts +6 -2
- package/lib/types.d.ts.map +1 -1
- package/lib/utils.d.ts.map +1 -1
- package/lib/utils.js +25 -8
- package/package.json +10 -10
package/lib/access-control.d.ts
CHANGED
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
import type { SignedToken } from '@enkaku/token';
|
|
2
|
-
export type
|
|
2
|
+
export type EncryptionPolicy = 'required' | 'optional' | 'none';
|
|
3
|
+
export type ProcedureAccessConfig = {
|
|
4
|
+
allow?: boolean | Array<string>;
|
|
5
|
+
encryption?: EncryptionPolicy;
|
|
6
|
+
};
|
|
7
|
+
export type ProcedureAccessValue = boolean | Array<string> | ProcedureAccessConfig;
|
|
8
|
+
export type ProcedureAccessRecord = Record<string, ProcedureAccessValue>;
|
|
9
|
+
export declare function resolveEncryptionPolicy(procedure: string, record: ProcedureAccessRecord | undefined, globalPolicy: EncryptionPolicy): EncryptionPolicy;
|
|
3
10
|
export type ProcedureAccessPayload = {
|
|
4
11
|
iss: string;
|
|
5
12
|
sub?: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"access-control.d.ts","sourceRoot":"","sources":["../src/access-control.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AAEhD,MAAM,MAAM,
|
|
1
|
+
{"version":3,"file":"access-control.d.ts","sourceRoot":"","sources":["../src/access-control.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AAEhD,MAAM,MAAM,gBAAgB,GAAG,UAAU,GAAG,UAAU,GAAG,MAAM,CAAA;AAE/D,MAAM,MAAM,qBAAqB,GAAG;IAClC,KAAK,CAAC,EAAE,OAAO,GAAG,KAAK,CAAC,MAAM,CAAC,CAAA;IAC/B,UAAU,CAAC,EAAE,gBAAgB,CAAA;CAC9B,CAAA;AAED,MAAM,MAAM,oBAAoB,GAAG,OAAO,GAAG,KAAK,CAAC,MAAM,CAAC,GAAG,qBAAqB,CAAA;AAElF,MAAM,MAAM,qBAAqB,GAAG,MAAM,CAAC,MAAM,EAAE,oBAAoB,CAAC,CAAA;AAgBxE,wBAAgB,uBAAuB,CACrC,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,qBAAqB,GAAG,SAAS,EACzC,YAAY,EAAE,gBAAgB,GAC7B,gBAAgB,CAYlB;AAED,MAAM,MAAM,sBAAsB,GAAG;IACnC,GAAG,EAAE,MAAM,CAAA;IACX,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,GAAG,CAAC,EAAE,MAAM,CAAA;CACb,CAAA;AAED,wBAAsB,oBAAoB,CACxC,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,qBAAqB,EAC7B,KAAK,EAAE,WAAW,CAAC,sBAAsB,CAAC,EAC1C,MAAM,CAAC,EAAE,MAAM,GACd,OAAO,CAAC,IAAI,CAAC,CAkCf;AAED,wBAAsB,gBAAgB,CACpC,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,qBAAqB,EAC7B,KAAK,EAAE,WAAW,EAClB,MAAM,CAAC,EAAE,MAAM,GACd,OAAO,CAAC,IAAI,CAAC,CA4Bf"}
|
package/lib/access-control.js
CHANGED
|
@@ -1,23 +1,49 @@
|
|
|
1
1
|
import { assertNonExpired, checkCapability, hasPartsMatch } from '@enkaku/capability';
|
|
2
|
+
function getAllowValue(access) {
|
|
3
|
+
if (typeof access === 'boolean' || Array.isArray(access)) {
|
|
4
|
+
return access;
|
|
5
|
+
}
|
|
6
|
+
return access.allow ?? false;
|
|
7
|
+
}
|
|
8
|
+
function getEncryptionPolicy(access) {
|
|
9
|
+
if (typeof access === 'boolean' || Array.isArray(access)) {
|
|
10
|
+
return undefined;
|
|
11
|
+
}
|
|
12
|
+
return access.encryption;
|
|
13
|
+
}
|
|
14
|
+
export function resolveEncryptionPolicy(procedure, record, globalPolicy) {
|
|
15
|
+
if (record != null) {
|
|
16
|
+
for (const [pattern, accessValue] of Object.entries(record)){
|
|
17
|
+
if (hasPartsMatch(procedure, pattern)) {
|
|
18
|
+
const procedurePolicy = getEncryptionPolicy(accessValue);
|
|
19
|
+
if (procedurePolicy != null) {
|
|
20
|
+
return procedurePolicy;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
return globalPolicy;
|
|
26
|
+
}
|
|
2
27
|
export async function checkProcedureAccess(serverID, record, token, atTime) {
|
|
3
28
|
const payload = token.payload;
|
|
4
29
|
if (payload.prc == null) {
|
|
5
30
|
throw new Error('No procedure to check');
|
|
6
31
|
}
|
|
7
|
-
for (const [procedure,
|
|
32
|
+
for (const [procedure, accessValue] of Object.entries(record)){
|
|
8
33
|
if (hasPartsMatch(payload.prc, procedure)) {
|
|
9
|
-
|
|
34
|
+
const allow = getAllowValue(accessValue);
|
|
35
|
+
if (allow === true) {
|
|
10
36
|
// Procedure can be publicly accessed
|
|
11
37
|
return;
|
|
12
38
|
}
|
|
13
|
-
if (
|
|
39
|
+
if (allow === false) {
|
|
14
40
|
continue;
|
|
15
41
|
}
|
|
16
|
-
if (
|
|
42
|
+
if (allow.includes(payload.iss)) {
|
|
17
43
|
// Issuer is allowed directly
|
|
18
44
|
return;
|
|
19
45
|
}
|
|
20
|
-
if (payload.sub == null || !
|
|
46
|
+
if (payload.sub == null || !allow.includes(payload.sub)) {
|
|
21
47
|
continue;
|
|
22
48
|
}
|
|
23
49
|
try {
|
package/lib/error.d.ts
CHANGED
|
@@ -1,4 +1,14 @@
|
|
|
1
1
|
import type { ErrorReplyPayload } from '@enkaku/protocol';
|
|
2
|
+
/**
|
|
3
|
+
* Error codes:
|
|
4
|
+
* - EK01: Handler execution failed
|
|
5
|
+
* - EK02: Access denied (authorization failure)
|
|
6
|
+
* - EK03: Server controller limit reached
|
|
7
|
+
* - EK04: Server handler concurrency limit reached
|
|
8
|
+
* - EK05: Request timeout (controller expired)
|
|
9
|
+
* - EK06: Message exceeds maximum size
|
|
10
|
+
* - EK07: Encryption required but message is not encrypted
|
|
11
|
+
*/
|
|
2
12
|
export type HandlerErrorParams<Code extends string = string, Data extends Record<string, unknown> = Record<string, unknown>> = {
|
|
3
13
|
cause?: unknown;
|
|
4
14
|
code: Code;
|
package/lib/error.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"error.d.ts","sourceRoot":"","sources":["../src/error.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAA;AAEzD,MAAM,MAAM,kBAAkB,CAC5B,IAAI,SAAS,MAAM,GAAG,MAAM,EAC5B,IAAI,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,IAC5D;IACF,KAAK,CAAC,EAAE,OAAO,CAAA;IACf,IAAI,EAAE,IAAI,CAAA;IACV,IAAI,CAAC,EAAE,IAAI,CAAA;IACX,OAAO,CAAC,EAAE,MAAM,CAAA;CACjB,CAAA;AAED,qBAAa,YAAY,CACvB,IAAI,SAAS,MAAM,EACnB,IAAI,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAC9D,SAAQ,KAAK;;IACb,MAAM,CAAC,IAAI,CAAC,IAAI,SAAS,MAAM,EAAE,IAAI,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7F,KAAK,EAAE,OAAO,EACd,MAAM,EAAE,kBAAkB,CAAC,IAAI,EAAE,IAAI,CAAC,GACrC,YAAY,CAAC,IAAI,EAAE,IAAI,CAAC;gBAWf,MAAM,EAAE,kBAAkB,CAAC,IAAI,EAAE,IAAI,CAAC;IAOlD,IAAI,IAAI,IAAI,IAAI,CAEf;IAED,IAAI,IAAI,IAAI,IAAI,CAEf;IAED,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,iBAAiB,CAAC,IAAI,EAAE,IAAI,CAAC;CAStD"}
|
|
1
|
+
{"version":3,"file":"error.d.ts","sourceRoot":"","sources":["../src/error.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAA;AAEzD;;;;;;;;;GASG;AAEH,MAAM,MAAM,kBAAkB,CAC5B,IAAI,SAAS,MAAM,GAAG,MAAM,EAC5B,IAAI,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,IAC5D;IACF,KAAK,CAAC,EAAE,OAAO,CAAA;IACf,IAAI,EAAE,IAAI,CAAA;IACV,IAAI,CAAC,EAAE,IAAI,CAAA;IACX,OAAO,CAAC,EAAE,MAAM,CAAA;CACjB,CAAA;AAED,qBAAa,YAAY,CACvB,IAAI,SAAS,MAAM,EACnB,IAAI,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAC9D,SAAQ,KAAK;;IACb,MAAM,CAAC,IAAI,CAAC,IAAI,SAAS,MAAM,EAAE,IAAI,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7F,KAAK,EAAE,OAAO,EACd,MAAM,EAAE,kBAAkB,CAAC,IAAI,EAAE,IAAI,CAAC,GACrC,YAAY,CAAC,IAAI,EAAE,IAAI,CAAC;gBAWf,MAAM,EAAE,kBAAkB,CAAC,IAAI,EAAE,IAAI,CAAC;IAOlD,IAAI,IAAI,IAAI,IAAI,CAEf;IAED,IAAI,IAAI,IAAI,IAAI,CAEf;IAED,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,iBAAiB,CAAC,IAAI,EAAE,IAAI,CAAC;CAStD"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"channel.d.ts","sourceRoot":"","sources":["../../src/handlers/channel.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAEV,gBAAgB,EAChB,aAAa,EACb,kBAAkB,EACnB,MAAM,kBAAkB,CAAA;AAGzB,OAAO,KAAK,EAGV,cAAc,EAGf,MAAM,aAAa,CAAA;AAGpB,MAAM,MAAM,gBAAgB,CAC1B,QAAQ,SAAS,kBAAkB,EACnC,SAAS,SAAS,MAAM,QAAQ,GAAG,MAAM,GAAG,MAAM,QAAQ,GAAG,MAAM,IACjE,aAAa,CAAC,gBAAgB,CAAC,SAAS,EAAE,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC,CAAA;AAEnE,wBAAgB,aAAa,CAC3B,QAAQ,SAAS,kBAAkB,EACnC,SAAS,SAAS,MAAM,QAAQ,GAAG,MAAM,EAEzC,GAAG,EAAE,cAAc,CAAC,QAAQ,CAAC,EAC7B,GAAG,EAAE,gBAAgB,CAAC,QAAQ,EAAE,SAAS,CAAC,GACzC,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"channel.d.ts","sourceRoot":"","sources":["../../src/handlers/channel.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAEV,gBAAgB,EAChB,aAAa,EACb,kBAAkB,EACnB,MAAM,kBAAkB,CAAA;AAGzB,OAAO,KAAK,EAGV,cAAc,EAGf,MAAM,aAAa,CAAA;AAGpB,MAAM,MAAM,gBAAgB,CAC1B,QAAQ,SAAS,kBAAkB,EACnC,SAAS,SAAS,MAAM,QAAQ,GAAG,MAAM,GAAG,MAAM,QAAQ,GAAG,MAAM,IACjE,aAAa,CAAC,gBAAgB,CAAC,SAAS,EAAE,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC,CAAA;AAEnE,wBAAgB,aAAa,CAC3B,QAAQ,SAAS,kBAAkB,EACnC,SAAS,SAAS,MAAM,QAAQ,GAAG,MAAM,EAEzC,GAAG,EAAE,cAAc,CAAC,QAAQ,CAAC,EAC7B,GAAG,EAAE,gBAAgB,CAAC,QAAQ,EAAE,SAAS,CAAC,GACzC,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC,CAsEvB"}
|
package/lib/handlers/channel.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { createPipe, writeTo } from '@enkaku/stream';
|
|
1
|
+
import { createPipe, tap, writeTo } from '@enkaku/stream';
|
|
2
2
|
import { executeHandler } from '../utils.js';
|
|
3
3
|
export function handleChannel(ctx, msg) {
|
|
4
4
|
const handler = ctx.handlers[msg.payload.prc];
|
|
@@ -22,19 +22,41 @@ export function handleChannel(ctx, msg) {
|
|
|
22
22
|
if (controller.signal.aborted) {
|
|
23
23
|
return;
|
|
24
24
|
}
|
|
25
|
+
ctx.logger.trace('send value to channel {procedure} with ID {rid}', {
|
|
26
|
+
procedure: msg.payload.prc,
|
|
27
|
+
rid: msg.payload.rid
|
|
28
|
+
});
|
|
25
29
|
await ctx.send({
|
|
26
30
|
typ: 'receive',
|
|
27
31
|
rid: msg.payload.rid,
|
|
28
32
|
val
|
|
29
33
|
});
|
|
30
34
|
}));
|
|
35
|
+
const readable = sendStream.readable.pipeThrough(tap((value)=>{
|
|
36
|
+
ctx.logger.trace('received value from channel {procedure} with ID {rid}', {
|
|
37
|
+
procedure: msg.payload.prc,
|
|
38
|
+
rid: msg.payload.rid,
|
|
39
|
+
value
|
|
40
|
+
});
|
|
41
|
+
}));
|
|
31
42
|
const handlerContext = {
|
|
32
43
|
message: msg,
|
|
33
44
|
param: msg.payload.prm,
|
|
34
|
-
readable
|
|
45
|
+
readable,
|
|
35
46
|
signal: controller.signal,
|
|
36
47
|
writable: receiveStream.writable
|
|
37
48
|
};
|
|
38
|
-
//
|
|
39
|
-
return
|
|
49
|
+
// Wrap execution to ensure stream cleanup on handler crash
|
|
50
|
+
return (async ()=>{
|
|
51
|
+
try {
|
|
52
|
+
// @ts-expect-error context and handler types
|
|
53
|
+
await executeHandler(ctx, msg.payload, ()=>handler(handlerContext));
|
|
54
|
+
} finally{
|
|
55
|
+
try {
|
|
56
|
+
await receiveStream.writable.close();
|
|
57
|
+
} catch {
|
|
58
|
+
// Stream may already be closed
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
})();
|
|
40
62
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"event.d.ts","sourceRoot":"","sources":["../../src/handlers/event.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,cAAc,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAA;
|
|
1
|
+
{"version":3,"file":"event.d.ts","sourceRoot":"","sources":["../../src/handlers/event.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,cAAc,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAA;AAGzF,OAAO,KAAK,EAAqC,cAAc,EAAE,MAAM,aAAa,CAAA;AAEpF,MAAM,MAAM,cAAc,CACxB,QAAQ,SAAS,kBAAkB,EACnC,SAAS,SAAS,MAAM,QAAQ,GAAG,MAAM,GAAG,MAAM,QAAQ,GAAG,MAAM,IACjE,aAAa,CAAC,cAAc,CAAC,SAAS,EAAE,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC,CAAA;AAEjE,wBAAgB,WAAW,CACzB,QAAQ,SAAS,kBAAkB,EACnC,SAAS,SAAS,MAAM,QAAQ,GAAG,MAAM,EACzC,GAAG,EAAE,cAAc,CAAC,QAAQ,CAAC,EAAE,GAAG,EAAE,cAAc,CAAC,QAAQ,EAAE,SAAS,CAAC,GAAG,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC,CA2BhG"}
|
package/lib/handlers/event.js
CHANGED
|
@@ -1,21 +1,30 @@
|
|
|
1
1
|
import { toPromise } from '@enkaku/async';
|
|
2
|
+
import { HandlerError } from '../error.js';
|
|
2
3
|
export function handleEvent(ctx, msg) {
|
|
3
4
|
const handler = ctx.handlers[msg.payload.prc];
|
|
4
5
|
if (handler == null) {
|
|
5
6
|
return new Error(`No handler for procedure: ${msg.payload.prc}`);
|
|
6
7
|
}
|
|
7
8
|
ctx.logger.trace('handle event {procedure}', {
|
|
8
|
-
procedure: msg.payload.prc
|
|
9
|
+
procedure: msg.payload.prc,
|
|
10
|
+
data: msg.payload.data
|
|
9
11
|
});
|
|
10
12
|
const handlerContext = {
|
|
11
13
|
message: msg,
|
|
12
14
|
data: msg.payload.data
|
|
13
15
|
};
|
|
14
16
|
return toPromise(()=>handler(handlerContext)).catch((cause)=>{
|
|
17
|
+
const error = HandlerError.from(cause, {
|
|
18
|
+
code: 'EK01',
|
|
19
|
+
message: cause.message ?? 'Handler execution failed'
|
|
20
|
+
});
|
|
21
|
+
ctx.logger.debug('handler error for event {procedure}', {
|
|
22
|
+
procedure: msg.payload.prc,
|
|
23
|
+
data: msg.payload.data,
|
|
24
|
+
error
|
|
25
|
+
});
|
|
15
26
|
ctx.events.emit('handlerError', {
|
|
16
|
-
error
|
|
17
|
-
cause
|
|
18
|
-
}),
|
|
27
|
+
error,
|
|
19
28
|
payload: msg.payload
|
|
20
29
|
});
|
|
21
30
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"request.d.ts","sourceRoot":"","sources":["../../src/handlers/request.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAA;AAE3F,OAAO,KAAK,EAAE,cAAc,EAAkB,MAAM,aAAa,CAAA;AAGjE,MAAM,MAAM,gBAAgB,CAC1B,QAAQ,SAAS,kBAAkB,EACnC,SAAS,SAAS,MAAM,QAAQ,GAAG,MAAM,GAAG,MAAM,QAAQ,GAAG,MAAM,IACjE,aAAa,CAAC,gBAAgB,CAAC,SAAS,EAAE,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC,CAAA;AAEnE,wBAAgB,aAAa,CAC3B,QAAQ,SAAS,kBAAkB,EACnC,SAAS,SAAS,MAAM,QAAQ,GAAG,MAAM,EAEzC,GAAG,EAAE,cAAc,CAAC,QAAQ,CAAC,EAC7B,GAAG,EAAE,gBAAgB,CAAC,QAAQ,EAAE,SAAS,CAAC,GACzC,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"request.d.ts","sourceRoot":"","sources":["../../src/handlers/request.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAA;AAE3F,OAAO,KAAK,EAAE,cAAc,EAAkB,MAAM,aAAa,CAAA;AAGjE,MAAM,MAAM,gBAAgB,CAC1B,QAAQ,SAAS,kBAAkB,EACnC,SAAS,SAAS,MAAM,QAAQ,GAAG,MAAM,GAAG,MAAM,QAAQ,GAAG,MAAM,IACjE,aAAa,CAAC,gBAAgB,CAAC,SAAS,EAAE,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC,CAAA;AAEnE,wBAAgB,aAAa,CAC3B,QAAQ,SAAS,kBAAkB,EACnC,SAAS,SAAS,MAAM,QAAQ,GAAG,MAAM,EAEzC,GAAG,EAAE,cAAc,CAAC,QAAQ,CAAC,EAC7B,GAAG,EAAE,gBAAgB,CAAC,QAAQ,EAAE,SAAS,CAAC,GACzC,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC,CAsBvB"}
|
package/lib/handlers/request.js
CHANGED
|
@@ -6,7 +6,8 @@ export function handleRequest(ctx, msg) {
|
|
|
6
6
|
}
|
|
7
7
|
ctx.logger.trace('handle request {procedure} with ID {rid}', {
|
|
8
8
|
procedure: msg.payload.prc,
|
|
9
|
-
rid: msg.payload.rid
|
|
9
|
+
rid: msg.payload.rid,
|
|
10
|
+
param: msg.payload.prm
|
|
10
11
|
});
|
|
11
12
|
const controller = new AbortController();
|
|
12
13
|
ctx.controllers[msg.payload.rid] = controller;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stream.d.ts","sourceRoot":"","sources":["../../src/handlers/stream.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAEV,aAAa,EACb,kBAAkB,EAClB,eAAe,EAChB,MAAM,kBAAkB,CAAA;AAGzB,OAAO,KAAK,EAAE,cAAc,EAA8B,MAAM,aAAa,CAAA;AAG7E,MAAM,MAAM,eAAe,CACzB,QAAQ,SAAS,kBAAkB,EACnC,SAAS,SAAS,MAAM,QAAQ,GAAG,MAAM,GAAG,MAAM,QAAQ,GAAG,MAAM,IACjE,aAAa,CAAC,eAAe,CAAC,SAAS,EAAE,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC,CAAA;AAElE,wBAAgB,YAAY,CAC1B,QAAQ,SAAS,kBAAkB,EACnC,SAAS,SAAS,MAAM,QAAQ,GAAG,MAAM,EACzC,GAAG,EAAE,cAAc,CAAC,QAAQ,CAAC,EAAE,GAAG,EAAE,eAAe,CAAC,QAAQ,EAAE,SAAS,CAAC,GAAG,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"stream.d.ts","sourceRoot":"","sources":["../../src/handlers/stream.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAEV,aAAa,EACb,kBAAkB,EAClB,eAAe,EAChB,MAAM,kBAAkB,CAAA;AAGzB,OAAO,KAAK,EAAE,cAAc,EAA8B,MAAM,aAAa,CAAA;AAG7E,MAAM,MAAM,eAAe,CACzB,QAAQ,SAAS,kBAAkB,EACnC,SAAS,SAAS,MAAM,QAAQ,GAAG,MAAM,GAAG,MAAM,QAAQ,GAAG,MAAM,IACjE,aAAa,CAAC,eAAe,CAAC,SAAS,EAAE,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC,CAAA;AAElE,wBAAgB,YAAY,CAC1B,QAAQ,SAAS,kBAAkB,EACnC,SAAS,SAAS,MAAM,QAAQ,GAAG,MAAM,EACzC,GAAG,EAAE,cAAc,CAAC,QAAQ,CAAC,EAAE,GAAG,EAAE,eAAe,CAAC,QAAQ,EAAE,SAAS,CAAC,GAAG,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC,CAoDjG"}
|
package/lib/handlers/stream.js
CHANGED
|
@@ -16,6 +16,10 @@ export function handleStream(ctx, msg) {
|
|
|
16
16
|
if (controller.signal.aborted) {
|
|
17
17
|
return;
|
|
18
18
|
}
|
|
19
|
+
ctx.logger.trace('send value to stream {procedure} with ID {rid}', {
|
|
20
|
+
procedure: msg.payload.prc,
|
|
21
|
+
rid: msg.payload.rid
|
|
22
|
+
});
|
|
19
23
|
await ctx.send({
|
|
20
24
|
typ: 'receive',
|
|
21
25
|
rid: msg.payload.rid,
|
|
@@ -28,6 +32,17 @@ export function handleStream(ctx, msg) {
|
|
|
28
32
|
signal: controller.signal,
|
|
29
33
|
writable: receiveStream.writable
|
|
30
34
|
};
|
|
31
|
-
//
|
|
32
|
-
return
|
|
35
|
+
// Wrap execution to ensure stream cleanup on handler crash
|
|
36
|
+
return (async ()=>{
|
|
37
|
+
try {
|
|
38
|
+
// @ts-expect-error context and handler types
|
|
39
|
+
await executeHandler(ctx, msg.payload, ()=>handler(handlerContext));
|
|
40
|
+
} finally{
|
|
41
|
+
try {
|
|
42
|
+
await receiveStream.writable.close();
|
|
43
|
+
} catch {
|
|
44
|
+
// Stream may already be closed
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
})();
|
|
33
48
|
}
|
package/lib/index.d.ts
CHANGED
|
@@ -9,7 +9,9 @@
|
|
|
9
9
|
*
|
|
10
10
|
* @module server
|
|
11
11
|
*/
|
|
12
|
-
export type { ProcedureAccessRecord } from './access-control.js';
|
|
12
|
+
export type { EncryptionPolicy, ProcedureAccessConfig, ProcedureAccessRecord, ProcedureAccessValue, } from './access-control.js';
|
|
13
|
+
export { resolveEncryptionPolicy } from './access-control.js';
|
|
14
|
+
export { createResourceLimiter, DEFAULT_RESOURCE_LIMITS, type ResourceLimiter, type ResourceLimits, } from './limits.js';
|
|
13
15
|
export { type ServeParams, Server, type ServerParams, serve } from './server.js';
|
|
14
16
|
export type { ChannelHandler, ChannelHandlerContext, EventHandler, EventHandlerContext, HandlerReturn, ProcedureHandlers, RequestHandler, RequestHandlerContext, ServerEmitter, ServerEvents, StreamHandler, StreamHandlerContext, } from './types.js';
|
|
15
17
|
//# sourceMappingURL=index.d.ts.map
|
package/lib/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,YAAY,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,YAAY,EACV,gBAAgB,EAChB,qBAAqB,EACrB,qBAAqB,EACrB,oBAAoB,GACrB,MAAM,qBAAqB,CAAA;AAC5B,OAAO,EAAE,uBAAuB,EAAE,MAAM,qBAAqB,CAAA;AAC7D,OAAO,EACL,qBAAqB,EACrB,uBAAuB,EACvB,KAAK,eAAe,EACpB,KAAK,cAAc,GACpB,MAAM,aAAa,CAAA;AACpB,OAAO,EAAE,KAAK,WAAW,EAAE,MAAM,EAAE,KAAK,YAAY,EAAE,KAAK,EAAE,MAAM,aAAa,CAAA;AAChF,YAAY,EACV,cAAc,EACd,qBAAqB,EACrB,YAAY,EACZ,mBAAmB,EACnB,aAAa,EACb,iBAAiB,EACjB,cAAc,EACd,qBAAqB,EACrB,aAAa,EACb,YAAY,EACZ,aAAa,EACb,oBAAoB,GACrB,MAAM,YAAY,CAAA"}
|
package/lib/index.js
CHANGED
|
@@ -8,4 +8,6 @@
|
|
|
8
8
|
* ```
|
|
9
9
|
*
|
|
10
10
|
* @module server
|
|
11
|
-
*/ export {
|
|
11
|
+
*/ export { resolveEncryptionPolicy } from './access-control.js';
|
|
12
|
+
export { createResourceLimiter, DEFAULT_RESOURCE_LIMITS } from './limits.js';
|
|
13
|
+
export { Server, serve } from './server.js';
|
package/lib/limits.d.ts
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
export type ResourceLimits = {
|
|
2
|
+
/** Maximum number of concurrent controllers (in-flight requests). Default: 10000 */
|
|
3
|
+
maxControllers: number;
|
|
4
|
+
/** Maximum number of concurrent handler executions. Default: 100 */
|
|
5
|
+
maxConcurrentHandlers: number;
|
|
6
|
+
/** Controller timeout in milliseconds. Default: 300000 (5 min) */
|
|
7
|
+
controllerTimeoutMs: number;
|
|
8
|
+
/** Cleanup timeout in milliseconds when disposing. Default: 30000 (30 sec) */
|
|
9
|
+
cleanupTimeoutMs: number;
|
|
10
|
+
/** Maximum size in bytes for any individual message payload. Default: 10485760 (10 MB) */
|
|
11
|
+
maxMessageSize: number;
|
|
12
|
+
};
|
|
13
|
+
export declare const DEFAULT_RESOURCE_LIMITS: ResourceLimits;
|
|
14
|
+
export type ResourceLimiter = {
|
|
15
|
+
limits: ResourceLimits;
|
|
16
|
+
controllerCount: number;
|
|
17
|
+
activeHandlers: number;
|
|
18
|
+
canAddController: () => boolean;
|
|
19
|
+
addController: (rid: string) => void;
|
|
20
|
+
removeController: (rid: string) => void;
|
|
21
|
+
getExpiredControllers: () => Array<string>;
|
|
22
|
+
acquireHandler: () => boolean;
|
|
23
|
+
releaseHandler: () => void;
|
|
24
|
+
};
|
|
25
|
+
export declare function createResourceLimiter(options?: Partial<ResourceLimits>): ResourceLimiter;
|
|
26
|
+
//# sourceMappingURL=limits.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"limits.d.ts","sourceRoot":"","sources":["../src/limits.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,cAAc,GAAG;IAC3B,oFAAoF;IACpF,cAAc,EAAE,MAAM,CAAA;IACtB,oEAAoE;IACpE,qBAAqB,EAAE,MAAM,CAAA;IAC7B,kEAAkE;IAClE,mBAAmB,EAAE,MAAM,CAAA;IAC3B,8EAA8E;IAC9E,gBAAgB,EAAE,MAAM,CAAA;IACxB,0FAA0F;IAC1F,cAAc,EAAE,MAAM,CAAA;CACvB,CAAA;AAED,eAAO,MAAM,uBAAuB,EAAE,cAMrC,CAAA;AAED,MAAM,MAAM,eAAe,GAAG;IAC5B,MAAM,EAAE,cAAc,CAAA;IACtB,eAAe,EAAE,MAAM,CAAA;IACvB,cAAc,EAAE,MAAM,CAAA;IACtB,gBAAgB,EAAE,MAAM,OAAO,CAAA;IAC/B,aAAa,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAA;IACpC,gBAAgB,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAA;IACvC,qBAAqB,EAAE,MAAM,KAAK,CAAC,MAAM,CAAC,CAAA;IAC1C,cAAc,EAAE,MAAM,OAAO,CAAA;IAC7B,cAAc,EAAE,MAAM,IAAI,CAAA;CAC3B,CAAA;AAED,wBAAgB,qBAAqB,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC,cAAc,CAAC,GAAG,eAAe,CAiDxF"}
|
package/lib/limits.js
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
export const DEFAULT_RESOURCE_LIMITS = {
|
|
2
|
+
maxControllers: 10000,
|
|
3
|
+
maxConcurrentHandlers: 100,
|
|
4
|
+
controllerTimeoutMs: 300000,
|
|
5
|
+
cleanupTimeoutMs: 30000,
|
|
6
|
+
maxMessageSize: 10485760
|
|
7
|
+
};
|
|
8
|
+
export function createResourceLimiter(options) {
|
|
9
|
+
const limits = {
|
|
10
|
+
...DEFAULT_RESOURCE_LIMITS,
|
|
11
|
+
...options
|
|
12
|
+
};
|
|
13
|
+
const controllers = new Map() // rid -> timestamp
|
|
14
|
+
;
|
|
15
|
+
let handlerCount = 0;
|
|
16
|
+
return {
|
|
17
|
+
limits,
|
|
18
|
+
get controllerCount () {
|
|
19
|
+
return controllers.size;
|
|
20
|
+
},
|
|
21
|
+
get activeHandlers () {
|
|
22
|
+
return handlerCount;
|
|
23
|
+
},
|
|
24
|
+
canAddController () {
|
|
25
|
+
return controllers.size < limits.maxControllers;
|
|
26
|
+
},
|
|
27
|
+
addController (rid) {
|
|
28
|
+
controllers.set(rid, Date.now());
|
|
29
|
+
},
|
|
30
|
+
removeController (rid) {
|
|
31
|
+
controllers.delete(rid);
|
|
32
|
+
},
|
|
33
|
+
getExpiredControllers () {
|
|
34
|
+
const now = Date.now();
|
|
35
|
+
const expired = [];
|
|
36
|
+
for (const [rid, timestamp] of controllers){
|
|
37
|
+
if (now - timestamp > limits.controllerTimeoutMs) {
|
|
38
|
+
expired.push(rid);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
return expired;
|
|
42
|
+
},
|
|
43
|
+
acquireHandler () {
|
|
44
|
+
if (handlerCount >= limits.maxConcurrentHandlers) {
|
|
45
|
+
return false;
|
|
46
|
+
}
|
|
47
|
+
handlerCount++;
|
|
48
|
+
return true;
|
|
49
|
+
},
|
|
50
|
+
releaseHandler () {
|
|
51
|
+
if (handlerCount > 0) {
|
|
52
|
+
handlerCount--;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
};
|
|
56
|
+
}
|
package/lib/server.d.ts
CHANGED
|
@@ -2,9 +2,11 @@ import { Disposer } from '@enkaku/async';
|
|
|
2
2
|
import { type Logger } from '@enkaku/log';
|
|
3
3
|
import { type AnyClientMessageOf, type ProtocolDefinition, type ServerTransportOf } from '@enkaku/protocol';
|
|
4
4
|
import { type Validator } from '@enkaku/schema';
|
|
5
|
-
import { type
|
|
5
|
+
import { type Identity } from '@enkaku/token';
|
|
6
|
+
import { type EncryptionPolicy, type ProcedureAccessRecord } from './access-control.js';
|
|
7
|
+
import { type ResourceLimiter, type ResourceLimits } from './limits.js';
|
|
6
8
|
import type { ProcedureHandlers, ServerEmitter } from './types.js';
|
|
7
|
-
export type AccessControlParams = {
|
|
9
|
+
export type AccessControlParams = ({
|
|
8
10
|
public: true;
|
|
9
11
|
serverID?: string;
|
|
10
12
|
access?: ProcedureAccessRecord;
|
|
@@ -12,10 +14,13 @@ export type AccessControlParams = {
|
|
|
12
14
|
public: false;
|
|
13
15
|
serverID: string;
|
|
14
16
|
access: ProcedureAccessRecord;
|
|
17
|
+
}) & {
|
|
18
|
+
encryptionPolicy?: EncryptionPolicy;
|
|
15
19
|
};
|
|
16
20
|
export type HandleMessagesParams<Protocol extends ProtocolDefinition> = AccessControlParams & {
|
|
17
21
|
events: ServerEmitter;
|
|
18
22
|
handlers: ProcedureHandlers<Protocol>;
|
|
23
|
+
limiter: ResourceLimiter;
|
|
19
24
|
logger: Logger;
|
|
20
25
|
signal: AbortSignal;
|
|
21
26
|
transport: ServerTransportOf<Protocol>;
|
|
@@ -23,8 +28,10 @@ export type HandleMessagesParams<Protocol extends ProtocolDefinition> = AccessCo
|
|
|
23
28
|
};
|
|
24
29
|
export type ServerParams<Protocol extends ProtocolDefinition> = {
|
|
25
30
|
access?: ProcedureAccessRecord;
|
|
31
|
+
encryptionPolicy?: EncryptionPolicy;
|
|
26
32
|
handlers: ProcedureHandlers<Protocol>;
|
|
27
|
-
|
|
33
|
+
identity?: Identity;
|
|
34
|
+
limits?: Partial<ResourceLimits>;
|
|
28
35
|
logger?: Logger;
|
|
29
36
|
protocol?: Protocol;
|
|
30
37
|
public?: boolean;
|
package/lib/server.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAuB,QAAQ,EAAE,MAAM,eAAe,CAAA;AAE7D,OAAO,EAAmB,KAAK,MAAM,EAAE,MAAM,aAAa,CAAA;AAC1D,OAAO,EACL,KAAK,kBAAkB,EAGvB,KAAK,kBAAkB,EACvB,KAAK,iBAAiB,EACvB,MAAM,kBAAkB,CAAA;AACzB,OAAO,EAIL,KAAK,SAAS,EACf,MAAM,gBAAgB,CAAA;
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
|
package/lib/server.js
CHANGED
|
@@ -4,13 +4,15 @@ import { getEnkakuLogger } from '@enkaku/log';
|
|
|
4
4
|
import { createClientMessageSchema } from '@enkaku/protocol';
|
|
5
5
|
import { createValidator, ValidationError } from '@enkaku/schema';
|
|
6
6
|
import { createUnsignedToken, isSignedToken } from '@enkaku/token';
|
|
7
|
-
import { checkClientToken } from './access-control.js';
|
|
7
|
+
import { checkClientToken, resolveEncryptionPolicy } from './access-control.js';
|
|
8
|
+
import { HandlerError } from './error.js';
|
|
8
9
|
import { handleChannel } from './handlers/channel.js';
|
|
9
10
|
import { handleEvent } from './handlers/event.js';
|
|
10
11
|
import { handleRequest } from './handlers/request.js';
|
|
11
12
|
import { handleStream } from './handlers/stream.js';
|
|
13
|
+
import { createResourceLimiter } from './limits.js';
|
|
12
14
|
async function handleMessages(params) {
|
|
13
|
-
const { events, handlers, logger, signal, transport, validator } = params;
|
|
15
|
+
const { events, handlers, limiter, logger, signal, transport, validator } = params;
|
|
14
16
|
const controllers = Object.create(null);
|
|
15
17
|
const context = {
|
|
16
18
|
controllers,
|
|
@@ -20,8 +22,34 @@ async function handleMessages(params) {
|
|
|
20
22
|
send: (payload)=>transport.write(createUnsignedToken(payload))
|
|
21
23
|
};
|
|
22
24
|
const running = Object.create(null);
|
|
25
|
+
const encoder = new TextEncoder();
|
|
26
|
+
// Periodic cleanup of expired controllers
|
|
27
|
+
const cleanupInterval = setInterval(()=>{
|
|
28
|
+
const expired = limiter.getExpiredControllers();
|
|
29
|
+
for (const rid of expired){
|
|
30
|
+
const controller = controllers[rid];
|
|
31
|
+
if (controller != null) {
|
|
32
|
+
controller.abort('Timeout');
|
|
33
|
+
const error = new HandlerError({
|
|
34
|
+
code: 'EK05',
|
|
35
|
+
message: 'Request timeout'
|
|
36
|
+
});
|
|
37
|
+
context.send(error.toPayload(rid));
|
|
38
|
+
events.emit('handlerTimeout', {
|
|
39
|
+
rid
|
|
40
|
+
});
|
|
41
|
+
limiter.removeController(rid);
|
|
42
|
+
limiter.releaseHandler();
|
|
43
|
+
delete controllers[rid];
|
|
44
|
+
delete running[rid];
|
|
45
|
+
} else {
|
|
46
|
+
limiter.removeController(rid);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}, Math.min(limiter.limits.controllerTimeoutMs, 10000));
|
|
23
50
|
const disposer = new Disposer({
|
|
24
51
|
dispose: async ()=>{
|
|
52
|
+
clearInterval(cleanupInterval);
|
|
25
53
|
const interruption = new DisposeInterruption();
|
|
26
54
|
// Abort all currently running handlers
|
|
27
55
|
for (const controller of Object.values(controllers)){
|
|
@@ -53,23 +81,96 @@ async function handleMessages(params) {
|
|
|
53
81
|
return result.value;
|
|
54
82
|
} : (message)=>message;
|
|
55
83
|
function processHandler(message, handle) {
|
|
84
|
+
const rid = message.payload.typ === 'event' ? Math.random().toString(36).slice(2) : message.payload.rid;
|
|
85
|
+
// Check controller limit
|
|
86
|
+
if (!limiter.canAddController()) {
|
|
87
|
+
const error = new HandlerError({
|
|
88
|
+
code: 'EK03',
|
|
89
|
+
message: 'Server controller limit reached'
|
|
90
|
+
});
|
|
91
|
+
if (message.payload.typ !== 'event') {
|
|
92
|
+
context.send(error.toPayload(rid));
|
|
93
|
+
}
|
|
94
|
+
events.emit('handlerError', {
|
|
95
|
+
error,
|
|
96
|
+
payload: message.payload
|
|
97
|
+
});
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
// Check handler concurrency (synchronous fast path)
|
|
101
|
+
if (limiter.activeHandlers >= limiter.limits.maxConcurrentHandlers) {
|
|
102
|
+
const error = new HandlerError({
|
|
103
|
+
code: 'EK04',
|
|
104
|
+
message: 'Server handler limit reached'
|
|
105
|
+
});
|
|
106
|
+
if (message.payload.typ !== 'event') {
|
|
107
|
+
context.send(error.toPayload(rid));
|
|
108
|
+
}
|
|
109
|
+
events.emit('handlerError', {
|
|
110
|
+
error,
|
|
111
|
+
payload: message.payload
|
|
112
|
+
});
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
limiter.addController(rid);
|
|
116
|
+
limiter.acquireHandler();
|
|
56
117
|
const returned = handle();
|
|
57
118
|
if (returned instanceof Error) {
|
|
58
|
-
|
|
119
|
+
limiter.removeController(rid);
|
|
120
|
+
limiter.releaseHandler();
|
|
59
121
|
events.emit('handlerError', {
|
|
60
|
-
error: returned,
|
|
61
|
-
|
|
62
|
-
|
|
122
|
+
error: HandlerError.from(returned, {
|
|
123
|
+
code: 'EK01'
|
|
124
|
+
}),
|
|
125
|
+
payload: message.payload
|
|
63
126
|
});
|
|
64
127
|
} else {
|
|
65
|
-
|
|
66
|
-
running[id] = returned;
|
|
128
|
+
running[rid] = returned;
|
|
67
129
|
returned.then(()=>{
|
|
68
|
-
|
|
130
|
+
// Guard against double-release if timeout cleanup already handled this rid
|
|
131
|
+
if (running[rid] === returned) {
|
|
132
|
+
limiter.removeController(rid);
|
|
133
|
+
limiter.releaseHandler();
|
|
134
|
+
delete running[rid];
|
|
135
|
+
}
|
|
69
136
|
});
|
|
70
137
|
}
|
|
71
138
|
}
|
|
72
|
-
|
|
139
|
+
function checkMessageEncryption(message) {
|
|
140
|
+
const globalPolicy = params.encryptionPolicy ?? 'none';
|
|
141
|
+
if (globalPolicy === 'none') {
|
|
142
|
+
return true;
|
|
143
|
+
}
|
|
144
|
+
const procedure = message.payload.prc;
|
|
145
|
+
const effectivePolicy = procedure != null ? resolveEncryptionPolicy(procedure, params.access, globalPolicy) : globalPolicy;
|
|
146
|
+
if (effectivePolicy !== 'required') {
|
|
147
|
+
return true;
|
|
148
|
+
}
|
|
149
|
+
// Detect if message was encrypted: jwe-in-jws mode has a 'jwe' field in the payload
|
|
150
|
+
const payload = message.payload;
|
|
151
|
+
return 'jwe' in payload && typeof payload.jwe === 'string';
|
|
152
|
+
}
|
|
153
|
+
function handleEncryptionViolation(message) {
|
|
154
|
+
const error = new HandlerError({
|
|
155
|
+
code: 'EK07',
|
|
156
|
+
message: 'Encryption required but message is not encrypted'
|
|
157
|
+
});
|
|
158
|
+
if (message.payload.typ === 'event') {
|
|
159
|
+
events.emit('handlerError', {
|
|
160
|
+
error,
|
|
161
|
+
payload: message.payload
|
|
162
|
+
});
|
|
163
|
+
} else {
|
|
164
|
+
context.send(error.toPayload(message.payload.rid));
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
const process = params.public ? (message, handle)=>{
|
|
168
|
+
if (!checkMessageEncryption(message)) {
|
|
169
|
+
handleEncryptionViolation(message);
|
|
170
|
+
return;
|
|
171
|
+
}
|
|
172
|
+
processHandler(message, handle);
|
|
173
|
+
} : async (message, handle)=>{
|
|
73
174
|
try {
|
|
74
175
|
if (!params.public) {
|
|
75
176
|
if (!isSignedToken(message)) {
|
|
@@ -77,25 +178,30 @@ async function handleMessages(params) {
|
|
|
77
178
|
}
|
|
78
179
|
await checkClientToken(params.serverID, params.access, message);
|
|
79
180
|
}
|
|
80
|
-
} catch (
|
|
81
|
-
const
|
|
181
|
+
} catch (cause) {
|
|
182
|
+
const error = new HandlerError({
|
|
183
|
+
cause,
|
|
184
|
+
code: 'EK02',
|
|
185
|
+
message: cause.message ?? 'Access denied'
|
|
186
|
+
});
|
|
82
187
|
if (message.payload.typ === 'event') {
|
|
188
|
+
events.emit('eventAuthError', {
|
|
189
|
+
error,
|
|
190
|
+
payload: message.payload
|
|
191
|
+
});
|
|
83
192
|
events.emit('handlerError', {
|
|
84
|
-
error
|
|
85
|
-
cause: err
|
|
86
|
-
}),
|
|
193
|
+
error,
|
|
87
194
|
payload: message.payload
|
|
88
195
|
});
|
|
89
196
|
} else {
|
|
90
|
-
context.send(
|
|
91
|
-
typ: 'error',
|
|
92
|
-
rid: message.payload.rid,
|
|
93
|
-
code: 'EK02',
|
|
94
|
-
msg: errorMessage
|
|
95
|
-
});
|
|
197
|
+
context.send(error.toPayload(message.payload.rid));
|
|
96
198
|
}
|
|
97
199
|
return;
|
|
98
200
|
}
|
|
201
|
+
if (!checkMessageEncryption(message)) {
|
|
202
|
+
handleEncryptionViolation(message);
|
|
203
|
+
return;
|
|
204
|
+
}
|
|
99
205
|
processHandler(message, handle);
|
|
100
206
|
};
|
|
101
207
|
async function handleNext() {
|
|
@@ -106,6 +212,22 @@ async function handleMessages(params) {
|
|
|
106
212
|
}
|
|
107
213
|
const msg = processMessage(next.value);
|
|
108
214
|
if (msg != null) {
|
|
215
|
+
const msgSize = encoder.encode(JSON.stringify(msg.payload)).byteLength;
|
|
216
|
+
if (msgSize > limiter.limits.maxMessageSize) {
|
|
217
|
+
const error = new HandlerError({
|
|
218
|
+
code: 'EK06',
|
|
219
|
+
message: 'Message exceeds maximum size'
|
|
220
|
+
});
|
|
221
|
+
if ('rid' in msg.payload && msg.payload.rid != null) {
|
|
222
|
+
context.send(error.toPayload(msg.payload.rid));
|
|
223
|
+
}
|
|
224
|
+
events.emit('handlerError', {
|
|
225
|
+
error,
|
|
226
|
+
payload: msg.payload
|
|
227
|
+
});
|
|
228
|
+
handleNext();
|
|
229
|
+
return;
|
|
230
|
+
}
|
|
109
231
|
switch(msg.payload.typ){
|
|
110
232
|
case 'abort':
|
|
111
233
|
controllers[msg.payload.rid]?.abort(msg.payload.rsn);
|
|
@@ -131,7 +253,35 @@ async function handleMessages(params) {
|
|
|
131
253
|
case 'send':
|
|
132
254
|
{
|
|
133
255
|
const controller = controllers[msg.payload.rid];
|
|
134
|
-
controller
|
|
256
|
+
if (controller == null) {
|
|
257
|
+
logger.debug('received send for unknown channel {rid}', {
|
|
258
|
+
rid: msg.payload.rid
|
|
259
|
+
});
|
|
260
|
+
break;
|
|
261
|
+
}
|
|
262
|
+
// In non-public mode, validate send messages
|
|
263
|
+
if (!params.public) {
|
|
264
|
+
if (!isSignedToken(msg)) {
|
|
265
|
+
const error = new HandlerError({
|
|
266
|
+
code: 'EK02',
|
|
267
|
+
message: 'Channel send message must be signed'
|
|
268
|
+
});
|
|
269
|
+
context.send(error.toPayload(msg.payload.rid));
|
|
270
|
+
break;
|
|
271
|
+
}
|
|
272
|
+
try {
|
|
273
|
+
await checkClientToken(params.serverID, params.access, msg);
|
|
274
|
+
} catch (cause) {
|
|
275
|
+
const error = new HandlerError({
|
|
276
|
+
cause,
|
|
277
|
+
code: 'EK02',
|
|
278
|
+
message: cause.message ?? 'Send authorization denied'
|
|
279
|
+
});
|
|
280
|
+
context.send(error.toPayload(msg.payload.rid));
|
|
281
|
+
break;
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
controller.writer.write(msg.payload.val);
|
|
135
285
|
break;
|
|
136
286
|
}
|
|
137
287
|
case 'stream':
|
|
@@ -153,6 +303,7 @@ export class Server extends Disposer {
|
|
|
153
303
|
#events;
|
|
154
304
|
#handlers;
|
|
155
305
|
#handling = [];
|
|
306
|
+
#limiter;
|
|
156
307
|
#logger;
|
|
157
308
|
#validator;
|
|
158
309
|
constructor(params){
|
|
@@ -160,40 +311,63 @@ export class Server extends Disposer {
|
|
|
160
311
|
dispose: async ()=>{
|
|
161
312
|
// Signal messages handler to stop execution and run cleanup logic
|
|
162
313
|
this.#abortController.abort();
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
314
|
+
const cleanupTimeout = this.#limiter.limits.cleanupTimeoutMs;
|
|
315
|
+
const timeoutPromise = new Promise((resolve)=>{
|
|
316
|
+
setTimeout(resolve, cleanupTimeout);
|
|
317
|
+
});
|
|
318
|
+
// Race between graceful cleanup and timeout
|
|
319
|
+
const gracefulDone = await Promise.race([
|
|
320
|
+
Promise.all(this.#handling.map(async (handling)=>{
|
|
321
|
+
// Wait until all handlers are done - they might still need to flush messages to the transport
|
|
322
|
+
await handling.done;
|
|
323
|
+
// Dispose transport
|
|
324
|
+
await handling.transport.dispose();
|
|
325
|
+
})).then(()=>true),
|
|
326
|
+
timeoutPromise.then(()=>false)
|
|
327
|
+
]);
|
|
328
|
+
// Force dispose any remaining transports only if timed out
|
|
329
|
+
if (!gracefulDone) {
|
|
330
|
+
for (const handling of this.#handling){
|
|
331
|
+
try {
|
|
332
|
+
await handling.transport.dispose();
|
|
333
|
+
} catch {
|
|
334
|
+
// Ignore errors during forced cleanup
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
}
|
|
170
338
|
},
|
|
171
339
|
signal: params.signal
|
|
172
340
|
});
|
|
173
341
|
this.#abortController = new AbortController();
|
|
174
342
|
this.#events = new EventEmitter();
|
|
175
343
|
this.#handlers = params.handlers;
|
|
344
|
+
const serverID = params.identity?.id;
|
|
176
345
|
this.#logger = params.logger ?? getEnkakuLogger('server', {
|
|
177
|
-
serverID:
|
|
346
|
+
serverID: serverID ?? crypto.randomUUID()
|
|
178
347
|
});
|
|
179
|
-
if (
|
|
348
|
+
if (serverID == null) {
|
|
180
349
|
if (params.public) {
|
|
181
350
|
this.#accessControl = {
|
|
182
351
|
public: true,
|
|
183
|
-
access: params.access
|
|
352
|
+
access: params.access,
|
|
353
|
+
encryptionPolicy: params.encryptionPolicy
|
|
184
354
|
};
|
|
185
355
|
} else {
|
|
186
|
-
throw new Error('Invalid server parameters: either the server "
|
|
356
|
+
throw new Error('Invalid server parameters: either the server "identity" must be provided or the "public" parameter must be set to true');
|
|
187
357
|
}
|
|
188
358
|
} else {
|
|
189
359
|
this.#accessControl = {
|
|
190
360
|
public: !!params.public,
|
|
191
|
-
serverID
|
|
192
|
-
access: params.access ?? {}
|
|
361
|
+
serverID,
|
|
362
|
+
access: params.access ?? {},
|
|
363
|
+
encryptionPolicy: params.encryptionPolicy
|
|
193
364
|
};
|
|
194
365
|
}
|
|
366
|
+
this.#limiter = createResourceLimiter(params.limits);
|
|
195
367
|
if (params.protocol != null) {
|
|
196
368
|
this.#validator = createValidator(createClientMessageSchema(params.protocol));
|
|
369
|
+
} else {
|
|
370
|
+
this.#logger.warn('No protocol provided: message validation is disabled. Pass a protocol definition to enable runtime type checking.');
|
|
197
371
|
}
|
|
198
372
|
for (const transport of params.transports ?? []){
|
|
199
373
|
this.handle(transport);
|
|
@@ -208,11 +382,13 @@ export class Server extends Disposer {
|
|
|
208
382
|
const logger = options.logger ?? this.#logger.getChild('handler').with({
|
|
209
383
|
transportID: crypto.randomUUID()
|
|
210
384
|
});
|
|
385
|
+
const encryptionPolicy = this.#accessControl.encryptionPolicy;
|
|
211
386
|
let accessControl;
|
|
212
387
|
if (publicAccess) {
|
|
213
388
|
accessControl = {
|
|
214
389
|
public: true,
|
|
215
|
-
access
|
|
390
|
+
access,
|
|
391
|
+
encryptionPolicy
|
|
216
392
|
};
|
|
217
393
|
} else {
|
|
218
394
|
const serverID = this.#accessControl.serverID;
|
|
@@ -222,12 +398,14 @@ export class Server extends Disposer {
|
|
|
222
398
|
accessControl = {
|
|
223
399
|
public: false,
|
|
224
400
|
serverID,
|
|
225
|
-
access
|
|
401
|
+
access,
|
|
402
|
+
encryptionPolicy
|
|
226
403
|
};
|
|
227
404
|
}
|
|
228
405
|
const done = handleMessages({
|
|
229
406
|
events: this.#events,
|
|
230
407
|
handlers: this.#handlers,
|
|
408
|
+
limiter: this.#limiter,
|
|
231
409
|
logger,
|
|
232
410
|
signal: this.#abortController.signal,
|
|
233
411
|
transport,
|
package/lib/types.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { EventEmitter } from '@enkaku/event';
|
|
2
2
|
import type { Logger } from '@enkaku/log';
|
|
3
3
|
import type { AnyRequestProcedureDefinition, AnyServerPayloadOf, ChannelProcedureDefinition, DataOf, EventCallPayload, EventProcedureDefinition, Message, ProtocolDefinition, RequestCallPayload, RequestProcedureDefinition, ReturnOf, StreamProcedureDefinition } from '@enkaku/protocol';
|
|
4
|
+
import type { HandlerError } from './error.js';
|
|
4
5
|
export type RequestController = AbortController;
|
|
5
6
|
export type ChannelController<Send = unknown> = AbortController & {
|
|
6
7
|
writer: WritableStreamDefaultWriter<Send>;
|
|
@@ -35,13 +36,16 @@ export type ReceiveType<Protocol extends ProtocolDefinition, Procedure extends k
|
|
|
35
36
|
export type ResultType<Protocol extends ProtocolDefinition, Procedure extends keyof Protocol & string> = Protocol[Procedure] extends AnyRequestProcedureDefinition ? DataOf<Protocol[Procedure]['result']> : never;
|
|
36
37
|
export type SendType<Protocol extends ProtocolDefinition, Procedure extends keyof Protocol & string> = Protocol[Procedure] extends ChannelProcedureDefinition ? DataOf<Protocol[Procedure]['send']> : never;
|
|
37
38
|
export type ServerEvents = {
|
|
39
|
+
eventAuthError: {
|
|
40
|
+
error: HandlerError<string>;
|
|
41
|
+
payload: Record<string, unknown>;
|
|
42
|
+
};
|
|
38
43
|
handlerAbort: {
|
|
39
44
|
rid: string;
|
|
40
45
|
};
|
|
41
46
|
handlerError: {
|
|
42
|
-
error:
|
|
47
|
+
error: HandlerError<string>;
|
|
43
48
|
payload: Record<string, unknown>;
|
|
44
|
-
rid?: string;
|
|
45
49
|
};
|
|
46
50
|
handlerTimeout: {
|
|
47
51
|
rid: string;
|
package/lib/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
package/lib/utils.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAsB,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAA;AAGhG,OAAO,KAAK,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AAO5D,wBAAsB,cAAc,CAClC,QAAQ,SAAS,kBAAkB,EACnC,SAAS,SAAS,MAAM,QAAQ,GAAG,MAAM,EACzC,MAAM,SAAS,UAAU,CAAC,QAAQ,EAAE,SAAS,CAAC,GAAG,UAAU,CAAC,QAAQ,EAAE,SAAS,CAAC,EAEhF,OAAO,EAAE,cAAc,CAAC,QAAQ,CAAC,EACjC,OAAO,EAAE,gBAAgB,CAAC,SAAS,EAAE,QAAQ,CAAC,SAAS,CAAC,CAAC,EACzD,OAAO,EAAE,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,GACtC,OAAO,CAAC,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAsB,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAA;AAGhG,OAAO,KAAK,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AAO5D,wBAAsB,cAAc,CAClC,QAAQ,SAAS,kBAAkB,EACnC,SAAS,SAAS,MAAM,QAAQ,GAAG,MAAM,EACzC,MAAM,SAAS,UAAU,CAAC,QAAQ,EAAE,SAAS,CAAC,GAAG,UAAU,CAAC,QAAQ,EAAE,SAAS,CAAC,EAEhF,OAAO,EAAE,cAAc,CAAC,QAAQ,CAAC,EACjC,OAAO,EAAE,gBAAgB,CAAC,SAAS,EAAE,QAAQ,CAAC,SAAS,CAAC,CAAC,EACzD,OAAO,EAAE,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,GACtC,OAAO,CAAC,IAAI,CAAC,CA6Cf"}
|
package/lib/utils.js
CHANGED
|
@@ -9,6 +9,12 @@ export async function executeHandler(context, payload, execute) {
|
|
|
9
9
|
try {
|
|
10
10
|
const val = await toPromise(execute);
|
|
11
11
|
if (canSend(controller.signal)) {
|
|
12
|
+
context.logger.trace('send result to {type} {procedure} with ID {rid}', {
|
|
13
|
+
type: payload.typ,
|
|
14
|
+
procedure: payload.prc,
|
|
15
|
+
rid: payload.rid,
|
|
16
|
+
result: val
|
|
17
|
+
});
|
|
12
18
|
await context.send({
|
|
13
19
|
typ: 'result',
|
|
14
20
|
rid: payload.rid,
|
|
@@ -16,17 +22,28 @@ export async function executeHandler(context, payload, execute) {
|
|
|
16
22
|
});
|
|
17
23
|
}
|
|
18
24
|
} catch (cause) {
|
|
25
|
+
const error = HandlerError.from(cause, {
|
|
26
|
+
code: 'EK01',
|
|
27
|
+
message: 'Handler execution failed'
|
|
28
|
+
});
|
|
19
29
|
if (canSend(controller.signal)) {
|
|
20
|
-
context.
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
30
|
+
context.logger.trace('send error to {type} {procedure} with ID {rid}', {
|
|
31
|
+
type: payload.typ,
|
|
32
|
+
procedure: payload.prc,
|
|
33
|
+
rid: payload.rid,
|
|
34
|
+
error
|
|
35
|
+
});
|
|
36
|
+
context.send(error.toPayload(payload.rid));
|
|
37
|
+
} else {
|
|
38
|
+
context.logger.debug('handler error for {type} {procedure} with ID {rid} cannot be sent to client', {
|
|
39
|
+
type: payload.typ,
|
|
40
|
+
procedure: payload.prc,
|
|
41
|
+
rid: payload.rid,
|
|
42
|
+
error
|
|
43
|
+
});
|
|
24
44
|
}
|
|
25
45
|
context.events.emit('handlerError', {
|
|
26
|
-
error
|
|
27
|
-
cause
|
|
28
|
-
}),
|
|
29
|
-
rid: payload.rid,
|
|
46
|
+
error,
|
|
30
47
|
payload
|
|
31
48
|
});
|
|
32
49
|
} finally{
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@enkaku/server",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.13.0",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"homepage": "https://enkaku.dev",
|
|
6
6
|
"description": "Server logic for Enkaku RPC",
|
|
@@ -25,17 +25,17 @@
|
|
|
25
25
|
],
|
|
26
26
|
"sideEffects": false,
|
|
27
27
|
"dependencies": {
|
|
28
|
-
"@enkaku/
|
|
29
|
-
"@enkaku/
|
|
30
|
-
"@enkaku/
|
|
31
|
-
"@enkaku/
|
|
32
|
-
"@enkaku/
|
|
33
|
-
"@enkaku/schema": "^0.
|
|
34
|
-
"@enkaku/token": "^0.
|
|
35
|
-
"@enkaku/stream": "^0.
|
|
28
|
+
"@enkaku/capability": "^0.13.0",
|
|
29
|
+
"@enkaku/async": "^0.13.0",
|
|
30
|
+
"@enkaku/protocol": "^0.13.0",
|
|
31
|
+
"@enkaku/log": "^0.13.0",
|
|
32
|
+
"@enkaku/event": "^0.13.0",
|
|
33
|
+
"@enkaku/schema": "^0.13.0",
|
|
34
|
+
"@enkaku/token": "^0.13.0",
|
|
35
|
+
"@enkaku/stream": "^0.13.0"
|
|
36
36
|
},
|
|
37
37
|
"devDependencies": {
|
|
38
|
-
"@enkaku/transport": "^0.
|
|
38
|
+
"@enkaku/transport": "^0.13.0"
|
|
39
39
|
},
|
|
40
40
|
"scripts": {
|
|
41
41
|
"build:clean": "del lib",
|