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