@bjoernboss/mws 1.0.0 → 1.1.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/README.md +31 -6
- package/dist/base.d.ts +7 -6
- package/dist/base.js +2 -2
- package/dist/builder.d.ts +14 -0
- package/dist/builder.js +10 -10
- package/dist/cache.d.ts +42 -2
- package/dist/cache.js +81 -41
- package/dist/client.d.ts +144 -19
- package/dist/client.js +177 -153
- package/dist/handler.d.ts +70 -9
- package/dist/handler.js +71 -71
- package/dist/helper.d.ts +24 -1
- package/dist/helper.js +23 -23
- package/dist/log.d.ts +25 -14
- package/dist/log.js +21 -57
- package/dist/server.d.ts +70 -13
- package/dist/server.js +237 -163
- package/package.json +5 -5
package/dist/handler.d.ts
CHANGED
|
@@ -1,17 +1,40 @@
|
|
|
1
1
|
import * as libClient from "./client.js";
|
|
2
2
|
import * as libLog from "./log.js";
|
|
3
3
|
import * as libServer from "./server.js";
|
|
4
|
+
import * as libCache from "./cache.js";
|
|
5
|
+
/**
|
|
6
|
+
* Translation to be applied for nested children and reversed for any paths produced by the children.
|
|
7
|
+
* Paths are matched by longest path. A null translation is considered not being mapped and will not be forwarded.
|
|
8
|
+
*/
|
|
4
9
|
export type PathTranslation = Record<string, string | null>;
|
|
10
|
+
/** Request and handler specific parameters to be passed to the corresponding handler */
|
|
11
|
+
export type Params = Record<string, any>;
|
|
5
12
|
export interface AttachedModule {
|
|
13
|
+
/** forward the given client to the module, and translate the paths and logging accordingly, if the module
|
|
14
|
+
* is designated for the client; returns false if the client is still unhandled after the handler; params
|
|
15
|
+
* are passed on to the module without modification; no translation is equivalent to [/] => [/] */
|
|
6
16
|
handle(client: libClient.ClientRequest, options?: {
|
|
7
|
-
params?:
|
|
17
|
+
params?: Params;
|
|
8
18
|
translate?: PathTranslation;
|
|
9
19
|
}): Promise<boolean>;
|
|
20
|
+
/** detach the module from the parent module handler (registered unlinked callback will be invoked before this promise
|
|
21
|
+
* is completed; clients dispatched to the module will not be disconnected directly any may still be active) */
|
|
10
22
|
unlink(): Promise<void>;
|
|
23
|
+
/** original module that was attached */
|
|
11
24
|
module: ModuleHandler;
|
|
25
|
+
/** check if the link is still valid (i.e. no unlink has been initiated) */
|
|
12
26
|
linked(): boolean;
|
|
27
|
+
/** resolves once the module has been unlinked */
|
|
13
28
|
unlinked(): Promise<void>;
|
|
14
29
|
}
|
|
30
|
+
/**
|
|
31
|
+
* Modules will be stopped by default, once it is fully unlinked from the server again.
|
|
32
|
+
* If a module is initialized, or stopped, the stop-handler is called.
|
|
33
|
+
* An initialization will always be followed by a stop-handler call.
|
|
34
|
+
* Any request will first happen after successful initialization, and will complete before stop-handlers.
|
|
35
|
+
* WebSockets will not be automatically closed and must be closed by the module.
|
|
36
|
+
* Modules can either be attached to other modules (allowing for recursive detaches/cleanups) or to the server.
|
|
37
|
+
*/
|
|
15
38
|
export declare abstract class ModuleHandler extends libLog.Logger {
|
|
16
39
|
private _stopped;
|
|
17
40
|
private _config;
|
|
@@ -26,17 +49,38 @@ export declare abstract class ModuleHandler extends libLog.Logger {
|
|
|
26
49
|
private _performDetachSelf;
|
|
27
50
|
private _performAttachToParent;
|
|
28
51
|
_rootAttachToServer(server: libServer.Server, unlinked: () => void): AttachedModule;
|
|
52
|
+
/** module is attached directly or indirectly to the server (will be the first call being performed before any other calls; will only be called once) */
|
|
29
53
|
protected handleInitialize(server: libServer.Server): Promise<void>;
|
|
30
|
-
|
|
54
|
+
/** handle the client request (guaranteed to not have been claimed yet; if the promise resolves, client must either have been handled or must
|
|
55
|
+
* not be handled anymore; long-running handlers must check 'client.claimed' or await 'client.responded' to allow timely server shutdown) */
|
|
56
|
+
protected abstract handleRequest(client: libClient.ClientRequest, params?: Params): Promise<void>;
|
|
57
|
+
/** module has been stopped (all clients are guaranteed to have left, but accepted WebSockets will be left intact and
|
|
58
|
+
* must be closed manually by this module; will only be called once; module should cleanup any resources and timers) */
|
|
31
59
|
protected handleStop(): Promise<void>;
|
|
32
|
-
|
|
33
|
-
get
|
|
60
|
+
/** name of the module */
|
|
61
|
+
get name(): string;
|
|
62
|
+
/** server the module has been attached to (null if not yet initialized) */
|
|
63
|
+
get server(): libServer.Server | null;
|
|
64
|
+
/** [throws] cache host to be used by this module (throws if not yet initialized) */
|
|
65
|
+
get cache(): libCache.CacheHost;
|
|
66
|
+
/** enable or disable the module tagging the logging of clients [default: true] */
|
|
34
67
|
tagClients(tag: boolean): this;
|
|
68
|
+
/** set the tagging string the module should use in the logging of clients with empty string being module log identity [default: ''] */
|
|
35
69
|
tagString(tag: string): this;
|
|
70
|
+
/** enable or disable the module being stopped once detached the next time from the server [default: true] */
|
|
36
71
|
stopOnDetach(stop: boolean): this;
|
|
72
|
+
/** link the child to this module (unlinked will be called once the child has been removed or is identified to not
|
|
73
|
+
* be suited for this module; will not be called if this module is not attached or will not be attached anymore;
|
|
74
|
+
* unless already destroyed; detail is an additional information to be logged upon linking and unlinking) */
|
|
37
75
|
linkModule(child: ModuleHandler, unlinked?: () => void, detail?: string): AttachedModule;
|
|
76
|
+
/** close any connections to the module and stop the module itself (stopping must not
|
|
77
|
+
* be awaited while stopping itself or a parent as this can result in deadlocks) */
|
|
38
78
|
stop(): Promise<void>;
|
|
39
79
|
}
|
|
80
|
+
/**
|
|
81
|
+
* Simple module handler implementation, which dispatches requests to different children based on the request path (longest match).
|
|
82
|
+
* Stops itself once all children have been unlinked. Own parameters are not forwarded.
|
|
83
|
+
*/
|
|
40
84
|
export declare function dispatch(map: Record<string, ModuleHandler>, options?: {
|
|
41
85
|
name?: string;
|
|
42
86
|
}): DispatchModule;
|
|
@@ -45,8 +89,12 @@ export declare class DispatchModule extends ModuleHandler {
|
|
|
45
89
|
constructor(map: Record<string, ModuleHandler>, options?: {
|
|
46
90
|
name?: string;
|
|
47
91
|
});
|
|
48
|
-
protected handleRequest(client: libClient.ClientRequest
|
|
92
|
+
protected handleRequest(client: libClient.ClientRequest): Promise<void>;
|
|
49
93
|
}
|
|
94
|
+
/**
|
|
95
|
+
* Simple module handler implementation, which dispatches requests to different children based on the request hostname (longest match).
|
|
96
|
+
* Stops itself once all children have been unlinked. Own parameters are not forwarded.
|
|
97
|
+
*/
|
|
50
98
|
export declare function host(map: Record<string, ModuleHandler>, options?: {
|
|
51
99
|
name?: string;
|
|
52
100
|
}): HostModule;
|
|
@@ -58,8 +106,13 @@ export declare class HostModule extends ModuleHandler {
|
|
|
58
106
|
private testSubHost;
|
|
59
107
|
protected handleRequest(client: libClient.ClientRequest): Promise<void>;
|
|
60
108
|
}
|
|
109
|
+
/**
|
|
110
|
+
* Simple module interface implementation, which forwards any requests to a child handler
|
|
111
|
+
* with optional parameter and translation binding. Stops itself once the child has been unlinked.
|
|
112
|
+
* Own parameters are not forwarded.
|
|
113
|
+
*/
|
|
61
114
|
export declare function bind(handler: ModuleHandler, options?: {
|
|
62
|
-
params?:
|
|
115
|
+
params?: Params;
|
|
63
116
|
translate?: PathTranslation;
|
|
64
117
|
name?: string;
|
|
65
118
|
}): BindModule;
|
|
@@ -68,12 +121,16 @@ export declare class BindModule extends ModuleHandler {
|
|
|
68
121
|
private params?;
|
|
69
122
|
private translate?;
|
|
70
123
|
constructor(handler: ModuleHandler, options?: {
|
|
71
|
-
params?:
|
|
124
|
+
params?: Params;
|
|
72
125
|
translate?: PathTranslation;
|
|
73
126
|
name?: string;
|
|
74
127
|
});
|
|
75
128
|
protected handleRequest(client: libClient.ClientRequest): Promise<void>;
|
|
76
129
|
}
|
|
130
|
+
/**
|
|
131
|
+
* Simple module interface implementation, which validates the connected host and port before forwarding the client.
|
|
132
|
+
* Stops itself once the child has been unlinked. Own parameters are not forwarded.
|
|
133
|
+
*/
|
|
77
134
|
export declare function check(handler: ModuleHandler, host: string | string[], options?: {
|
|
78
135
|
name?: string;
|
|
79
136
|
port?: number;
|
|
@@ -89,6 +146,10 @@ export declare class CheckModule extends ModuleHandler {
|
|
|
89
146
|
private respondBadEndpoint;
|
|
90
147
|
protected handleRequest(client: libClient.ClientRequest): Promise<void>;
|
|
91
148
|
}
|
|
149
|
+
/**
|
|
150
|
+
* Simple module handler implementation, which allows requests to be handled by lambdas, and child modules to be attached.
|
|
151
|
+
* Stops itself once all children have been unlinked. Forwards parameter to lambda functions.
|
|
152
|
+
*/
|
|
92
153
|
export declare function lambda(options?: {
|
|
93
154
|
attach?: Record<string, ModuleHandler>;
|
|
94
155
|
setup?: CallbackSetup;
|
|
@@ -110,10 +171,10 @@ export declare class LambdaModule extends ModuleHandler {
|
|
|
110
171
|
name?: string;
|
|
111
172
|
});
|
|
112
173
|
protected handleInitialize(server: libServer.Server): Promise<void>;
|
|
113
|
-
protected handleRequest(client: libClient.ClientRequest, params?:
|
|
174
|
+
protected handleRequest(client: libClient.ClientRequest, params?: Params): Promise<void>;
|
|
114
175
|
protected handleStop(): Promise<void>;
|
|
115
176
|
}
|
|
116
177
|
export type CallbackSetup = (this: ModuleHandler, server: libServer.Server, links: Record<string, AttachedModule>) => Promise<void>;
|
|
117
|
-
export type CallbackHandle = (this: ModuleHandler, client: libClient.ClientRequest, params:
|
|
178
|
+
export type CallbackHandle = (this: ModuleHandler, client: libClient.ClientRequest, params: Params | undefined, links: Record<string, AttachedModule>) => Promise<void>;
|
|
118
179
|
export type CallbackStop = (this: ModuleHandler, links: Record<string, AttachedModule>) => Promise<void>;
|
|
119
180
|
//# sourceMappingURL=handler.d.ts.map
|
package/dist/handler.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as libLog from "./log.js";
|
|
2
2
|
import * as libBase from "./base.js";
|
|
3
3
|
import * as libServer from "./server.js";
|
|
4
|
-
|
|
4
|
+
/**
|
|
5
5
|
* Modules will be stopped by default, once it is fully unlinked from the server again.
|
|
6
6
|
* If a module is initialized, or stopped, the stop-handler is called.
|
|
7
7
|
* An initialization will always be followed by a stop-handler call.
|
|
@@ -60,17 +60,13 @@ export class ModuleHandler extends libLog.Logger {
|
|
|
60
60
|
return false;
|
|
61
61
|
}
|
|
62
62
|
async _processIncomingClient(client, params, translate) {
|
|
63
|
-
/* check if the client
|
|
64
|
-
* been handled and otherwise process any outstanding tasks */
|
|
65
|
-
if (this._handling.active.has(client) || client.claimed)
|
|
66
|
-
return client.claimed;
|
|
63
|
+
/* ensure that any outstanding tasks have completed and then check if the client can be processed by this module */
|
|
67
64
|
await this._drainTaskQueue(false, null);
|
|
68
|
-
|
|
69
|
-
if (!this._attachment.attached)
|
|
65
|
+
if (!this._attachment.attached || this._handling.active.has(client) || client.claimed || client.server != this._attachment.server)
|
|
70
66
|
return client.claimed;
|
|
71
|
-
|
|
72
|
-
const logTag = (this._config.tagClients ? (this._config.tagString == '' ? this.
|
|
73
|
-
const snapshot = client._pushTranslation(
|
|
67
|
+
/* setup the new mapping and path translation and check if the translation can be applied */
|
|
68
|
+
const logTag = (this._config.tagClients ? (this._config.tagString == '' ? this.identity : this._config.tagString) : '');
|
|
69
|
+
const snapshot = client._pushTranslation(translate ?? null, logTag);
|
|
74
70
|
if (snapshot == null)
|
|
75
71
|
return client.claimed;
|
|
76
72
|
/* check if the cleanup handler needs to be setup and push the client in general to be handled right now */
|
|
@@ -114,16 +110,17 @@ export class ModuleHandler extends libLog.Logger {
|
|
|
114
110
|
this._attachment.task.order.shift();
|
|
115
111
|
this._pushHandleTask(taskPromise);
|
|
116
112
|
/* notify the module itself about the initialization */
|
|
117
|
-
|
|
118
|
-
|
|
113
|
+
if (firstAttachment) {
|
|
114
|
+
try {
|
|
119
115
|
await this.handleInitialize(this._attachment.server);
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
116
|
+
}
|
|
117
|
+
catch (err) {
|
|
118
|
+
this.error(`Unhandled exception while initializing: ${err.message}`);
|
|
119
|
+
this.stop();
|
|
120
|
+
}
|
|
121
|
+
this.info(`Handler initialized to server [${this._attachment.server.identity}]`);
|
|
124
122
|
}
|
|
125
123
|
taskResolver();
|
|
126
|
-
return firstAttachment;
|
|
127
124
|
}
|
|
128
125
|
async _performDetachSelf() {
|
|
129
126
|
if (!this._attachment.attached)
|
|
@@ -161,18 +158,18 @@ export class ModuleHandler extends libLog.Logger {
|
|
|
161
158
|
};
|
|
162
159
|
const validateLinkState = (parentServer) => {
|
|
163
160
|
if (this._stopped != null) {
|
|
164
|
-
this.warning(`Stopped module cannot be attached to [${parent.
|
|
161
|
+
this.warning(`Stopped module cannot be attached to [${parent.identity}]`);
|
|
165
162
|
return false;
|
|
166
163
|
}
|
|
167
164
|
const thisServer = this._attachment.server;
|
|
168
165
|
if (thisServer != null && parentServer != null && thisServer != parentServer) {
|
|
169
|
-
this.warning(`Module attached to server [${thisServer.
|
|
166
|
+
this.warning(`Module attached to server [${thisServer.identity}] cannot be attached to server [${parentServer.identity}]`);
|
|
170
167
|
return false;
|
|
171
168
|
}
|
|
172
169
|
if (parent instanceof libServer.Server)
|
|
173
170
|
return true;
|
|
174
171
|
if (parent._stopped != null) {
|
|
175
|
-
this.warning(`Module cannot be attached to stopped module [${parent.
|
|
172
|
+
this.warning(`Module cannot be attached to stopped module [${parent.identity}]`);
|
|
176
173
|
return false;
|
|
177
174
|
}
|
|
178
175
|
if (!recSearchParents(parent)) {
|
|
@@ -196,7 +193,6 @@ export class ModuleHandler extends libLog.Logger {
|
|
|
196
193
|
return;
|
|
197
194
|
const parentServer = (parent instanceof libServer.Server ? parent : parent._attachment.server);
|
|
198
195
|
/* check if the attachment is possible in theory */
|
|
199
|
-
let firstAttachment = false;
|
|
200
196
|
if (!validateLinkState(parentServer))
|
|
201
197
|
link.cleanup();
|
|
202
198
|
/* check if the attachment is still certain (uncertainty can only happen once on the first time
|
|
@@ -206,15 +202,11 @@ export class ModuleHandler extends libLog.Logger {
|
|
|
206
202
|
if (!this._attachment.attached) {
|
|
207
203
|
if (realized != null)
|
|
208
204
|
this._pushHandleTask(realized);
|
|
209
|
-
|
|
205
|
+
await this._performAttachSelf(parentServer);
|
|
210
206
|
}
|
|
211
207
|
logged = !stopping;
|
|
212
|
-
if (logged)
|
|
213
|
-
|
|
214
|
-
this.info(`Attached to [${parent.logIdentity}]${detail}`);
|
|
215
|
-
else
|
|
216
|
-
this.info(`Attached to [${parent.logIdentity}] and server [${parentServer.logIdentity}]${detail}`);
|
|
217
|
-
}
|
|
208
|
+
if (logged)
|
|
209
|
+
this.info(`Attached to [${parent.identity}]${detail}`);
|
|
218
210
|
}
|
|
219
211
|
},
|
|
220
212
|
cleanup: async () => {
|
|
@@ -222,7 +214,7 @@ export class ModuleHandler extends libLog.Logger {
|
|
|
222
214
|
return unlinkPromise;
|
|
223
215
|
stopping = true, link.setup = null;
|
|
224
216
|
if (logged)
|
|
225
|
-
this.info(`Detached from [${parent.
|
|
217
|
+
this.info(`Detached from [${parent.identity}]${detail}`);
|
|
226
218
|
/* remove the link from the parent and add its cleanup to its task list (cleanup calls are only linked as task to the parent,
|
|
227
219
|
* as the child does not care for them; this implies that the module's stop method itself does not await them either) */
|
|
228
220
|
if (!(parent instanceof libServer.Server)) {
|
|
@@ -267,69 +259,77 @@ export class ModuleHandler extends libLog.Logger {
|
|
|
267
259
|
_rootAttachToServer(server, unlinked) {
|
|
268
260
|
return this._performAttachToParent(server, unlinked, '');
|
|
269
261
|
}
|
|
270
|
-
|
|
262
|
+
/** module is attached directly or indirectly to the server (will be the first call being performed before any other calls; will only be called once) */
|
|
271
263
|
async handleInitialize(server) { }
|
|
272
|
-
|
|
273
|
-
|
|
264
|
+
/** module has been stopped (all clients are guaranteed to have left, but accepted WebSockets will be left intact and
|
|
265
|
+
* must be closed manually by this module; will only be called once; module should cleanup any resources and timers) */
|
|
274
266
|
async handleStop() { }
|
|
275
|
-
|
|
276
|
-
get
|
|
267
|
+
/** name of the module */
|
|
268
|
+
get name() {
|
|
277
269
|
return this._config.name;
|
|
278
270
|
}
|
|
279
|
-
|
|
280
|
-
get
|
|
271
|
+
/** server the module has been attached to (null if not yet initialized) */
|
|
272
|
+
get server() {
|
|
281
273
|
return this._attachment.server;
|
|
282
274
|
}
|
|
283
|
-
|
|
275
|
+
/** [throws] cache host to be used by this module (throws if not yet initialized) */
|
|
276
|
+
get cache() {
|
|
277
|
+
if (this._attachment.server == null)
|
|
278
|
+
throw new Error('Not yet initialized');
|
|
279
|
+
return this._attachment.server.cache;
|
|
280
|
+
}
|
|
281
|
+
/** enable or disable the module tagging the logging of clients [default: true] */
|
|
284
282
|
tagClients(tag) {
|
|
285
283
|
this._config.tagClients = tag;
|
|
286
284
|
return this;
|
|
287
285
|
}
|
|
288
|
-
|
|
286
|
+
/** set the tagging string the module should use in the logging of clients with empty string being module log identity [default: ''] */
|
|
289
287
|
tagString(tag) {
|
|
290
288
|
this._config.tagString = tag;
|
|
291
289
|
return this;
|
|
292
290
|
}
|
|
293
|
-
|
|
291
|
+
/** enable or disable the module being stopped once detached the next time from the server [default: true] */
|
|
294
292
|
stopOnDetach(stop) {
|
|
295
293
|
this._config.stopOnDetach = stop;
|
|
296
294
|
return this;
|
|
297
295
|
}
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
296
|
+
/** link the child to this module (unlinked will be called once the child has been removed or is identified to not
|
|
297
|
+
* be suited for this module; will not be called if this module is not attached or will not be attached anymore;
|
|
298
|
+
* unless already destroyed; detail is an additional information to be logged upon linking and unlinking) */
|
|
301
299
|
linkModule(child, unlinked, detail) {
|
|
302
300
|
return child._performAttachToParent(this, (unlinked == null ? () => { } : unlinked), detail ?? '');
|
|
303
301
|
}
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
302
|
+
/** close any connections to the module and stop the module itself (stopping must not
|
|
303
|
+
* be awaited while stopping itself or a parent as this can result in deadlocks) */
|
|
304
|
+
stop() {
|
|
307
305
|
if (this._stopped != null)
|
|
308
306
|
return this._stopped;
|
|
309
307
|
/* setup the stopped-promise (before performing any operations, as the first operations might otherwise
|
|
310
308
|
* call stop again, without the stopped-promise value being set, thereby recursively stopping again) */
|
|
311
309
|
let resolver = () => { };
|
|
312
310
|
this._stopped = new Promise((res) => resolver = res);
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
client.
|
|
318
|
-
|
|
319
|
-
link.
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
311
|
+
(async () => {
|
|
312
|
+
/* kill any connections and kill all links and drain the remaining task queue
|
|
313
|
+
* (will not await the unlinked calls of links where this element is the child) */
|
|
314
|
+
this._performDetachSelf();
|
|
315
|
+
for (const client of this._handling.active)
|
|
316
|
+
client.killConnection('Module detached');
|
|
317
|
+
for (const link of this._attachment.links)
|
|
318
|
+
link.cleanup();
|
|
319
|
+
await this._drainTaskQueue(true, null);
|
|
320
|
+
try {
|
|
321
|
+
await this.handleStop();
|
|
322
|
+
}
|
|
323
|
+
catch (err) {
|
|
324
|
+
this.error(`Unhandled exception while stopping: ${err.message}`);
|
|
325
|
+
}
|
|
326
|
+
this.info('Handler stopped');
|
|
327
|
+
resolver();
|
|
328
|
+
})();
|
|
329
329
|
return this._stopped;
|
|
330
330
|
}
|
|
331
331
|
}
|
|
332
|
-
|
|
332
|
+
/**
|
|
333
333
|
* Simple module handler implementation, which dispatches requests to different children based on the request path (longest match).
|
|
334
334
|
* Stops itself once all children have been unlinked. Own parameters are not forwarded.
|
|
335
335
|
*/
|
|
@@ -343,7 +343,7 @@ export class DispatchModule extends ModuleHandler {
|
|
|
343
343
|
this.mapping = {};
|
|
344
344
|
for (const [key, handler] of Object.entries(map)) {
|
|
345
345
|
if (key in this.mapping) {
|
|
346
|
-
this.warning(`Ignoring duplicate mapping [${key}] by [${handler.
|
|
346
|
+
this.warning(`Ignoring duplicate mapping [${key}] by [${handler.identity}]`);
|
|
347
347
|
continue;
|
|
348
348
|
}
|
|
349
349
|
this.mapping[key] = this.linkModule(handler, () => {
|
|
@@ -355,7 +355,7 @@ export class DispatchModule extends ModuleHandler {
|
|
|
355
355
|
if (Object.keys(this.mapping).length == 0)
|
|
356
356
|
this.stop();
|
|
357
357
|
}
|
|
358
|
-
async handleRequest(client
|
|
358
|
+
async handleRequest(client) {
|
|
359
359
|
let bestMatch = null;
|
|
360
360
|
/* iterate over the mappings and look for the corresponding best handler */
|
|
361
361
|
for (const path in this.mapping) {
|
|
@@ -365,14 +365,14 @@ export class DispatchModule extends ModuleHandler {
|
|
|
365
365
|
bestMatch = path;
|
|
366
366
|
}
|
|
367
367
|
if (bestMatch != null) {
|
|
368
|
-
client.trace(`Client dispatched to handler [${this.mapping[bestMatch].module.
|
|
368
|
+
client.trace(`Client dispatched to handler [${this.mapping[bestMatch].module.identity}] for path [${bestMatch}]`);
|
|
369
369
|
await this.mapping[bestMatch].handle(client, { translate: { [bestMatch]: '/' } });
|
|
370
370
|
}
|
|
371
371
|
else
|
|
372
372
|
client.trace(`Request cannot be dispatched`);
|
|
373
373
|
}
|
|
374
374
|
}
|
|
375
|
-
|
|
375
|
+
/**
|
|
376
376
|
* Simple module handler implementation, which dispatches requests to different children based on the request hostname (longest match).
|
|
377
377
|
* Stops itself once all children have been unlinked. Own parameters are not forwarded.
|
|
378
378
|
*/
|
|
@@ -386,7 +386,7 @@ export class HostModule extends ModuleHandler {
|
|
|
386
386
|
this.mapping = {};
|
|
387
387
|
for (const [host, handler] of Object.entries(map)) {
|
|
388
388
|
if (host in this.mapping) {
|
|
389
|
-
this.warning(`Ignoring duplicate mapping of host [${host}] by [${handler.
|
|
389
|
+
this.warning(`Ignoring duplicate mapping of host [${host}] by [${handler.identity}]`);
|
|
390
390
|
continue;
|
|
391
391
|
}
|
|
392
392
|
this.mapping[host] = this.linkModule(handler, () => {
|
|
@@ -417,14 +417,14 @@ export class HostModule extends ModuleHandler {
|
|
|
417
417
|
bestMatch = host;
|
|
418
418
|
}
|
|
419
419
|
if (bestMatch != null) {
|
|
420
|
-
client.trace(`Client dispatched to handler [${this.mapping[bestMatch].module.
|
|
420
|
+
client.trace(`Client dispatched to handler [${this.mapping[bestMatch].module.identity}] for host [${bestMatch}]`);
|
|
421
421
|
await this.mapping[bestMatch].handle(client);
|
|
422
422
|
}
|
|
423
423
|
else
|
|
424
424
|
client.trace(`Request cannot be dispatched`);
|
|
425
425
|
}
|
|
426
426
|
}
|
|
427
|
-
|
|
427
|
+
/**
|
|
428
428
|
* Simple module interface implementation, which forwards any requests to a child handler
|
|
429
429
|
* with optional parameter and translation binding. Stops itself once the child has been unlinked.
|
|
430
430
|
* Own parameters are not forwarded.
|
|
@@ -447,7 +447,7 @@ export class BindModule extends ModuleHandler {
|
|
|
447
447
|
await this.handler.handle(client, { params: this.params, translate: this.translate });
|
|
448
448
|
}
|
|
449
449
|
}
|
|
450
|
-
|
|
450
|
+
/**
|
|
451
451
|
* Simple module interface implementation, which validates the connected host and port before forwarding the client.
|
|
452
452
|
* Stops itself once the child has been unlinked. Own parameters are not forwarded.
|
|
453
453
|
*/
|
|
@@ -495,7 +495,7 @@ export class CheckModule extends ModuleHandler {
|
|
|
495
495
|
await this.handler.handle(client);
|
|
496
496
|
}
|
|
497
497
|
}
|
|
498
|
-
|
|
498
|
+
/**
|
|
499
499
|
* Simple module handler implementation, which allows requests to be handled by lambdas, and child modules to be attached.
|
|
500
500
|
* Stops itself once all children have been unlinked. Forwards parameter to lambda functions.
|
|
501
501
|
*/
|
package/dist/helper.d.ts
CHANGED
|
@@ -1,8 +1,13 @@
|
|
|
1
1
|
import * as libBase from "./base.js";
|
|
2
|
+
/** lookup the encoding for a given name */
|
|
2
3
|
export declare function lookupEncoding(name: string): libBase.EncodingType | null;
|
|
4
|
+
/** list of all supported encodings */
|
|
3
5
|
export declare function supportedEncodingNames(): string[];
|
|
6
|
+
/** map extension of file-path/file-name to media type (null if no match was found) */
|
|
4
7
|
export declare function lookupMediaTypeFromFile(filePath: string): libBase.MediaType | null;
|
|
8
|
+
/** format the media type to the proper http header identifier */
|
|
5
9
|
export declare function buildMediaTypeIdentifier(media: libBase.MediaType): string;
|
|
10
|
+
/** does not respect 'no-identity' encoding requests; unknown at-least-size is considered valid (defaults 'identity' to null) */
|
|
6
11
|
export declare function negotiateEncoding(accept: string | null, atLeastSize: number | null, media: libBase.MediaType): libBase.EncodingType | null;
|
|
7
12
|
export declare enum RangeState {
|
|
8
13
|
noRange = 0,
|
|
@@ -10,24 +15,42 @@ export declare enum RangeState {
|
|
|
10
15
|
issue = 2,
|
|
11
16
|
malformed = 3
|
|
12
17
|
}
|
|
18
|
+
/** parse an http header range request (first and last are correct for all valid range states; will be [0,-1] for an emtpy file) */
|
|
13
19
|
export declare function parseRangeHeader(range: string | null, fileSize: number): {
|
|
14
20
|
first: number;
|
|
15
21
|
last: number;
|
|
16
22
|
state: RangeState;
|
|
17
23
|
};
|
|
24
|
+
/** check if the [etag] matches the list (i.e. in list or list is '*'), will not match for undefined list; if [strong]
|
|
25
|
+
* comparison, both must be non-weak, opaque-tags equal (strip W/ prefix and compare opaque-tags regardless of weakness) */
|
|
18
26
|
export declare function etagMatchesList(etag: string, header: string | null, strong: boolean): boolean;
|
|
27
|
+
/** returns null on invalid times, [>0] for a being greater, [<0] for a being smaller, [=0] for same time */
|
|
19
28
|
export declare function timestampCompare(a: string, b: string): number | null;
|
|
29
|
+
/** split a list value while removing whitespace and optionally respecting quotes (returns empty list on validly quoted strings) */
|
|
20
30
|
export declare function splitAndTrimList(content: string | null, separator: string, quotesAware: boolean): string[];
|
|
31
|
+
/** escape all html-special characters to prevent injection when embedding untrusted values */
|
|
21
32
|
export declare function escapeHtml(content: string): string;
|
|
33
|
+
/** expand the placeholders in the content (format: {#name}, with '{#' being escaped as '{##'; optionally html-escape values) */
|
|
22
34
|
export declare function expandPlaceholders(content: string, args: Record<string, string>, htmlEscape: boolean): string;
|
|
35
|
+
/** escape all placeholders in the content */
|
|
23
36
|
export declare function escapePlaceholders(content: string): string;
|
|
37
|
+
/** sanitize path and remove relative path components and convert it to an absolute path */
|
|
24
38
|
export declare function sanitize(path: string, relative: boolean): string;
|
|
39
|
+
/** join two paths into the sanitized absolute server path-environment */
|
|
25
40
|
export declare function joinSanitized(a: string, b: string): string;
|
|
41
|
+
/** check if the sanitized path is a sub-path of or equal to the sanitized base path (can be /base or /base/...) */
|
|
26
42
|
export declare function isSubPath(base: string, path: string): boolean;
|
|
43
|
+
/** check if the sanitized path is a true sub-path of the sanitized base path (must be truly inside: /base/...) */
|
|
27
44
|
export declare function isInside(base: string, path: string): boolean;
|
|
45
|
+
/** return the remaining path for the sub directory path in base (must be a true sub-directory) */
|
|
28
46
|
export declare function childPath(base: string, path: string): string;
|
|
47
|
+
/** rebase the path from the old base directory onto the new base (must be a true sub-directory) */
|
|
29
48
|
export declare function rebasePath(oldBase: string, newBase: string, path: string): string;
|
|
49
|
+
/** create path-creator, which returns sanitized paths relative to [path] */
|
|
30
50
|
export declare function createPathLocation(path: string): (path: string) => string;
|
|
31
|
-
|
|
51
|
+
/** create path-creator, which returns paths relative to the file url path (like the script itself using 'import.meta.url') and optionally changed by relative [path] */
|
|
52
|
+
export declare function createPathSelf(urlFilePath: string, path?: string): (path: string) => string;
|
|
53
|
+
/** split the path in three components ['/base/', 'name', '.extension'] (extension will be empty if the path
|
|
54
|
+
* does not contain a distinct extension; path will be empty if the path does not contain a distinct path) */
|
|
32
55
|
export declare function splitFilePath(path: string): [string, string, string];
|
|
33
56
|
//# sourceMappingURL=helper.d.ts.map
|