@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/helper.js
CHANGED
|
@@ -14,15 +14,15 @@ for (const media of Object.values(libBase.Media)) {
|
|
|
14
14
|
}
|
|
15
15
|
for (const encoding of Object.values(libBase.Encoding))
|
|
16
16
|
EncodingNameToEncodingTypeMapping[encoding.name] = encoding;
|
|
17
|
-
|
|
17
|
+
/** lookup the encoding for a given name */
|
|
18
18
|
export function lookupEncoding(name) {
|
|
19
19
|
return EncodingNameToEncodingTypeMapping[name.toLowerCase()] ?? null;
|
|
20
20
|
}
|
|
21
|
-
|
|
21
|
+
/** list of all supported encodings */
|
|
22
22
|
export function supportedEncodingNames() {
|
|
23
23
|
return Object.keys(EncodingNameToEncodingTypeMapping);
|
|
24
24
|
}
|
|
25
|
-
|
|
25
|
+
/** map extension of file-path/file-name to media type (null if no match was found) */
|
|
26
26
|
export function lookupMediaTypeFromFile(filePath) {
|
|
27
27
|
const fileExtension = splitFilePath(filePath)[2];
|
|
28
28
|
if (fileExtension != '') {
|
|
@@ -32,13 +32,13 @@ export function lookupMediaTypeFromFile(filePath) {
|
|
|
32
32
|
}
|
|
33
33
|
return null;
|
|
34
34
|
}
|
|
35
|
-
|
|
35
|
+
/** format the media type to the proper http header identifier */
|
|
36
36
|
export function buildMediaTypeIdentifier(media) {
|
|
37
37
|
if (media.encoding == '')
|
|
38
38
|
return media.mediaType;
|
|
39
39
|
return `${media.mediaType}; ${media.encoding}`;
|
|
40
40
|
}
|
|
41
|
-
|
|
41
|
+
/** does not respect 'no-identity' encoding requests; unknown at-least-size is considered valid (defaults 'identity' to null) */
|
|
42
42
|
export function negotiateEncoding(accept, atLeastSize, media) {
|
|
43
43
|
if (!media.compressible || accept == null)
|
|
44
44
|
return null;
|
|
@@ -90,7 +90,7 @@ export var RangeState;
|
|
|
90
90
|
RangeState[RangeState["issue"] = 2] = "issue";
|
|
91
91
|
RangeState[RangeState["malformed"] = 3] = "malformed";
|
|
92
92
|
})(RangeState || (RangeState = {}));
|
|
93
|
-
|
|
93
|
+
/** parse an http header range request (first and last are correct for all valid range states; will be [0,-1] for an emtpy file) */
|
|
94
94
|
export function parseRangeHeader(range, fileSize) {
|
|
95
95
|
if (range == null)
|
|
96
96
|
return { first: 0, last: fileSize - 1, state: RangeState.noRange };
|
|
@@ -136,7 +136,7 @@ export function parseRangeHeader(range, fileSize) {
|
|
|
136
136
|
return { first: 0, last: 0, state: RangeState.issue };
|
|
137
137
|
return { first: fileSize - last, last: fileSize - 1, state: RangeState.valid };
|
|
138
138
|
}
|
|
139
|
-
|
|
139
|
+
/** check if the [etag] matches the list (i.e. in list or list is '*'), will not match for undefined list; if [strong]
|
|
140
140
|
* comparison, both must be non-weak, opaque-tags equal (strip W/ prefix and compare opaque-tags regardless of weakness) */
|
|
141
141
|
export function etagMatchesList(etag, header, strong) {
|
|
142
142
|
if (header == null)
|
|
@@ -154,7 +154,7 @@ export function etagMatchesList(etag, header, strong) {
|
|
|
154
154
|
}
|
|
155
155
|
return false;
|
|
156
156
|
}
|
|
157
|
-
|
|
157
|
+
/** returns null on invalid times, [>0] for a being greater, [<0] for a being smaller, [=0] for same time */
|
|
158
158
|
export function timestampCompare(a, b) {
|
|
159
159
|
const _a = new Date(a).getTime();
|
|
160
160
|
if (isNaN(_a))
|
|
@@ -164,7 +164,7 @@ export function timestampCompare(a, b) {
|
|
|
164
164
|
return null;
|
|
165
165
|
return (_a - _b);
|
|
166
166
|
}
|
|
167
|
-
|
|
167
|
+
/** split a list value while removing whitespace and optionally respecting quotes (returns empty list on validly quoted strings) */
|
|
168
168
|
export function splitAndTrimList(content, separator, quotesAware) {
|
|
169
169
|
if (content == null)
|
|
170
170
|
return [];
|
|
@@ -182,7 +182,7 @@ export function splitAndTrimList(content, separator, quotesAware) {
|
|
|
182
182
|
output.push(current.trim());
|
|
183
183
|
return output;
|
|
184
184
|
}
|
|
185
|
-
|
|
185
|
+
/** escape all html-special characters to prevent injection when embedding untrusted values */
|
|
186
186
|
export function escapeHtml(content) {
|
|
187
187
|
let out = '';
|
|
188
188
|
for (let i = 0; i < content.length; ++i) {
|
|
@@ -209,7 +209,7 @@ export function escapeHtml(content) {
|
|
|
209
209
|
}
|
|
210
210
|
return out;
|
|
211
211
|
}
|
|
212
|
-
|
|
212
|
+
/** expand the placeholders in the content (format: {#name}, with '{#' being escaped as '{##'; optionally html-escape values) */
|
|
213
213
|
export function expandPlaceholders(content, args, htmlEscape) {
|
|
214
214
|
let out = '', name = '', placeholder = false;
|
|
215
215
|
for (let i = 0; i < content.length; ++i) {
|
|
@@ -239,7 +239,7 @@ export function expandPlaceholders(content, args, htmlEscape) {
|
|
|
239
239
|
helperLogger.warning('Content ends with an incomplete placeholder');
|
|
240
240
|
return out;
|
|
241
241
|
}
|
|
242
|
-
|
|
242
|
+
/** escape all placeholders in the content */
|
|
243
243
|
export function escapePlaceholders(content) {
|
|
244
244
|
let out = '';
|
|
245
245
|
/* construct the new escaped output content */
|
|
@@ -251,7 +251,7 @@ export function escapePlaceholders(content) {
|
|
|
251
251
|
}
|
|
252
252
|
return out;
|
|
253
253
|
}
|
|
254
|
-
|
|
254
|
+
/** sanitize path and remove relative path components and convert it to an absolute path */
|
|
255
255
|
export function sanitize(path, relative) {
|
|
256
256
|
/* treat the path as absolute, but preserve backward traversals into the root */
|
|
257
257
|
let out = '/';
|
|
@@ -298,7 +298,7 @@ export function sanitize(path, relative) {
|
|
|
298
298
|
out = '.';
|
|
299
299
|
return out;
|
|
300
300
|
}
|
|
301
|
-
|
|
301
|
+
/** join two paths into the sanitized absolute server path-environment */
|
|
302
302
|
export function joinSanitized(a, b) {
|
|
303
303
|
if (a.length == 0 || b.length == 0)
|
|
304
304
|
return sanitize(a.length == 0 ? b : a, false);
|
|
@@ -307,7 +307,7 @@ export function joinSanitized(a, b) {
|
|
|
307
307
|
return sanitize(bSlash ? a + b.substring(1) : a + b, false);
|
|
308
308
|
return sanitize(bSlash ? a + b : `${a}/${b}`, false);
|
|
309
309
|
}
|
|
310
|
-
|
|
310
|
+
/** check if the sanitized path is a sub-path of or equal to the sanitized base path (can be /base or /base/...) */
|
|
311
311
|
export function isSubPath(base, path) {
|
|
312
312
|
if (base.length > path.length)
|
|
313
313
|
return false;
|
|
@@ -317,37 +317,37 @@ export function isSubPath(base, path) {
|
|
|
317
317
|
return false;
|
|
318
318
|
return (path[base.length] == '/' || base.endsWith('/'));
|
|
319
319
|
}
|
|
320
|
-
|
|
320
|
+
/** check if the sanitized path is a true sub-path of the sanitized base path (must be truly inside: /base/...) */
|
|
321
321
|
export function isInside(base, path) {
|
|
322
322
|
if (base.length >= path.length)
|
|
323
323
|
return false;
|
|
324
324
|
if (!path.startsWith(base))
|
|
325
325
|
return false;
|
|
326
|
-
return (path[base.length] == '/' || base.endsWith('/'));
|
|
326
|
+
return ((path[base.length] == '/' && base.length + 1 < path.length) || base.endsWith('/'));
|
|
327
327
|
}
|
|
328
|
-
|
|
328
|
+
/** return the remaining path for the sub directory path in base (must be a true sub-directory) */
|
|
329
329
|
export function childPath(base, path) {
|
|
330
330
|
const out = path.substring(base.endsWith('/') ? base.length - 1 : base.length);
|
|
331
331
|
return (out == '' ? '/' : out);
|
|
332
332
|
}
|
|
333
|
-
|
|
333
|
+
/** rebase the path from the old base directory onto the new base (must be a true sub-directory) */
|
|
334
334
|
export function rebasePath(oldBase, newBase, path) {
|
|
335
335
|
return joinSanitized(newBase, childPath(oldBase, path));
|
|
336
336
|
}
|
|
337
|
-
|
|
337
|
+
/** create path-creator, which returns sanitized paths relative to [path] */
|
|
338
338
|
export function createPathLocation(path) {
|
|
339
339
|
return function (p) {
|
|
340
340
|
return libPath.join(path, sanitize(p, false));
|
|
341
341
|
};
|
|
342
342
|
}
|
|
343
|
-
|
|
344
|
-
export function createPathSelf(urlFilePath, path
|
|
343
|
+
/** 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] */
|
|
344
|
+
export function createPathSelf(urlFilePath, path) {
|
|
345
345
|
let dirName = libPath.dirname(libUrl.fileURLToPath(urlFilePath));
|
|
346
346
|
if (path != null)
|
|
347
347
|
dirName = libPath.join(dirName, sanitize(path, true));
|
|
348
348
|
return createPathLocation(dirName);
|
|
349
349
|
}
|
|
350
|
-
|
|
350
|
+
/** split the path in three components ['/base/', 'name', '.extension'] (extension will be empty if the path
|
|
351
351
|
* does not contain a distinct extension; path will be empty if the path does not contain a distinct path) */
|
|
352
352
|
export function splitFilePath(path) {
|
|
353
353
|
let dot = null;
|
package/dist/log.d.ts
CHANGED
|
@@ -1,52 +1,63 @@
|
|
|
1
|
+
/** supported log level */
|
|
1
2
|
export type LogLevel = 'error' | 'info' | 'warning' | 'log' | 'trace';
|
|
3
|
+
/** if [level] is null: is not a log, but the callback is being unregistered */
|
|
2
4
|
export type LogConsumer = (level: LogLevel | null, date: string, identity: string, msg: string) => void;
|
|
5
|
+
/** type to invoke to detach the given logger */
|
|
3
6
|
export type Detacher = () => void;
|
|
4
|
-
|
|
7
|
+
/** implementation of a console logger */
|
|
5
8
|
export declare function createConsoleLogger(): LogConsumer;
|
|
9
|
+
/** implementation of a logger which receives a well formatted line */
|
|
6
10
|
export declare function createLineLogger(cb: (line: string) => void): LogConsumer;
|
|
11
|
+
/** file overwriting preservation mode */
|
|
7
12
|
export declare enum PreserveMode {
|
|
13
|
+
/** simply clear the log file once full */
|
|
8
14
|
none = 0,
|
|
15
|
+
/** preserve the last log file to 'filePath.old' */
|
|
9
16
|
last = 1,
|
|
17
|
+
/** preserve all last log files to 'filePath.%time%.old */
|
|
10
18
|
all = 2
|
|
11
19
|
}
|
|
20
|
+
/** implementation of a file logger, which logs into the file-path and optionally preserves old logs
|
|
21
|
+
* (Note: contains a timer, server shutdown should clear all loggers to ensure fast shutdown) */
|
|
12
22
|
export declare function createFileLogger(filePath: string, options?: {
|
|
13
23
|
flushingDelayMs?: number;
|
|
14
24
|
bufMaxLineCount?: number;
|
|
15
25
|
sizeSwapFile?: number;
|
|
16
26
|
preserve?: PreserveMode;
|
|
17
27
|
}): LogConsumer;
|
|
28
|
+
/** implementation of a log filter, which can filter by matching level and identity including a given sub-string, and then forwards these logs to the target logger */
|
|
18
29
|
export declare function createLogFilter(target: LogConsumer, options?: {
|
|
19
30
|
level?: LogLevel | LogLevel[];
|
|
20
31
|
identity?: string | string[];
|
|
21
32
|
}): LogConsumer;
|
|
33
|
+
/** logger class to extend, supporting various logging classes, and writing to the registered log consumer */
|
|
34
|
+
export declare function createLogger(identity: string): Logger;
|
|
22
35
|
export declare class Logger {
|
|
23
|
-
private _rootIdentity;
|
|
24
36
|
private _logIdentity;
|
|
25
|
-
private _logTagList;
|
|
26
37
|
constructor(identity: string);
|
|
27
|
-
private _updateLogIdentity;
|
|
28
38
|
private _performActualLog;
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
39
|
+
/** update the log identity */
|
|
40
|
+
protected logSetIdentity(identity: string): void;
|
|
41
|
+
/** logging identity as shown in logs */
|
|
42
|
+
get identity(): string;
|
|
33
43
|
error(msg: string, options?: {
|
|
34
|
-
|
|
44
|
+
identity?: string;
|
|
35
45
|
}): void;
|
|
36
46
|
info(msg: string, options?: {
|
|
37
|
-
|
|
47
|
+
identity?: string;
|
|
38
48
|
}): void;
|
|
39
49
|
warning(msg: string, options?: {
|
|
40
|
-
|
|
50
|
+
identity?: string;
|
|
41
51
|
}): void;
|
|
42
52
|
log(msg: string, options?: {
|
|
43
|
-
|
|
53
|
+
identity?: string;
|
|
44
54
|
}): void;
|
|
45
55
|
trace(msg: string, options?: {
|
|
46
|
-
|
|
56
|
+
identity?: string;
|
|
47
57
|
}): void;
|
|
48
58
|
}
|
|
49
|
-
|
|
59
|
+
/** register another global logger to receive the logs (returned detacher can be invoked to remove the log) */
|
|
50
60
|
export declare function addLogger(cb: LogConsumer): Detacher;
|
|
61
|
+
/** perform a global log to all registered loggers */
|
|
51
62
|
export declare function logGlobal(level: LogLevel, identity: string, msg: string): void;
|
|
52
63
|
//# sourceMappingURL=log.d.ts.map
|
package/dist/log.js
CHANGED
|
@@ -26,7 +26,7 @@ function formatLine(level, date, identity, msg, lineBreak) {
|
|
|
26
26
|
return `[${date}] ${printLevel}: [${identity}] ${msg}\n`;
|
|
27
27
|
return `[${date}] ${printLevel}: [${identity}] ${msg}`;
|
|
28
28
|
}
|
|
29
|
-
|
|
29
|
+
/** implementation of a console logger */
|
|
30
30
|
export function createConsoleLogger() {
|
|
31
31
|
return (level, date, identity, msg) => {
|
|
32
32
|
if (level == null)
|
|
@@ -55,24 +55,24 @@ export function createConsoleLogger() {
|
|
|
55
55
|
console.log(`\x1b[90m[${date}] ${levelColor}${levelPrint}\x1b[0m: [\x1b[93m${identity}\x1b[0m] ${msg}`);
|
|
56
56
|
};
|
|
57
57
|
}
|
|
58
|
-
|
|
58
|
+
/** implementation of a logger which receives a well formatted line */
|
|
59
59
|
export function createLineLogger(cb) {
|
|
60
60
|
return (level, date, identity, msg) => {
|
|
61
61
|
if (level != null)
|
|
62
62
|
cb(formatLine(level, date, identity, msg, false));
|
|
63
63
|
};
|
|
64
64
|
}
|
|
65
|
-
|
|
65
|
+
/** file overwriting preservation mode */
|
|
66
66
|
export var PreserveMode;
|
|
67
67
|
(function (PreserveMode) {
|
|
68
|
-
|
|
68
|
+
/** simply clear the log file once full */
|
|
69
69
|
PreserveMode[PreserveMode["none"] = 0] = "none";
|
|
70
|
-
|
|
70
|
+
/** preserve the last log file to 'filePath.old' */
|
|
71
71
|
PreserveMode[PreserveMode["last"] = 1] = "last";
|
|
72
|
-
|
|
72
|
+
/** preserve all last log files to 'filePath.%time%.old */
|
|
73
73
|
PreserveMode[PreserveMode["all"] = 2] = "all";
|
|
74
74
|
})(PreserveMode || (PreserveMode = {}));
|
|
75
|
-
|
|
75
|
+
/** implementation of a file logger, which logs into the file-path and optionally preserves old logs
|
|
76
76
|
* (Note: contains a timer, server shutdown should clear all loggers to ensure fast shutdown) */
|
|
77
77
|
export function createFileLogger(filePath, options) {
|
|
78
78
|
/* setup the logging state (ignore any errors, as they cannot be logged) */
|
|
@@ -163,7 +163,7 @@ export function createFileLogger(filePath, options) {
|
|
|
163
163
|
logFileSize = 0;
|
|
164
164
|
};
|
|
165
165
|
}
|
|
166
|
-
|
|
166
|
+
/** implementation of a log filter, which can filter by matching level and identity including a given sub-string, and then forwards these logs to the target logger */
|
|
167
167
|
export function createLogFilter(target, options) {
|
|
168
168
|
const filterLevel = (options?.level == null ? null : new Set(Array.isArray(options.level) ? options.level : [options.level]));
|
|
169
169
|
const filterIdentity = (options?.identity == null ? null : (Array.isArray(options.identity) ? options.identity : [options.identity]));
|
|
@@ -178,61 +178,29 @@ export function createLogFilter(target, options) {
|
|
|
178
178
|
target(level, date, identity, msg);
|
|
179
179
|
};
|
|
180
180
|
}
|
|
181
|
-
|
|
181
|
+
/** logger class to extend, supporting various logging classes, and writing to the registered log consumer */
|
|
182
|
+
export function createLogger(identity) {
|
|
183
|
+
return new Logger(identity);
|
|
184
|
+
}
|
|
182
185
|
export class Logger {
|
|
183
|
-
_rootIdentity;
|
|
184
186
|
_logIdentity;
|
|
185
|
-
_logTagList;
|
|
186
187
|
constructor(identity) {
|
|
187
188
|
const id = (LoggerIdMap[identity] ?? 0) + 1;
|
|
188
189
|
LoggerIdMap[identity] = id;
|
|
189
|
-
this.
|
|
190
|
-
this._logIdentity = this._rootIdentity;
|
|
191
|
-
this._logTagList = [];
|
|
192
|
-
}
|
|
193
|
-
_updateLogIdentity() {
|
|
194
|
-
this._logIdentity = this._rootIdentity;
|
|
195
|
-
for (const tag of this._logTagList) {
|
|
196
|
-
if (tag.value != '')
|
|
197
|
-
this._logIdentity += `.${tag.value}`;
|
|
198
|
-
}
|
|
190
|
+
this._logIdentity = `${identity}!${id}`;
|
|
199
191
|
}
|
|
200
192
|
_performActualLog(level, msg, options) {
|
|
201
|
-
const identity = (options?.
|
|
193
|
+
const identity = (options?.identity == null ? this._logIdentity : options.identity);
|
|
202
194
|
logGlobal(level, identity, msg);
|
|
203
195
|
}
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
}
|
|
208
|
-
/* tag extension appended to root identity to form full logging identity */
|
|
209
|
-
get logExtension() {
|
|
210
|
-
return this._logIdentity.substring(this._rootIdentity.length + 1);
|
|
196
|
+
/** update the log identity */
|
|
197
|
+
logSetIdentity(identity) {
|
|
198
|
+
this._logIdentity = identity;
|
|
211
199
|
}
|
|
212
|
-
|
|
213
|
-
get
|
|
200
|
+
/** logging identity as shown in logs */
|
|
201
|
+
get identity() {
|
|
214
202
|
return this._logIdentity;
|
|
215
203
|
}
|
|
216
|
-
/* tag the logging with the given identifier and return a callback to update the tag */
|
|
217
|
-
tagLog(identifier) {
|
|
218
|
-
let tag = { value: identifier };
|
|
219
|
-
this._logTagList.push(tag);
|
|
220
|
-
if (tag.value != '')
|
|
221
|
-
this._updateLogIdentity();
|
|
222
|
-
/* setup the handler responsible to update the logging */
|
|
223
|
-
return (value) => {
|
|
224
|
-
if (tag == null)
|
|
225
|
-
return;
|
|
226
|
-
/* check if the tag should be removed or if the value should just be updated */
|
|
227
|
-
if (value == null) {
|
|
228
|
-
this._logTagList = this._logTagList.filter((v) => v != tag);
|
|
229
|
-
tag = null;
|
|
230
|
-
}
|
|
231
|
-
else if (value != tag.value)
|
|
232
|
-
tag.value = value;
|
|
233
|
-
this._updateLogIdentity();
|
|
234
|
-
};
|
|
235
|
-
}
|
|
236
204
|
error(msg, options) {
|
|
237
205
|
this._performActualLog('error', msg, options);
|
|
238
206
|
}
|
|
@@ -249,11 +217,7 @@ export class Logger {
|
|
|
249
217
|
this._performActualLog('trace', msg, options);
|
|
250
218
|
}
|
|
251
219
|
}
|
|
252
|
-
|
|
253
|
-
export function createLogger(identity) {
|
|
254
|
-
return new Logger(identity);
|
|
255
|
-
}
|
|
256
|
-
/* register another global logger to receive the logs (returned detacher can be invoked to remove the log) */
|
|
220
|
+
/** register another global logger to receive the logs (returned detacher can be invoked to remove the log) */
|
|
257
221
|
export function addLogger(cb) {
|
|
258
222
|
let detached = false;
|
|
259
223
|
const wrapped = (level, date, identity, msg) => {
|
|
@@ -279,7 +243,7 @@ export function addLogger(cb) {
|
|
|
279
243
|
wrapped(null, '', '', '');
|
|
280
244
|
};
|
|
281
245
|
}
|
|
282
|
-
|
|
246
|
+
/** perform a global log to all registered loggers */
|
|
283
247
|
export function logGlobal(level, identity, msg) {
|
|
284
248
|
const date = new Date().toUTCString();
|
|
285
249
|
for (const cb of GlobalLogConsumers)
|
package/dist/server.d.ts
CHANGED
|
@@ -4,55 +4,112 @@ import * as libHandler from "./handler.js";
|
|
|
4
4
|
import * as libCache from "./cache.js";
|
|
5
5
|
import * as libHttp from "http";
|
|
6
6
|
import * as libNet from "net";
|
|
7
|
+
import * as libStream from "stream";
|
|
8
|
+
type ListenerEvents = {
|
|
9
|
+
'listening': (address: libNet.AddressInfo | null) => void;
|
|
10
|
+
'failed': (err: Error) => void;
|
|
11
|
+
'stopped': () => void;
|
|
12
|
+
};
|
|
7
13
|
export declare class Server extends libLog.Logger {
|
|
8
14
|
private _stop;
|
|
9
15
|
private _cache;
|
|
10
16
|
private _config;
|
|
11
|
-
private
|
|
17
|
+
private _nextEndpoint;
|
|
12
18
|
constructor(config?: ServerConfig);
|
|
13
|
-
|
|
14
|
-
private fetchAddress;
|
|
15
|
-
private performServerCleanup;
|
|
16
|
-
private emitEventSync;
|
|
17
|
-
private makeServer;
|
|
19
|
+
/** listener is automatically stopped when the server is stopped or the handler stops itself */
|
|
18
20
|
listen(handler: libHandler.ModuleHandler, options?: ListenOptions): Listener;
|
|
21
|
+
/** shutdown the server and unlink all modules (immediately kills all open connections and listener; can be called multiple times) */
|
|
19
22
|
stop(): Promise<void>;
|
|
23
|
+
/** cache host used by this server */
|
|
20
24
|
get cache(): libCache.CacheHost;
|
|
25
|
+
/** configuration used by this server */
|
|
21
26
|
get config(): BurntServerConfig;
|
|
27
|
+
/** resolves once the server has stopped */
|
|
22
28
|
get stopped(): Promise<void>;
|
|
29
|
+
/** check if the server is still running */
|
|
23
30
|
get running(): boolean;
|
|
31
|
+
/** link the given module to the server (automatically unlinked upon server stop) */
|
|
24
32
|
linkModule(module: libHandler.ModuleHandler, unlinked?: () => void): libHandler.AttachedModule;
|
|
25
33
|
}
|
|
26
|
-
|
|
34
|
+
/**
|
|
35
|
+
* Either 'listening' or 'failed' is fired, followed at some point by a 'stopped' event.
|
|
36
|
+
* 'address' of 'listening' event is null for serverless listener.
|
|
37
|
+
*/
|
|
38
|
+
export declare class Listener {
|
|
39
|
+
private _host;
|
|
40
|
+
private _self;
|
|
41
|
+
private _stop;
|
|
42
|
+
private _native;
|
|
43
|
+
private _handling;
|
|
44
|
+
private _emitter;
|
|
45
|
+
private _config;
|
|
46
|
+
private constructor();
|
|
47
|
+
private emitEventSync;
|
|
48
|
+
private performServerListening;
|
|
49
|
+
private handleClient;
|
|
50
|
+
private configure;
|
|
51
|
+
static _fromParams(server: Server, handler: libHandler.ModuleHandler, id: number, hostStop: {
|
|
52
|
+
stopping: boolean;
|
|
53
|
+
list: (() => Promise<void>)[];
|
|
54
|
+
}, options: ListenOptions): Listener;
|
|
55
|
+
/** manually pass a request through the listener (takes ownership of the request; will kill the connection if the listener is not running anymore) */
|
|
56
|
+
handleRequest(request: libHttp.IncomingMessage, response: libHttp.ServerResponse): Promise<void>;
|
|
57
|
+
/** manually pass an upgrade through the listener (takes ownership of the connection; immediately closes the connection if the listener is not running anymore) */
|
|
58
|
+
handleUpgrade(request: libHttp.IncomingMessage, socket: libStream.Duplex, head: Buffer): Promise<void>;
|
|
59
|
+
/** server this listener belongs to */
|
|
60
|
+
get server(): Server;
|
|
61
|
+
/** client configuration used for this listener */
|
|
62
|
+
get config(): libClient.BurntClientConfig;
|
|
63
|
+
/** stop the listener and return promise which resolves once fully stopped */
|
|
27
64
|
stop(): Promise<void>;
|
|
65
|
+
/** resolves once the server has stopped */
|
|
66
|
+
get stopped(): Promise<void>;
|
|
67
|
+
/** check if the server is still running */
|
|
68
|
+
get running(): boolean;
|
|
28
69
|
on<K extends keyof ListenerEvents>(event: K, listener: ListenerEvents[K]): Listener;
|
|
29
|
-
off<K extends keyof ListenerEvents>(event: K, listener: ListenerEvents[K]): Listener;
|
|
30
70
|
once<K extends keyof ListenerEvents>(event: K, listener: ListenerEvents[K]): Listener;
|
|
71
|
+
off<K extends keyof ListenerEvents>(event: K, listener: ListenerEvents[K]): Listener;
|
|
31
72
|
}
|
|
32
|
-
|
|
33
|
-
'listening': (address: libNet.AddressInfo) => void;
|
|
34
|
-
'failed': (err: Error) => void;
|
|
35
|
-
'stopped': () => void;
|
|
36
|
-
};
|
|
73
|
+
/** server order: (tls > server > shallow > http.Server) */
|
|
37
74
|
export interface ListenOptions {
|
|
75
|
+
/** port to listen on (omit/0 for an OS-assigned port) */
|
|
38
76
|
port?: number;
|
|
77
|
+
/** hostname/interface to bind to (omit to listen on all interfaces) */
|
|
39
78
|
hostname?: string;
|
|
79
|
+
/** client configuration to use for this listener, otherwise the server's is used */
|
|
40
80
|
client?: libClient.ClientConfig | libClient.BurntClientConfig;
|
|
81
|
+
/** tls configuration to be used */
|
|
41
82
|
tls?: {
|
|
42
83
|
key: string;
|
|
43
84
|
cert: string;
|
|
44
85
|
};
|
|
86
|
+
/** custom configured server to be used (connectionsCheckingInterval must be configured
|
|
87
|
+
* accordingly beforehand; ownership will be taken; secure to encode https compared to http) */
|
|
45
88
|
server?: {
|
|
46
89
|
server: libHttp.Server;
|
|
47
90
|
secure: boolean;
|
|
48
91
|
};
|
|
92
|
+
/** create a serverless listener, designed to only be passed connections to */
|
|
93
|
+
serverless?: {
|
|
94
|
+
secure: boolean;
|
|
95
|
+
};
|
|
49
96
|
}
|
|
97
|
+
/** wrapper to create a simple server */
|
|
50
98
|
export declare function createServer(config?: ServerConfig): Server;
|
|
51
99
|
export interface ServerConfig {
|
|
100
|
+
/** logging string used for the server (default: server) */
|
|
101
|
+
name?: string;
|
|
102
|
+
/** default timeout for request headers to be fully received [0 disables the timeout; in milliseconds; Default: 30_000] */
|
|
52
103
|
headerTimeout?: number;
|
|
104
|
+
/** default inactivity timeout — connection is closed if no data is sent or received; resets on any I/O activity, so active transfers are not affected;
|
|
105
|
+
* is temporarily cleared by clients, which handle it themselves via throughput [0 disables the timeout; in milliseconds; Default: 90_000] */
|
|
53
106
|
connectionTimeout?: number;
|
|
107
|
+
/** idle time allowed between requests before closing a keep-alive connection [0 falls back to connectionTimeout; in milliseconds; Default: 10_000] */
|
|
54
108
|
keepAliveTimeout?: number;
|
|
109
|
+
/** default client configuration to be used */
|
|
55
110
|
client?: libClient.ClientConfig | libClient.BurntClientConfig;
|
|
111
|
+
/** default cache configuration to be used
|
|
112
|
+
* Important: cache host should be shared where possible as otherwise multiple unshared caches could exist and immutable ids might overwrite each other */
|
|
56
113
|
cache?: libCache.CacheHost | libCache.CacheConfig | libCache.BurntCacheConfig;
|
|
57
114
|
}
|
|
58
115
|
export declare class BurntServerConfig {
|