routup 3.0.0-alpha.3 → 3.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 +23 -19
- package/dist/adapters/node/module.d.ts +7 -0
- package/dist/{utils → adapters/raw}/header.d.ts +1 -1
- package/dist/{layer → adapters/raw}/index.d.ts +1 -1
- package/dist/adapters/raw/module.d.ts +4 -0
- package/dist/{dispatcher/adapters → adapters}/raw/type.d.ts +1 -1
- package/dist/adapters/web/module.d.ts +4 -0
- package/dist/constants.d.ts +7 -7
- package/dist/dispatcher/event/dispatch.d.ts +4 -0
- package/dist/dispatcher/event/error.d.ts +5 -0
- package/dist/dispatcher/event/index.d.ts +5 -0
- package/dist/dispatcher/event/is.d.ts +3 -0
- package/dist/dispatcher/event/module.d.ts +56 -0
- package/dist/dispatcher/event/types.d.ts +9 -0
- package/dist/dispatcher/index.d.ts +1 -2
- package/dist/dispatcher/type.d.ts +2 -30
- package/dist/error/create.d.ts +3 -3
- package/dist/error/is.d.ts +2 -2
- package/dist/error/module.d.ts +1 -1
- package/dist/handler/constants.d.ts +1 -0
- package/dist/handler/core/define.d.ts +4 -3
- package/dist/handler/core/types.d.ts +3 -3
- package/dist/handler/error/define.d.ts +4 -3
- package/dist/handler/error/types.d.ts +5 -5
- package/dist/handler/index.d.ts +1 -0
- package/dist/handler/is.d.ts +3 -1
- package/dist/handler/module.d.ts +23 -0
- package/dist/handler/types-base.d.ts +6 -2
- package/dist/handler/types.d.ts +3 -4
- package/dist/hook/constants.d.ts +8 -0
- package/dist/hook/index.d.ts +3 -0
- package/dist/hook/module.d.ts +19 -0
- package/dist/hook/types.d.ts +5 -0
- package/dist/index.cjs +658 -468
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.mjs +649 -461
- package/dist/index.mjs.map +1 -1
- package/dist/plugin/types.d.ts +0 -5
- package/dist/response/helpers/send-web-blob.d.ts +1 -1
- package/dist/response/helpers/send-web-response.d.ts +1 -1
- package/dist/router/constants.d.ts +8 -0
- package/dist/router/index.d.ts +0 -1
- package/dist/router/module.d.ts +58 -24
- package/dist/router/types.d.ts +7 -0
- package/dist/types.d.ts +1 -0
- package/dist/utils/index.d.ts +2 -1
- package/dist/utils/method.d.ts +3 -0
- package/dist/utils/next.d.ts +2 -0
- package/package.json +8 -8
- package/dist/dispatcher/adapters/node/module.d.ts +0 -7
- package/dist/dispatcher/adapters/raw/module.d.ts +0 -4
- package/dist/dispatcher/adapters/web/index.d.ts +0 -2
- package/dist/dispatcher/adapters/web/module.d.ts +0 -5
- package/dist/dispatcher/utils.d.ts +0 -5
- package/dist/layer/constants.d.ts +0 -1
- package/dist/layer/module.d.ts +0 -17
- package/dist/layer/type.d.ts +0 -8
- package/dist/layer/utils.d.ts +0 -2
- /package/dist/{dispatcher/adapters → adapters}/index.d.ts +0 -0
- /package/dist/{dispatcher/adapters → adapters}/node/index.d.ts +0 -0
- /package/dist/{dispatcher/adapters/raw → adapters/web}/index.d.ts +0 -0
- /package/dist/{dispatcher/adapters → adapters}/web/type.d.ts +0 -0
package/dist/index.mjs
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { HTTPError } from '@ebec/http';
|
|
2
1
|
import { merge, hasOwnProperty, distinctArray } from 'smob';
|
|
3
2
|
import { Buffer } from 'buffer';
|
|
4
3
|
import { subtle } from 'uncrypto';
|
|
@@ -6,17 +5,18 @@ import { compile, all } from 'proxy-addr';
|
|
|
6
5
|
import { getType, get } from 'mime-explorer';
|
|
7
6
|
import Negotiator from 'negotiator';
|
|
8
7
|
import { Readable, Writable } from 'readable-stream';
|
|
8
|
+
import { HTTPError } from '@ebec/http';
|
|
9
9
|
import { pathToRegexp } from 'path-to-regexp';
|
|
10
10
|
|
|
11
11
|
var MethodName;
|
|
12
12
|
(function(MethodName) {
|
|
13
|
-
MethodName["GET"] = "
|
|
14
|
-
MethodName["POST"] = "
|
|
15
|
-
MethodName["PUT"] = "
|
|
16
|
-
MethodName["PATCH"] = "
|
|
17
|
-
MethodName["DELETE"] = "
|
|
18
|
-
MethodName["OPTIONS"] = "
|
|
19
|
-
MethodName["HEAD"] = "
|
|
13
|
+
MethodName["GET"] = "GET";
|
|
14
|
+
MethodName["POST"] = "POST";
|
|
15
|
+
MethodName["PUT"] = "PUT";
|
|
16
|
+
MethodName["PATCH"] = "PATCH";
|
|
17
|
+
MethodName["DELETE"] = "DELETE";
|
|
18
|
+
MethodName["OPTIONS"] = "OPTIONS";
|
|
19
|
+
MethodName["HEAD"] = "HEAD";
|
|
20
20
|
})(MethodName || (MethodName = {}));
|
|
21
21
|
var HeaderName;
|
|
22
22
|
(function(HeaderName) {
|
|
@@ -51,32 +51,6 @@ var HeaderName;
|
|
|
51
51
|
HeaderName["X_FORWARDED_PROTO"] = "x-forwarded-proto";
|
|
52
52
|
})(HeaderName || (HeaderName = {}));
|
|
53
53
|
|
|
54
|
-
class ErrorProxy extends HTTPError {
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
function isError(input) {
|
|
58
|
-
return input instanceof ErrorProxy;
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
/**
|
|
62
|
-
* Create an error proxy by
|
|
63
|
-
* - an existing error (accessible via cause property)
|
|
64
|
-
* - options
|
|
65
|
-
* - message
|
|
66
|
-
*
|
|
67
|
-
* @param input
|
|
68
|
-
*/ function createError(input) {
|
|
69
|
-
if (isError(input)) {
|
|
70
|
-
return input;
|
|
71
|
-
}
|
|
72
|
-
if (typeof input === 'string') {
|
|
73
|
-
return new ErrorProxy(input);
|
|
74
|
-
}
|
|
75
|
-
return new ErrorProxy({
|
|
76
|
-
cause: input
|
|
77
|
-
}, input);
|
|
78
|
-
}
|
|
79
|
-
|
|
80
54
|
function isRequestCacheable(req, modifiedTime) {
|
|
81
55
|
const modifiedSince = req.headers[HeaderName.IF_MODIFIED_SINCE];
|
|
82
56
|
if (!modifiedSince) {
|
|
@@ -207,33 +181,6 @@ function setRequestHeader(req, name, value) {
|
|
|
207
181
|
return cookiesStrings;
|
|
208
182
|
}
|
|
209
183
|
|
|
210
|
-
function transformHeaderToTuples(key, value) {
|
|
211
|
-
const output = [];
|
|
212
|
-
if (Array.isArray(value)) {
|
|
213
|
-
for(let j = 0; j < value.length; j++){
|
|
214
|
-
output.push([
|
|
215
|
-
key,
|
|
216
|
-
value[j]
|
|
217
|
-
]);
|
|
218
|
-
}
|
|
219
|
-
} else if (value !== undefined) {
|
|
220
|
-
output.push([
|
|
221
|
-
key,
|
|
222
|
-
String(value)
|
|
223
|
-
]);
|
|
224
|
-
}
|
|
225
|
-
return output;
|
|
226
|
-
}
|
|
227
|
-
function transformHeadersToTuples(input) {
|
|
228
|
-
const output = [];
|
|
229
|
-
const keys = Object.keys(input);
|
|
230
|
-
for(let i = 0; i < keys.length; i++){
|
|
231
|
-
const key = keys[i].toLowerCase();
|
|
232
|
-
output.push(...transformHeaderToTuples(key, input[key]));
|
|
233
|
-
}
|
|
234
|
-
return output;
|
|
235
|
-
}
|
|
236
|
-
|
|
237
184
|
function isObject(item) {
|
|
238
185
|
return !!item && typeof item === 'object' && !Array.isArray(item);
|
|
239
186
|
}
|
|
@@ -346,6 +293,15 @@ function getCharsetForMimeType(type) {
|
|
|
346
293
|
return undefined;
|
|
347
294
|
}
|
|
348
295
|
|
|
296
|
+
function toMethodName(input, alt) {
|
|
297
|
+
if (input) {
|
|
298
|
+
return input.toUpperCase();
|
|
299
|
+
}
|
|
300
|
+
return alt;
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
const nextPlaceholder = (_err)=>{};
|
|
304
|
+
|
|
349
305
|
/**
|
|
350
306
|
* Based on https://github.com/unjs/pathe v1.1.1 (055f50a6f1131f4e5c56cf259dd8816168fba329)
|
|
351
307
|
*/ function normalizeWindowsPath(input = '') {
|
|
@@ -749,6 +705,35 @@ function createRequest(context) {
|
|
|
749
705
|
return readable;
|
|
750
706
|
}
|
|
751
707
|
|
|
708
|
+
class RoutupError extends HTTPError {
|
|
709
|
+
}
|
|
710
|
+
|
|
711
|
+
function isError(input) {
|
|
712
|
+
return input instanceof RoutupError;
|
|
713
|
+
}
|
|
714
|
+
|
|
715
|
+
/**
|
|
716
|
+
* Create an internal error object by
|
|
717
|
+
* - an existing error (accessible via cause property)
|
|
718
|
+
* - options
|
|
719
|
+
* - message
|
|
720
|
+
*
|
|
721
|
+
* @param input
|
|
722
|
+
*/ function createError(input) {
|
|
723
|
+
if (isError(input)) {
|
|
724
|
+
return input;
|
|
725
|
+
}
|
|
726
|
+
if (typeof input === 'string') {
|
|
727
|
+
return new RoutupError(input);
|
|
728
|
+
}
|
|
729
|
+
if (!isObject(input)) {
|
|
730
|
+
return new RoutupError();
|
|
731
|
+
}
|
|
732
|
+
return new RoutupError({
|
|
733
|
+
cause: input
|
|
734
|
+
}, input);
|
|
735
|
+
}
|
|
736
|
+
|
|
752
737
|
function setResponseCacheHeaders(res, options) {
|
|
753
738
|
options = options || {};
|
|
754
739
|
const cacheControls = [
|
|
@@ -904,7 +889,7 @@ async function send(res, chunk) {
|
|
|
904
889
|
const etagFn = findRouterOption('etag', useRequestRouterPath(res.req));
|
|
905
890
|
const chunkHash = await etagFn(chunk, encoding, len);
|
|
906
891
|
if (isResponseGone(res)) {
|
|
907
|
-
return
|
|
892
|
+
return;
|
|
908
893
|
}
|
|
909
894
|
if (typeof chunkHash === 'string') {
|
|
910
895
|
res.setHeader(HeaderName.ETag, chunkHash);
|
|
@@ -925,23 +910,22 @@ async function send(res, chunk) {
|
|
|
925
910
|
res.removeHeader(HeaderName.TRANSFER_ENCODING);
|
|
926
911
|
}
|
|
927
912
|
if (isResponseGone(res)) {
|
|
928
|
-
return
|
|
913
|
+
return;
|
|
929
914
|
}
|
|
930
|
-
if (res.req.method === 'HEAD') {
|
|
915
|
+
if (res.req.method === 'HEAD' || res.req.method === 'head') {
|
|
931
916
|
// skip body for HEAD
|
|
932
917
|
res.end();
|
|
933
|
-
return
|
|
918
|
+
return;
|
|
934
919
|
}
|
|
935
920
|
if (typeof chunk === 'undefined' || chunk === null) {
|
|
936
921
|
res.end();
|
|
937
|
-
return
|
|
922
|
+
return;
|
|
938
923
|
}
|
|
939
924
|
if (typeof encoding !== 'undefined') {
|
|
940
925
|
res.end(chunk, encoding);
|
|
941
|
-
return
|
|
926
|
+
return;
|
|
942
927
|
}
|
|
943
928
|
res.end(chunk);
|
|
944
|
-
return Promise.resolve();
|
|
945
929
|
}
|
|
946
930
|
|
|
947
931
|
function sendAccepted(res, chunk) {
|
|
@@ -1087,7 +1071,7 @@ function sendRedirect(res, location, statusCode = 302) {
|
|
|
1087
1071
|
return send(res, html);
|
|
1088
1072
|
}
|
|
1089
1073
|
|
|
1090
|
-
function sendWebResponse(res, webResponse) {
|
|
1074
|
+
async function sendWebResponse(res, webResponse) {
|
|
1091
1075
|
if (webResponse.redirected) {
|
|
1092
1076
|
res.setHeader(HeaderName.LOCATION, webResponse.url);
|
|
1093
1077
|
}
|
|
@@ -1105,15 +1089,16 @@ function sendWebResponse(res, webResponse) {
|
|
|
1105
1089
|
}
|
|
1106
1090
|
});
|
|
1107
1091
|
if (webResponse.body) {
|
|
1108
|
-
|
|
1092
|
+
await sendStream(res, webResponse.body);
|
|
1093
|
+
return Promise.resolve();
|
|
1109
1094
|
}
|
|
1110
1095
|
res.end();
|
|
1111
1096
|
return Promise.resolve();
|
|
1112
1097
|
}
|
|
1113
1098
|
|
|
1114
|
-
function sendWebBlob(res, blob) {
|
|
1099
|
+
async function sendWebBlob(res, blob) {
|
|
1115
1100
|
setResponseHeaderContentType(res, blob.type);
|
|
1116
|
-
|
|
1101
|
+
await sendStream(res, blob.stream());
|
|
1117
1102
|
}
|
|
1118
1103
|
|
|
1119
1104
|
function createResponse(request) {
|
|
@@ -1261,84 +1246,130 @@ function createResponse(request) {
|
|
|
1261
1246
|
return writable;
|
|
1262
1247
|
}
|
|
1263
1248
|
|
|
1264
|
-
function
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
params: input.params || {},
|
|
1268
|
-
path: input.path || '/',
|
|
1269
|
-
routerPath: []
|
|
1270
|
-
};
|
|
1271
|
-
}
|
|
1272
|
-
function cloneDispatcherMeta(input) {
|
|
1273
|
-
return {
|
|
1274
|
-
path: input.path,
|
|
1275
|
-
mountPath: input.mountPath,
|
|
1276
|
-
error: input.error,
|
|
1277
|
-
routerPath: [
|
|
1278
|
-
...input.routerPath
|
|
1279
|
-
],
|
|
1280
|
-
params: cloneDispatcherMetaParams(input.params)
|
|
1281
|
-
};
|
|
1282
|
-
}
|
|
1283
|
-
function cloneDispatcherMetaParams(input) {
|
|
1284
|
-
if (typeof input === 'undefined') {
|
|
1285
|
-
return {};
|
|
1249
|
+
async function sendData(event, chunk) {
|
|
1250
|
+
if (chunk instanceof Error) {
|
|
1251
|
+
return Promise.reject(createError(chunk));
|
|
1286
1252
|
}
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
return
|
|
1253
|
+
if (isStream(chunk)) {
|
|
1254
|
+
await sendStream(event.response, chunk);
|
|
1255
|
+
return Promise.resolve();
|
|
1290
1256
|
}
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1257
|
+
if (isWebBlob(chunk)) {
|
|
1258
|
+
await sendWebBlob(event.response, chunk);
|
|
1259
|
+
return Promise.resolve();
|
|
1294
1260
|
}
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
if (!t1 && !t2) {
|
|
1299
|
-
return {};
|
|
1261
|
+
if (isWebResponse(chunk)) {
|
|
1262
|
+
await sendWebResponse(event.response, chunk);
|
|
1263
|
+
return Promise.resolve();
|
|
1300
1264
|
}
|
|
1301
|
-
|
|
1302
|
-
|
|
1265
|
+
return send(event.response, chunk);
|
|
1266
|
+
}
|
|
1267
|
+
function dispatch(event, target) {
|
|
1268
|
+
setRequestParams(event.request, event.params);
|
|
1269
|
+
setRequestMountPath(event.request, event.mountPath);
|
|
1270
|
+
setRequestRouterPath(event.request, event.routerPath);
|
|
1271
|
+
return new Promise((resolve, reject)=>{
|
|
1272
|
+
let handled = false;
|
|
1273
|
+
const unsubscribe = ()=>{
|
|
1274
|
+
event.response.off('close', done);
|
|
1275
|
+
event.response.off('error', done);
|
|
1276
|
+
};
|
|
1277
|
+
const shutdown = (dispatched, err)=>{
|
|
1278
|
+
if (handled) {
|
|
1279
|
+
return;
|
|
1280
|
+
}
|
|
1281
|
+
handled = true;
|
|
1282
|
+
unsubscribe();
|
|
1283
|
+
if (err) {
|
|
1284
|
+
reject(createError(err));
|
|
1285
|
+
} else {
|
|
1286
|
+
resolve(dispatched);
|
|
1287
|
+
}
|
|
1288
|
+
};
|
|
1289
|
+
const done = (err)=>shutdown(true, err);
|
|
1290
|
+
const next = (err)=>shutdown(false, err);
|
|
1291
|
+
event.response.once('close', done);
|
|
1292
|
+
event.response.once('error', done);
|
|
1293
|
+
const handle = async (data)=>{
|
|
1294
|
+
if (typeof data === 'undefined' || handled) {
|
|
1295
|
+
return false;
|
|
1296
|
+
}
|
|
1297
|
+
handled = true;
|
|
1298
|
+
unsubscribe();
|
|
1299
|
+
if (!event.dispatched) {
|
|
1300
|
+
await sendData(event, data);
|
|
1301
|
+
}
|
|
1302
|
+
return true;
|
|
1303
|
+
};
|
|
1304
|
+
try {
|
|
1305
|
+
const output = target(next);
|
|
1306
|
+
if (isPromise(output)) {
|
|
1307
|
+
output.then((r)=>handle(r)).then((resolved)=>{
|
|
1308
|
+
if (resolved) {
|
|
1309
|
+
resolve(true);
|
|
1310
|
+
}
|
|
1311
|
+
}).catch((e)=>reject(createError(e)));
|
|
1312
|
+
return;
|
|
1313
|
+
}
|
|
1314
|
+
Promise.resolve().then(()=>handle(output)).then((resolved)=>{
|
|
1315
|
+
if (resolved) {
|
|
1316
|
+
resolve(true);
|
|
1317
|
+
}
|
|
1318
|
+
}).catch((e)=>reject(createError(e)));
|
|
1319
|
+
} catch (error) {
|
|
1320
|
+
next(error);
|
|
1321
|
+
}
|
|
1322
|
+
});
|
|
1323
|
+
}
|
|
1324
|
+
|
|
1325
|
+
function isDispatcherErrorEvent(event) {
|
|
1326
|
+
return typeof event.error !== 'undefined';
|
|
1327
|
+
}
|
|
1328
|
+
|
|
1329
|
+
class DispatchEvent {
|
|
1330
|
+
get dispatched() {
|
|
1331
|
+
return this._dispatched || this.response.writableEnded || this.response.headersSent;
|
|
1303
1332
|
}
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
return t1;
|
|
1333
|
+
set dispatched(value) {
|
|
1334
|
+
this._dispatched = value;
|
|
1307
1335
|
}
|
|
1308
|
-
|
|
1309
|
-
|
|
1336
|
+
constructor(context){
|
|
1337
|
+
this.request = context.request;
|
|
1338
|
+
this.response = context.response;
|
|
1339
|
+
this.method = context.method || MethodName.GET;
|
|
1340
|
+
this.methodsAllowed = [];
|
|
1341
|
+
this.mountPath = '/';
|
|
1342
|
+
this.params = {};
|
|
1343
|
+
this.path = context.path || '/';
|
|
1344
|
+
this.routerPath = [];
|
|
1345
|
+
this.next = nextPlaceholder;
|
|
1310
1346
|
}
|
|
1311
|
-
return t1;
|
|
1312
1347
|
}
|
|
1313
1348
|
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
if (
|
|
1331
|
-
|
|
1332
|
-
res.statusCode = e.statusCode;
|
|
1333
|
-
if (e.statusMessage) {
|
|
1334
|
-
res.statusMessage = e.statusMessage;
|
|
1335
|
-
}
|
|
1336
|
-
} else {
|
|
1337
|
-
res.statusCode = 500;
|
|
1338
|
-
}
|
|
1339
|
-
res.end();
|
|
1349
|
+
class DispatchErrorEvent extends DispatchEvent {
|
|
1350
|
+
}
|
|
1351
|
+
|
|
1352
|
+
async function dispatchNodeRequest(router, request, response) {
|
|
1353
|
+
const event = new DispatchEvent({
|
|
1354
|
+
request,
|
|
1355
|
+
response,
|
|
1356
|
+
path: useRequestPath(request),
|
|
1357
|
+
method: toMethodName(request.method, MethodName.GET)
|
|
1358
|
+
});
|
|
1359
|
+
await router.dispatch(event);
|
|
1360
|
+
if (event.dispatched) {
|
|
1361
|
+
return;
|
|
1362
|
+
}
|
|
1363
|
+
if (event.error) {
|
|
1364
|
+
event.response.statusCode = event.error.statusCode;
|
|
1365
|
+
if (event.error.statusMessage) {
|
|
1366
|
+
event.response.statusMessage = event.error.statusMessage;
|
|
1340
1367
|
}
|
|
1368
|
+
event.response.end();
|
|
1369
|
+
return;
|
|
1341
1370
|
}
|
|
1371
|
+
event.response.statusCode = 404;
|
|
1372
|
+
event.response.end();
|
|
1342
1373
|
}
|
|
1343
1374
|
function createNodeDispatcher(router) {
|
|
1344
1375
|
return (req, res)=>{
|
|
@@ -1347,10 +1378,38 @@ function createNodeDispatcher(router) {
|
|
|
1347
1378
|
};
|
|
1348
1379
|
}
|
|
1349
1380
|
|
|
1350
|
-
|
|
1381
|
+
function transformHeaderToTuples(key, value) {
|
|
1382
|
+
const output = [];
|
|
1383
|
+
if (Array.isArray(value)) {
|
|
1384
|
+
for(let j = 0; j < value.length; j++){
|
|
1385
|
+
output.push([
|
|
1386
|
+
key,
|
|
1387
|
+
value[j]
|
|
1388
|
+
]);
|
|
1389
|
+
}
|
|
1390
|
+
} else if (value !== undefined) {
|
|
1391
|
+
output.push([
|
|
1392
|
+
key,
|
|
1393
|
+
String(value)
|
|
1394
|
+
]);
|
|
1395
|
+
}
|
|
1396
|
+
return output;
|
|
1397
|
+
}
|
|
1398
|
+
function transformHeadersToTuples(input) {
|
|
1399
|
+
const output = [];
|
|
1400
|
+
const keys = Object.keys(input);
|
|
1401
|
+
for(let i = 0; i < keys.length; i++){
|
|
1402
|
+
const key = keys[i].toLowerCase();
|
|
1403
|
+
output.push(...transformHeaderToTuples(key, input[key]));
|
|
1404
|
+
}
|
|
1405
|
+
return output;
|
|
1406
|
+
}
|
|
1407
|
+
|
|
1408
|
+
async function dispatchRawRequest(router, request) {
|
|
1409
|
+
const method = toMethodName(request.method, MethodName.GET);
|
|
1351
1410
|
const req = createRequest({
|
|
1352
1411
|
url: request.path,
|
|
1353
|
-
method
|
|
1412
|
+
method,
|
|
1354
1413
|
body: request.body,
|
|
1355
1414
|
headers: request.headers
|
|
1356
1415
|
});
|
|
@@ -1375,52 +1434,45 @@ async function dispatchRawRequest(router, request, options = {}) {
|
|
|
1375
1434
|
headers: getHeaders(),
|
|
1376
1435
|
body: res.body
|
|
1377
1436
|
});
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
status: 404
|
|
1390
|
-
});
|
|
1391
|
-
} catch (e) {
|
|
1392
|
-
if (options.throwOnError) {
|
|
1393
|
-
throw e;
|
|
1394
|
-
}
|
|
1395
|
-
if (isError(e)) {
|
|
1396
|
-
return createRawResponse({
|
|
1397
|
-
status: e.statusCode,
|
|
1398
|
-
statusMessage: e.statusMessage
|
|
1399
|
-
});
|
|
1400
|
-
}
|
|
1437
|
+
const event = new DispatchEvent({
|
|
1438
|
+
request: req,
|
|
1439
|
+
response: res,
|
|
1440
|
+
path: request.path,
|
|
1441
|
+
method
|
|
1442
|
+
});
|
|
1443
|
+
await router.dispatch(event);
|
|
1444
|
+
if (event.dispatched) {
|
|
1445
|
+
return createRawResponse();
|
|
1446
|
+
}
|
|
1447
|
+
if (event.error) {
|
|
1401
1448
|
return createRawResponse({
|
|
1402
|
-
status:
|
|
1449
|
+
status: event.error.statusCode,
|
|
1450
|
+
statusMessage: event.error.statusMessage
|
|
1403
1451
|
});
|
|
1404
1452
|
}
|
|
1453
|
+
return createRawResponse({
|
|
1454
|
+
status: 404
|
|
1455
|
+
});
|
|
1405
1456
|
}
|
|
1406
1457
|
function createRawDispatcher(router) {
|
|
1407
1458
|
return async (request)=>dispatchRawRequest(router, request);
|
|
1408
1459
|
}
|
|
1409
1460
|
|
|
1410
|
-
async function dispatchWebRequest(router, request
|
|
1461
|
+
async function dispatchWebRequest(router, request) {
|
|
1411
1462
|
const url = new URL(request.url);
|
|
1412
1463
|
const headers = {};
|
|
1413
1464
|
request.headers.forEach((value, key)=>{
|
|
1414
1465
|
headers[key] = value;
|
|
1415
1466
|
});
|
|
1467
|
+
const method = toMethodName(request.method, MethodName.GET);
|
|
1416
1468
|
const res = await dispatchRawRequest(router, {
|
|
1417
|
-
method
|
|
1469
|
+
method,
|
|
1418
1470
|
path: url.pathname + url.search,
|
|
1419
1471
|
headers,
|
|
1420
1472
|
body: request.body
|
|
1421
|
-
}
|
|
1473
|
+
});
|
|
1422
1474
|
let body;
|
|
1423
|
-
if (
|
|
1475
|
+
if (method === MethodName.HEAD || res.status === 304 || res.status === 101 || res.status === 204 || res.status === 205) {
|
|
1424
1476
|
body = null;
|
|
1425
1477
|
} else {
|
|
1426
1478
|
body = res.body;
|
|
@@ -1440,35 +1492,98 @@ var HandlerType;
|
|
|
1440
1492
|
HandlerType["CORE"] = "core";
|
|
1441
1493
|
HandlerType["ERROR"] = "error";
|
|
1442
1494
|
})(HandlerType || (HandlerType = {}));
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1495
|
+
const HandlerSymbol = Symbol.for('Handler');
|
|
1496
|
+
|
|
1497
|
+
var HookName;
|
|
1498
|
+
(function(HookName) {
|
|
1499
|
+
HookName["ERROR"] = "error";
|
|
1500
|
+
HookName["DISPATCH_START"] = "dispatchStart";
|
|
1501
|
+
HookName["DISPATCH_END"] = "dispatchEnd";
|
|
1502
|
+
HookName["CHILD_MATCH"] = "childMatch";
|
|
1503
|
+
HookName["CHILD_DISPATCH_BEFORE"] = "childDispatchBefore";
|
|
1504
|
+
HookName["CHILD_DISPATCH_AFTER"] = "childDispatchAfter";
|
|
1505
|
+
})(HookName || (HookName = {}));
|
|
1506
|
+
|
|
1507
|
+
class HookManager {
|
|
1508
|
+
// --------------------------------------------------
|
|
1509
|
+
addListener(name, fn) {
|
|
1510
|
+
this.items[name] = this.items[name] || [];
|
|
1511
|
+
this.items[name].push(fn);
|
|
1512
|
+
return ()=>{
|
|
1513
|
+
this.removeListener(name, fn);
|
|
1449
1514
|
};
|
|
1450
1515
|
}
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1516
|
+
removeListener(name, fn) {
|
|
1517
|
+
if (!this.items[name]) {
|
|
1518
|
+
return;
|
|
1519
|
+
}
|
|
1520
|
+
if (typeof fn === 'undefined') {
|
|
1521
|
+
delete this.items[name];
|
|
1522
|
+
return;
|
|
1523
|
+
}
|
|
1524
|
+
if (typeof fn === 'function') {
|
|
1525
|
+
const index = this.items[name].indexOf(fn);
|
|
1526
|
+
if (index !== -1) {
|
|
1527
|
+
this.items[name].splice(index, 1);
|
|
1528
|
+
}
|
|
1529
|
+
}
|
|
1530
|
+
if (this.items[name].length === 0) {
|
|
1531
|
+
delete this.items[name];
|
|
1532
|
+
}
|
|
1533
|
+
}
|
|
1534
|
+
// --------------------------------------------------
|
|
1535
|
+
/**
|
|
1536
|
+
* @throws RoutupError
|
|
1537
|
+
*
|
|
1538
|
+
* @param name
|
|
1539
|
+
* @param event
|
|
1540
|
+
*/ async trigger(name, event) {
|
|
1541
|
+
if (!this.items[name] || this.items[name].length === 0) {
|
|
1542
|
+
return;
|
|
1543
|
+
}
|
|
1544
|
+
try {
|
|
1545
|
+
for(let i = 0; i < this.items[name].length; i++){
|
|
1546
|
+
const hook = this.items[name][i];
|
|
1547
|
+
event.dispatched = await dispatch(event, (next)=>Promise.resolve().then(()=>{
|
|
1548
|
+
event.next = next;
|
|
1549
|
+
return this.triggerListener(name, event, hook);
|
|
1550
|
+
}).catch((err)=>next(err)));
|
|
1551
|
+
event.next = nextPlaceholder;
|
|
1552
|
+
if (event.dispatched) {
|
|
1553
|
+
if (event.error) {
|
|
1554
|
+
event.error = undefined;
|
|
1555
|
+
}
|
|
1556
|
+
return;
|
|
1557
|
+
}
|
|
1558
|
+
}
|
|
1559
|
+
} catch (e) {
|
|
1560
|
+
event.error = e;
|
|
1561
|
+
if (!this.isErrorListenerHook(name)) {
|
|
1562
|
+
await this.trigger(HookName.ERROR, event);
|
|
1563
|
+
if (event.dispatched) {
|
|
1564
|
+
if (event.error) {
|
|
1565
|
+
event.error = undefined;
|
|
1566
|
+
}
|
|
1567
|
+
}
|
|
1568
|
+
}
|
|
1569
|
+
}
|
|
1570
|
+
}
|
|
1571
|
+
triggerListener(name, event, listener) {
|
|
1572
|
+
if (this.isErrorListenerHook(name)) {
|
|
1573
|
+
if (isDispatcherErrorEvent(event)) {
|
|
1574
|
+
return listener(event);
|
|
1575
|
+
}
|
|
1576
|
+
return undefined;
|
|
1577
|
+
}
|
|
1578
|
+
return listener(event);
|
|
1579
|
+
}
|
|
1580
|
+
isErrorListenerHook(input) {
|
|
1581
|
+
return input === HookName.ERROR;
|
|
1582
|
+
}
|
|
1583
|
+
// --------------------------------------------------
|
|
1584
|
+
constructor(){
|
|
1585
|
+
this.items = {};
|
|
1463
1586
|
}
|
|
1464
|
-
return {
|
|
1465
|
-
type: HandlerType.ERROR,
|
|
1466
|
-
...input
|
|
1467
|
-
};
|
|
1468
|
-
}
|
|
1469
|
-
|
|
1470
|
-
function isHandler(input) {
|
|
1471
|
-
return isObject(input) && typeof input.fn === 'function' && typeof input.type === 'string';
|
|
1472
1587
|
}
|
|
1473
1588
|
|
|
1474
1589
|
function decodeParam(val) {
|
|
@@ -1526,93 +1641,59 @@ function isPath(input) {
|
|
|
1526
1641
|
return typeof input === 'string' || input instanceof RegExp;
|
|
1527
1642
|
}
|
|
1528
1643
|
|
|
1529
|
-
|
|
1530
|
-
|
|
1531
|
-
class Layer {
|
|
1644
|
+
class Handler {
|
|
1532
1645
|
// --------------------------------------------------
|
|
1533
1646
|
get type() {
|
|
1534
|
-
return this.
|
|
1647
|
+
return this.config.type;
|
|
1535
1648
|
}
|
|
1536
1649
|
get path() {
|
|
1537
|
-
return this.
|
|
1650
|
+
return this.config.path;
|
|
1538
1651
|
}
|
|
1539
1652
|
get method() {
|
|
1540
|
-
|
|
1653
|
+
if (this._method || !this.config.method) {
|
|
1654
|
+
return this._method;
|
|
1655
|
+
}
|
|
1656
|
+
this._method = toMethodName(this.config.method);
|
|
1657
|
+
return this._method;
|
|
1541
1658
|
}
|
|
1542
1659
|
// --------------------------------------------------
|
|
1543
|
-
dispatch(event
|
|
1660
|
+
async dispatch(event) {
|
|
1544
1661
|
if (this.pathMatcher) {
|
|
1545
|
-
const pathMatch = this.pathMatcher.exec(
|
|
1662
|
+
const pathMatch = this.pathMatcher.exec(event.path);
|
|
1546
1663
|
if (pathMatch) {
|
|
1547
|
-
|
|
1664
|
+
event.params = {
|
|
1665
|
+
...event.params,
|
|
1666
|
+
...pathMatch.params
|
|
1667
|
+
};
|
|
1548
1668
|
}
|
|
1549
1669
|
}
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
const shutdown = (dispatched, err)=>{
|
|
1560
|
-
if (handled) {
|
|
1561
|
-
return;
|
|
1562
|
-
}
|
|
1563
|
-
handled = true;
|
|
1564
|
-
unsubscribe();
|
|
1565
|
-
if (err) {
|
|
1566
|
-
reject(createError(err));
|
|
1567
|
-
} else {
|
|
1568
|
-
resolve(dispatched);
|
|
1569
|
-
}
|
|
1570
|
-
};
|
|
1571
|
-
const onFinished = (err)=>shutdown(true, err);
|
|
1572
|
-
const onNext = (err)=>shutdown(false, err);
|
|
1573
|
-
event.res.once('close', onFinished);
|
|
1574
|
-
event.res.once('error', onFinished);
|
|
1575
|
-
const handle = (data)=>{
|
|
1576
|
-
if (typeof data === 'undefined' || handled) {
|
|
1577
|
-
return Promise.resolve();
|
|
1578
|
-
}
|
|
1579
|
-
handled = true;
|
|
1580
|
-
unsubscribe();
|
|
1581
|
-
return this.sendOutput(event.res, data).then(()=>resolve(true)).catch((e)=>reject(createError(e)));
|
|
1582
|
-
};
|
|
1583
|
-
try {
|
|
1584
|
-
let output;
|
|
1585
|
-
if (this.handler.type === HandlerType.ERROR) {
|
|
1586
|
-
if (meta.error) {
|
|
1587
|
-
output = this.handler.fn(meta.error, event.req, event.res, onNext);
|
|
1670
|
+
await this.hookManager.trigger(HookName.CHILD_DISPATCH_BEFORE, event);
|
|
1671
|
+
if (event.dispatched) {
|
|
1672
|
+
return Promise.resolve();
|
|
1673
|
+
}
|
|
1674
|
+
try {
|
|
1675
|
+
event.dispatched = await dispatch(event, (done)=>{
|
|
1676
|
+
if (this.config.type === HandlerType.ERROR) {
|
|
1677
|
+
if (event.error) {
|
|
1678
|
+
return this.config.fn(event.error, event.request, event.response, done);
|
|
1588
1679
|
}
|
|
1589
1680
|
} else {
|
|
1590
|
-
|
|
1681
|
+
return this.config.fn(event.request, event.response, done);
|
|
1591
1682
|
}
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
1683
|
+
return undefined;
|
|
1684
|
+
});
|
|
1685
|
+
} catch (e) {
|
|
1686
|
+
if (isError(e)) {
|
|
1687
|
+
event.error = e;
|
|
1688
|
+
await this.hookManager.trigger(HookName.ERROR, event);
|
|
1689
|
+
if (event.dispatched) {
|
|
1690
|
+
event.error = undefined;
|
|
1691
|
+
} else {
|
|
1692
|
+
throw e;
|
|
1595
1693
|
}
|
|
1596
|
-
Promise.resolve().then(()=>handle(output)).catch((e)=>reject(createError(e)));
|
|
1597
|
-
} catch (error) {
|
|
1598
|
-
onNext(error);
|
|
1599
1694
|
}
|
|
1600
|
-
});
|
|
1601
|
-
}
|
|
1602
|
-
sendOutput(res, input) {
|
|
1603
|
-
if (input instanceof Error) {
|
|
1604
|
-
return Promise.reject(createError(input));
|
|
1605
|
-
}
|
|
1606
|
-
if (isStream(input)) {
|
|
1607
|
-
return sendStream(res, input);
|
|
1608
1695
|
}
|
|
1609
|
-
|
|
1610
|
-
return sendWebBlob(res, input);
|
|
1611
|
-
}
|
|
1612
|
-
if (isWebResponse(input)) {
|
|
1613
|
-
return sendWebResponse(res, input);
|
|
1614
|
-
}
|
|
1615
|
-
return send(res, input);
|
|
1696
|
+
return this.hookManager.trigger(HookName.CHILD_DISPATCH_AFTER, event);
|
|
1616
1697
|
}
|
|
1617
1698
|
// --------------------------------------------------
|
|
1618
1699
|
matchPath(path) {
|
|
@@ -1621,30 +1702,81 @@ class Layer {
|
|
|
1621
1702
|
}
|
|
1622
1703
|
return this.pathMatcher.test(path);
|
|
1623
1704
|
}
|
|
1705
|
+
setPath(path) {
|
|
1706
|
+
if (typeof path === 'string') {
|
|
1707
|
+
path = withLeadingSlash(path);
|
|
1708
|
+
}
|
|
1709
|
+
this.config.path = path;
|
|
1710
|
+
if (typeof path === 'undefined') {
|
|
1711
|
+
this.pathMatcher = undefined;
|
|
1712
|
+
return;
|
|
1713
|
+
}
|
|
1714
|
+
this.pathMatcher = new PathMatcher(path, {
|
|
1715
|
+
end: !!this.config.method
|
|
1716
|
+
});
|
|
1717
|
+
}
|
|
1718
|
+
// --------------------------------------------------
|
|
1624
1719
|
matchMethod(method) {
|
|
1625
|
-
|
|
1626
|
-
|
|
1720
|
+
return !this.method || method === this.method || method === MethodName.HEAD && this.method === MethodName.GET;
|
|
1721
|
+
}
|
|
1722
|
+
setMethod(input) {
|
|
1723
|
+
const method = toMethodName(input);
|
|
1724
|
+
this.config.method = method;
|
|
1725
|
+
this._method = method;
|
|
1726
|
+
}
|
|
1727
|
+
// --------------------------------------------------
|
|
1728
|
+
mountHooks() {
|
|
1729
|
+
if (this.config.onBefore) {
|
|
1730
|
+
this.hookManager.addListener(HookName.CHILD_DISPATCH_BEFORE, this.config.onBefore);
|
|
1627
1731
|
}
|
|
1628
|
-
|
|
1629
|
-
|
|
1630
|
-
|
|
1732
|
+
if (this.config.onAfter) {
|
|
1733
|
+
this.hookManager.addListener(HookName.CHILD_DISPATCH_AFTER, this.config.onAfter);
|
|
1734
|
+
}
|
|
1735
|
+
if (this.config.onError) {
|
|
1736
|
+
this.hookManager.addListener(HookName.ERROR, this.config.onError);
|
|
1631
1737
|
}
|
|
1632
|
-
return name === MethodName.HEAD && this.method === MethodName.GET;
|
|
1633
1738
|
}
|
|
1634
1739
|
// --------------------------------------------------
|
|
1635
1740
|
constructor(handler){
|
|
1636
|
-
this['@instanceof'] =
|
|
1637
|
-
this.
|
|
1638
|
-
|
|
1639
|
-
|
|
1640
|
-
|
|
1641
|
-
|
|
1642
|
-
|
|
1741
|
+
this['@instanceof'] = HandlerSymbol;
|
|
1742
|
+
this.config = handler;
|
|
1743
|
+
this.hookManager = new HookManager();
|
|
1744
|
+
this.mountHooks();
|
|
1745
|
+
this.setPath(handler.path);
|
|
1746
|
+
}
|
|
1747
|
+
}
|
|
1748
|
+
|
|
1749
|
+
function coreHandler(input) {
|
|
1750
|
+
if (typeof input === 'function') {
|
|
1751
|
+
return new Handler({
|
|
1752
|
+
type: HandlerType.CORE,
|
|
1753
|
+
fn: input
|
|
1754
|
+
});
|
|
1755
|
+
}
|
|
1756
|
+
return new Handler({
|
|
1757
|
+
type: HandlerType.CORE,
|
|
1758
|
+
...input
|
|
1759
|
+
});
|
|
1760
|
+
}
|
|
1761
|
+
|
|
1762
|
+
function errorHandler(input) {
|
|
1763
|
+
if (typeof input === 'function') {
|
|
1764
|
+
return new Handler({
|
|
1765
|
+
type: HandlerType.ERROR,
|
|
1766
|
+
fn: input
|
|
1767
|
+
});
|
|
1643
1768
|
}
|
|
1769
|
+
return new Handler({
|
|
1770
|
+
type: HandlerType.ERROR,
|
|
1771
|
+
...input
|
|
1772
|
+
});
|
|
1644
1773
|
}
|
|
1645
1774
|
|
|
1646
|
-
function
|
|
1647
|
-
return
|
|
1775
|
+
function isHandlerConfig(input) {
|
|
1776
|
+
return isObject(input) && typeof input.fn === 'function' && typeof input.type === 'string';
|
|
1777
|
+
}
|
|
1778
|
+
function isHandler(input) {
|
|
1779
|
+
return isInstance(input, HandlerSymbol);
|
|
1648
1780
|
}
|
|
1649
1781
|
|
|
1650
1782
|
function isPlugin(input) {
|
|
@@ -1654,10 +1786,7 @@ function isPlugin(input) {
|
|
|
1654
1786
|
if (typeof input.name !== 'undefined' && typeof input.name !== 'string') {
|
|
1655
1787
|
return false;
|
|
1656
1788
|
}
|
|
1657
|
-
|
|
1658
|
-
return false;
|
|
1659
|
-
}
|
|
1660
|
-
return typeof input.version === 'undefined' || typeof input.version === 'string';
|
|
1789
|
+
return typeof input.install === 'function' && input.install.length === 1;
|
|
1661
1790
|
}
|
|
1662
1791
|
|
|
1663
1792
|
function transformRouterOptions(input) {
|
|
@@ -1671,6 +1800,15 @@ function transformRouterOptions(input) {
|
|
|
1671
1800
|
}
|
|
1672
1801
|
|
|
1673
1802
|
const RouterSymbol = Symbol.for('Router');
|
|
1803
|
+
var RouterPipelineStep;
|
|
1804
|
+
(function(RouterPipelineStep) {
|
|
1805
|
+
RouterPipelineStep[RouterPipelineStep["START"] = 0] = "START";
|
|
1806
|
+
RouterPipelineStep[RouterPipelineStep["LOOKUP"] = 1] = "LOOKUP";
|
|
1807
|
+
RouterPipelineStep[RouterPipelineStep["CHILD_BEFORE"] = 2] = "CHILD_BEFORE";
|
|
1808
|
+
RouterPipelineStep[RouterPipelineStep["CHILD_DISPATCH"] = 3] = "CHILD_DISPATCH";
|
|
1809
|
+
RouterPipelineStep[RouterPipelineStep["CHILD_AFTER"] = 4] = "CHILD_AFTER";
|
|
1810
|
+
RouterPipelineStep[RouterPipelineStep["FINISH"] = 5] = "FINISH";
|
|
1811
|
+
})(RouterPipelineStep || (RouterPipelineStep = {}));
|
|
1674
1812
|
|
|
1675
1813
|
let nextId = 0;
|
|
1676
1814
|
function generateRouterID() {
|
|
@@ -1682,220 +1820,252 @@ function isRouterInstance(input) {
|
|
|
1682
1820
|
|
|
1683
1821
|
class Router {
|
|
1684
1822
|
// --------------------------------------------------
|
|
1823
|
+
matchPath(path) {
|
|
1824
|
+
if (this.pathMatcher) {
|
|
1825
|
+
return this.pathMatcher.test(path);
|
|
1826
|
+
}
|
|
1827
|
+
return true;
|
|
1828
|
+
}
|
|
1685
1829
|
setPath(value) {
|
|
1686
|
-
if (value === '/' ||
|
|
1830
|
+
if (value === '/' || typeof value === 'undefined') {
|
|
1831
|
+
this.pathMatcher = undefined;
|
|
1687
1832
|
return;
|
|
1688
1833
|
}
|
|
1689
|
-
let path;
|
|
1690
1834
|
if (typeof value === 'string') {
|
|
1691
|
-
|
|
1835
|
+
this.pathMatcher = new PathMatcher(withLeadingSlash(withoutTrailingSlash(`${value}`)), {
|
|
1836
|
+
end: false
|
|
1837
|
+
});
|
|
1692
1838
|
} else {
|
|
1693
|
-
|
|
1839
|
+
this.pathMatcher = new PathMatcher(value, {
|
|
1840
|
+
end: false
|
|
1841
|
+
});
|
|
1694
1842
|
}
|
|
1695
|
-
this.pathMatcher = new PathMatcher(path, {
|
|
1696
|
-
end: false
|
|
1697
|
-
});
|
|
1698
1843
|
}
|
|
1699
1844
|
// --------------------------------------------------
|
|
1700
|
-
|
|
1701
|
-
|
|
1702
|
-
|
|
1845
|
+
async executePipelineStep(context) {
|
|
1846
|
+
switch(context.step){
|
|
1847
|
+
case RouterPipelineStep.START:
|
|
1848
|
+
{
|
|
1849
|
+
return this.executePipelineStepStart(context);
|
|
1850
|
+
}
|
|
1851
|
+
case RouterPipelineStep.LOOKUP:
|
|
1852
|
+
{
|
|
1853
|
+
return this.executePipelineStepLookup(context);
|
|
1854
|
+
}
|
|
1855
|
+
case RouterPipelineStep.CHILD_BEFORE:
|
|
1856
|
+
{
|
|
1857
|
+
return this.executePipelineStepChildBefore(context);
|
|
1858
|
+
}
|
|
1859
|
+
case RouterPipelineStep.CHILD_DISPATCH:
|
|
1860
|
+
{
|
|
1861
|
+
return this.executePipelineStepChildDispatch(context);
|
|
1862
|
+
}
|
|
1863
|
+
case RouterPipelineStep.CHILD_AFTER:
|
|
1864
|
+
{
|
|
1865
|
+
return this.executePipelineStepChildAfter(context);
|
|
1866
|
+
}
|
|
1867
|
+
case RouterPipelineStep.FINISH:
|
|
1868
|
+
default:
|
|
1869
|
+
{
|
|
1870
|
+
return this.executePipelineStepFinish(context);
|
|
1871
|
+
}
|
|
1703
1872
|
}
|
|
1704
|
-
return true;
|
|
1705
1873
|
}
|
|
1706
|
-
|
|
1707
|
-
|
|
1708
|
-
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
|
|
1712
|
-
meta.mountPath = cleanDoubleSlashes(`${meta.mountPath}/${output.path}`);
|
|
1713
|
-
if (meta.path === output.path) {
|
|
1714
|
-
meta.path = '/';
|
|
1715
|
-
} else {
|
|
1716
|
-
meta.path = withLeadingSlash(meta.path.substring(output.path.length));
|
|
1717
|
-
}
|
|
1718
|
-
meta.params = {
|
|
1719
|
-
...meta.params,
|
|
1720
|
-
...output.params
|
|
1721
|
-
};
|
|
1874
|
+
async executePipelineStepStart(context) {
|
|
1875
|
+
return this.hookManager.trigger(HookName.DISPATCH_START, context.event).then(()=>{
|
|
1876
|
+
if (context.event.dispatched) {
|
|
1877
|
+
context.step = RouterPipelineStep.FINISH;
|
|
1878
|
+
} else {
|
|
1879
|
+
context.step++;
|
|
1722
1880
|
}
|
|
1723
|
-
|
|
1724
|
-
|
|
1725
|
-
|
|
1726
|
-
|
|
1727
|
-
|
|
1728
|
-
|
|
1729
|
-
|
|
1730
|
-
|
|
1731
|
-
|
|
1732
|
-
|
|
1733
|
-
|
|
1881
|
+
return this.executePipelineStep(context);
|
|
1882
|
+
});
|
|
1883
|
+
}
|
|
1884
|
+
async executePipelineStepLookup(context) {
|
|
1885
|
+
if (context.event.dispatched || context.stackIndex >= this.stack.length) {
|
|
1886
|
+
context.step = RouterPipelineStep.FINISH;
|
|
1887
|
+
return this.executePipelineStep(context);
|
|
1888
|
+
}
|
|
1889
|
+
let match;
|
|
1890
|
+
const item = this.stack[context.stackIndex];
|
|
1891
|
+
if (isHandler(item)) {
|
|
1892
|
+
if (context.event.error && item.type === HandlerType.CORE || !context.event.error && item.type === HandlerType.ERROR) {
|
|
1893
|
+
context.stackIndex++;
|
|
1894
|
+
return this.executePipelineStepLookup(context);
|
|
1895
|
+
}
|
|
1896
|
+
match = item.matchPath(context.event.path);
|
|
1897
|
+
if (match) {
|
|
1898
|
+
if (item.method) {
|
|
1899
|
+
context.event.methodsAllowed.push(item.method);
|
|
1734
1900
|
}
|
|
1735
|
-
|
|
1736
|
-
|
|
1737
|
-
if (
|
|
1738
|
-
|
|
1739
|
-
}
|
|
1740
|
-
|
|
1741
|
-
allowedMethods.push(item.method);
|
|
1901
|
+
if (item.matchMethod(context.event.method)) {
|
|
1902
|
+
await this.hookManager.trigger(HookName.CHILD_MATCH, context.event);
|
|
1903
|
+
if (context.event.dispatched) {
|
|
1904
|
+
context.step = RouterPipelineStep.FINISH;
|
|
1905
|
+
} else {
|
|
1906
|
+
context.step++;
|
|
1742
1907
|
}
|
|
1908
|
+
return this.executePipelineStep(context);
|
|
1743
1909
|
}
|
|
1744
|
-
} else if (isRouterInstance(item)) {
|
|
1745
|
-
match = item.matchPath(meta.path);
|
|
1746
1910
|
}
|
|
1747
|
-
|
|
1748
|
-
|
|
1911
|
+
context.stackIndex++;
|
|
1912
|
+
return this.executePipelineStepLookup(context);
|
|
1913
|
+
}
|
|
1914
|
+
match = item.matchPath(context.event.path);
|
|
1915
|
+
if (match) {
|
|
1916
|
+
await this.hookManager.trigger(HookName.CHILD_MATCH, context.event);
|
|
1917
|
+
if (context.event.dispatched) {
|
|
1918
|
+
context.step = RouterPipelineStep.FINISH;
|
|
1919
|
+
} else {
|
|
1920
|
+
context.step++;
|
|
1749
1921
|
}
|
|
1750
|
-
|
|
1751
|
-
|
|
1752
|
-
|
|
1922
|
+
return this.executePipelineStep(context);
|
|
1923
|
+
}
|
|
1924
|
+
context.stackIndex++;
|
|
1925
|
+
return this.executePipelineStepLookup(context);
|
|
1926
|
+
}
|
|
1927
|
+
async executePipelineStepChildBefore(context) {
|
|
1928
|
+
return this.hookManager.trigger(HookName.CHILD_DISPATCH_BEFORE, context.event).then(()=>{
|
|
1929
|
+
if (context.event.dispatched) {
|
|
1930
|
+
context.step = RouterPipelineStep.FINISH;
|
|
1931
|
+
} else {
|
|
1932
|
+
context.step++;
|
|
1753
1933
|
}
|
|
1754
|
-
|
|
1755
|
-
|
|
1756
|
-
|
|
1757
|
-
|
|
1758
|
-
|
|
1759
|
-
|
|
1760
|
-
|
|
1761
|
-
|
|
1762
|
-
|
|
1934
|
+
return this.executePipelineStep(context);
|
|
1935
|
+
});
|
|
1936
|
+
}
|
|
1937
|
+
async executePipelineStepChildAfter(context) {
|
|
1938
|
+
return this.hookManager.trigger(HookName.CHILD_DISPATCH_AFTER, context.event).then(()=>{
|
|
1939
|
+
if (context.event.dispatched) {
|
|
1940
|
+
context.step = RouterPipelineStep.FINISH;
|
|
1941
|
+
} else {
|
|
1942
|
+
context.step = RouterPipelineStep.LOOKUP;
|
|
1763
1943
|
}
|
|
1944
|
+
return this.executePipelineStep(context);
|
|
1945
|
+
});
|
|
1946
|
+
}
|
|
1947
|
+
async executePipelineStepChildDispatch(context) {
|
|
1948
|
+
if (context.event.dispatched || typeof this.stack[context.stackIndex] === 'undefined') {
|
|
1949
|
+
context.step = RouterPipelineStep.FINISH;
|
|
1950
|
+
return this.executePipelineStep(context);
|
|
1764
1951
|
}
|
|
1765
|
-
|
|
1766
|
-
|
|
1952
|
+
try {
|
|
1953
|
+
await this.stack[context.stackIndex].dispatch(context.event);
|
|
1954
|
+
} catch (e) {
|
|
1955
|
+
context.event.error = e;
|
|
1956
|
+
await this.hookManager.trigger(HookName.ERROR, context.event);
|
|
1767
1957
|
}
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
|
-
|
|
1772
|
-
|
|
1773
|
-
|
|
1774
|
-
|
|
1775
|
-
|
|
1776
|
-
|
|
1958
|
+
context.stackIndex++;
|
|
1959
|
+
context.step++;
|
|
1960
|
+
return this.executePipelineStep(context);
|
|
1961
|
+
}
|
|
1962
|
+
async executePipelineStepFinish(context) {
|
|
1963
|
+
if (context.event.error || context.event.dispatched) {
|
|
1964
|
+
return this.hookManager.trigger(HookName.DISPATCH_END, context.event);
|
|
1965
|
+
}
|
|
1966
|
+
if (!context.event.dispatched && context.event.routerPath.length === 1 && context.event.method && context.event.method === MethodName.OPTIONS) {
|
|
1967
|
+
if (context.event.methodsAllowed.indexOf(MethodName.GET) !== -1) {
|
|
1968
|
+
context.event.methodsAllowed.push(MethodName.HEAD);
|
|
1777
1969
|
}
|
|
1778
|
-
|
|
1970
|
+
distinctArray(context.event.methodsAllowed);
|
|
1971
|
+
const options = context.event.methodsAllowed.map((key)=>key.toUpperCase()).join(',');
|
|
1972
|
+
context.event.response.setHeader(HeaderName.ALLOW, options);
|
|
1973
|
+
await send(context.event.response, options);
|
|
1974
|
+
context.event.dispatched = true;
|
|
1779
1975
|
}
|
|
1780
|
-
return
|
|
1976
|
+
return this.hookManager.trigger(HookName.DISPATCH_END, context.event);
|
|
1781
1977
|
}
|
|
1782
|
-
|
|
1783
|
-
|
|
1784
|
-
|
|
1785
|
-
|
|
1786
|
-
|
|
1787
|
-
path
|
|
1788
|
-
|
|
1789
|
-
|
|
1978
|
+
// --------------------------------------------------
|
|
1979
|
+
async dispatch(event) {
|
|
1980
|
+
if (this.pathMatcher) {
|
|
1981
|
+
const output = this.pathMatcher.exec(event.path);
|
|
1982
|
+
if (typeof output !== 'undefined') {
|
|
1983
|
+
event.mountPath = cleanDoubleSlashes(`${event.mountPath}/${output.path}`);
|
|
1984
|
+
if (event.path === output.path) {
|
|
1985
|
+
event.path = '/';
|
|
1986
|
+
} else {
|
|
1987
|
+
event.path = withLeadingSlash(event.path.substring(output.path.length));
|
|
1988
|
+
}
|
|
1989
|
+
event.params = {
|
|
1990
|
+
...event.params,
|
|
1991
|
+
...output.params
|
|
1992
|
+
};
|
|
1993
|
+
}
|
|
1790
1994
|
}
|
|
1791
|
-
|
|
1792
|
-
|
|
1793
|
-
|
|
1995
|
+
const context = {
|
|
1996
|
+
step: RouterPipelineStep.START,
|
|
1997
|
+
event,
|
|
1998
|
+
stackIndex: 0
|
|
1999
|
+
};
|
|
2000
|
+
event.routerPath.push(this.id);
|
|
2001
|
+
return this.executePipelineStepStart(context).then(()=>{
|
|
2002
|
+
context.event.routerPath.pop();
|
|
1794
2003
|
});
|
|
2004
|
+
}
|
|
2005
|
+
delete(...input) {
|
|
2006
|
+
this.useForMethod(MethodName.DELETE, ...input);
|
|
1795
2007
|
return this;
|
|
1796
2008
|
}
|
|
1797
|
-
get(
|
|
1798
|
-
|
|
1799
|
-
this.use({
|
|
1800
|
-
...handler,
|
|
1801
|
-
method: MethodName.GET,
|
|
1802
|
-
path
|
|
1803
|
-
});
|
|
1804
|
-
return this;
|
|
1805
|
-
}
|
|
1806
|
-
this.use({
|
|
1807
|
-
...path,
|
|
1808
|
-
method: MethodName.GET
|
|
1809
|
-
});
|
|
2009
|
+
get(...input) {
|
|
2010
|
+
this.useForMethod(MethodName.GET, ...input);
|
|
1810
2011
|
return this;
|
|
1811
2012
|
}
|
|
1812
|
-
post(
|
|
1813
|
-
|
|
1814
|
-
this.use({
|
|
1815
|
-
...handler,
|
|
1816
|
-
method: MethodName.POST,
|
|
1817
|
-
path
|
|
1818
|
-
});
|
|
1819
|
-
return this;
|
|
1820
|
-
}
|
|
1821
|
-
this.use({
|
|
1822
|
-
...path,
|
|
1823
|
-
method: MethodName.POST
|
|
1824
|
-
});
|
|
2013
|
+
post(...input) {
|
|
2014
|
+
this.useForMethod(MethodName.POST, ...input);
|
|
1825
2015
|
return this;
|
|
1826
2016
|
}
|
|
1827
|
-
put(
|
|
1828
|
-
|
|
1829
|
-
this.use({
|
|
1830
|
-
...handler,
|
|
1831
|
-
method: MethodName.PUT,
|
|
1832
|
-
path
|
|
1833
|
-
});
|
|
1834
|
-
return this;
|
|
1835
|
-
}
|
|
1836
|
-
this.use({
|
|
1837
|
-
...path,
|
|
1838
|
-
method: MethodName.PUT
|
|
1839
|
-
});
|
|
2017
|
+
put(...input) {
|
|
2018
|
+
this.useForMethod(MethodName.PUT, ...input);
|
|
1840
2019
|
return this;
|
|
1841
2020
|
}
|
|
1842
|
-
patch(
|
|
1843
|
-
|
|
1844
|
-
this.use({
|
|
1845
|
-
...handler,
|
|
1846
|
-
method: MethodName.PATCH,
|
|
1847
|
-
path
|
|
1848
|
-
});
|
|
1849
|
-
return this;
|
|
1850
|
-
}
|
|
1851
|
-
this.use({
|
|
1852
|
-
...path,
|
|
1853
|
-
method: MethodName.PATCH
|
|
1854
|
-
});
|
|
2021
|
+
patch(...input) {
|
|
2022
|
+
this.useForMethod(MethodName.PATCH, ...input);
|
|
1855
2023
|
return this;
|
|
1856
2024
|
}
|
|
1857
|
-
head(
|
|
1858
|
-
|
|
1859
|
-
this.use({
|
|
1860
|
-
...handler,
|
|
1861
|
-
method: MethodName.HEAD,
|
|
1862
|
-
path
|
|
1863
|
-
});
|
|
1864
|
-
return this;
|
|
1865
|
-
}
|
|
1866
|
-
this.use({
|
|
1867
|
-
...path,
|
|
1868
|
-
method: MethodName.HEAD
|
|
1869
|
-
});
|
|
2025
|
+
head(...input) {
|
|
2026
|
+
this.useForMethod(MethodName.HEAD, ...input);
|
|
1870
2027
|
return this;
|
|
1871
2028
|
}
|
|
1872
|
-
options(
|
|
1873
|
-
|
|
1874
|
-
this.use({
|
|
1875
|
-
...handler,
|
|
1876
|
-
method: MethodName.OPTIONS,
|
|
1877
|
-
path
|
|
1878
|
-
});
|
|
1879
|
-
return this;
|
|
1880
|
-
}
|
|
1881
|
-
this.use({
|
|
1882
|
-
...path,
|
|
1883
|
-
method: MethodName.OPTIONS
|
|
1884
|
-
});
|
|
2029
|
+
options(...input) {
|
|
2030
|
+
this.useForMethod(MethodName.OPTIONS, ...input);
|
|
1885
2031
|
return this;
|
|
1886
2032
|
}
|
|
1887
|
-
|
|
1888
|
-
|
|
1889
|
-
|
|
1890
|
-
|
|
2033
|
+
// --------------------------------------------------
|
|
2034
|
+
useForMethod(method, ...input) {
|
|
2035
|
+
let path;
|
|
2036
|
+
for(let i = 0; i < input.length; i++){
|
|
2037
|
+
const element = input[i];
|
|
2038
|
+
if (isPath(element)) {
|
|
2039
|
+
path = element;
|
|
2040
|
+
continue;
|
|
1891
2041
|
}
|
|
1892
|
-
|
|
1893
|
-
|
|
2042
|
+
if (isHandlerConfig(element)) {
|
|
2043
|
+
if (path) {
|
|
2044
|
+
element.path = path;
|
|
2045
|
+
}
|
|
2046
|
+
element.method = method;
|
|
2047
|
+
this.use(element);
|
|
2048
|
+
continue;
|
|
2049
|
+
}
|
|
2050
|
+
if (isHandler(element)) {
|
|
2051
|
+
if (path) {
|
|
2052
|
+
element.setPath(path);
|
|
2053
|
+
}
|
|
2054
|
+
element.setMethod(method);
|
|
2055
|
+
this.use(element);
|
|
2056
|
+
}
|
|
2057
|
+
}
|
|
2058
|
+
}
|
|
2059
|
+
use(...input) {
|
|
1894
2060
|
let path;
|
|
1895
2061
|
for(let i = 0; i < input.length; i++){
|
|
1896
2062
|
const item = input[i];
|
|
1897
2063
|
if (isPath(item)) {
|
|
1898
|
-
|
|
2064
|
+
if (typeof item === 'string') {
|
|
2065
|
+
path = withLeadingSlash(item);
|
|
2066
|
+
} else {
|
|
2067
|
+
path = item;
|
|
2068
|
+
}
|
|
1899
2069
|
continue;
|
|
1900
2070
|
}
|
|
1901
2071
|
if (isRouterInstance(item)) {
|
|
@@ -1905,9 +2075,15 @@ class Router {
|
|
|
1905
2075
|
this.stack.push(item);
|
|
1906
2076
|
continue;
|
|
1907
2077
|
}
|
|
2078
|
+
if (isHandlerConfig(item)) {
|
|
2079
|
+
item.path = path || item.path;
|
|
2080
|
+
this.stack.push(new Handler(item));
|
|
2081
|
+
continue;
|
|
2082
|
+
}
|
|
1908
2083
|
if (isHandler(item)) {
|
|
1909
|
-
item.path
|
|
1910
|
-
this.stack.push(
|
|
2084
|
+
item.setPath(path || item.path);
|
|
2085
|
+
this.stack.push(item);
|
|
2086
|
+
continue;
|
|
1911
2087
|
}
|
|
1912
2088
|
if (isPlugin(item)) {
|
|
1913
2089
|
if (path) {
|
|
@@ -1924,15 +2100,26 @@ class Router {
|
|
|
1924
2100
|
// --------------------------------------------------
|
|
1925
2101
|
install(plugin, context = {}) {
|
|
1926
2102
|
const name = context.name || plugin.name;
|
|
2103
|
+
const router = new Router({
|
|
2104
|
+
name
|
|
2105
|
+
});
|
|
2106
|
+
plugin.install(router);
|
|
1927
2107
|
if (context.path) {
|
|
1928
|
-
const router = new Router({
|
|
1929
|
-
name
|
|
1930
|
-
});
|
|
1931
|
-
plugin.install(router);
|
|
1932
2108
|
this.use(context.path, router);
|
|
2109
|
+
} else {
|
|
2110
|
+
this.use(router);
|
|
2111
|
+
}
|
|
2112
|
+
return this;
|
|
2113
|
+
}
|
|
2114
|
+
on(name, fn) {
|
|
2115
|
+
return this.hookManager.addListener(name, fn);
|
|
2116
|
+
}
|
|
2117
|
+
off(name, fn) {
|
|
2118
|
+
if (typeof fn === 'undefined') {
|
|
2119
|
+
this.hookManager.removeListener(name);
|
|
1933
2120
|
return this;
|
|
1934
2121
|
}
|
|
1935
|
-
|
|
2122
|
+
this.hookManager.removeListener(name, fn);
|
|
1936
2123
|
return this;
|
|
1937
2124
|
}
|
|
1938
2125
|
// --------------------------------------------------
|
|
@@ -1945,10 +2132,11 @@ class Router {
|
|
|
1945
2132
|
*/ this.stack = [];
|
|
1946
2133
|
this.id = generateRouterID();
|
|
1947
2134
|
this.name = options.name;
|
|
2135
|
+
this.hookManager = new HookManager();
|
|
1948
2136
|
this.setPath(options.path);
|
|
1949
2137
|
setRouterOptions(this.id, transformRouterOptions(options));
|
|
1950
2138
|
}
|
|
1951
2139
|
}
|
|
1952
2140
|
|
|
1953
|
-
export {
|
|
2141
|
+
export { DispatchErrorEvent, DispatchEvent, Handler, HandlerSymbol, HandlerType, HeaderName, MethodName, PathMatcher, Router, RoutupError, appendResponseHeader, appendResponseHeaderDirective, coreHandler, createError, createNodeDispatcher, createRawDispatcher, createRequest, createResponse, createWebDispatcher, dispatch, dispatchNodeRequest, dispatchRawRequest, dispatchWebRequest, errorHandler, getRequestAcceptableCharset, getRequestAcceptableCharsets, getRequestAcceptableContentType, getRequestAcceptableContentTypes, getRequestAcceptableEncoding, getRequestAcceptableEncodings, getRequestAcceptableLanguage, getRequestAcceptableLanguages, getRequestHeader, getRequestHostName, getRequestIP, getRequestProtocol, isDispatcherErrorEvent, isError, isHandler, isHandlerConfig, isPath, isPlugin, isRequestCacheable, isResponseGone, matchRequestContentType, send, sendAccepted, sendCreated, sendFile, sendFormat, sendRedirect, sendStream, sendWebBlob, sendWebResponse, setRequestEnv, setRequestHeader, setRequestMountPath, setRequestParam, setRequestParams, setRequestRouterPath, setResponseCacheHeaders, setResponseContentTypeByFileName, setResponseHeaderAttachment, setResponseHeaderContentType, transformHeaderToTuples, transformHeadersToTuples, unsetRequestEnv, useRequestEnv, useRequestMountPath, useRequestNegotiator, useRequestParam, useRequestParams, useRequestPath, useRequestRouterPath };
|
|
1954
2142
|
//# sourceMappingURL=index.mjs.map
|