routup 0.12.0 → 0.13.1
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/LICENSE +1 -1
- package/README.md +11 -10
- package/dist/handler/index.d.ts +1 -1
- package/dist/handler/utils.d.ts +2 -2
- package/dist/handler/utils.d.ts.map +1 -1
- package/dist/index.cjs +579 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.ts +8 -8
- package/dist/index.mjs +561 -0
- package/dist/index.mjs.map +1 -0
- package/dist/layer/index.d.ts +3 -3
- package/dist/layer/module.d.ts +15 -15
- package/dist/layer/module.d.ts.map +1 -1
- package/dist/layer/type.d.ts +6 -6
- package/dist/layer/type.d.ts.map +1 -1
- package/dist/layer/utils.d.ts +2 -2
- package/dist/layer/utils.d.ts.map +1 -1
- package/dist/path/index.d.ts +2 -2
- package/dist/path/matcher.d.ts +12 -12
- package/dist/path/matcher.d.ts.map +1 -1
- package/dist/path/type.d.ts +6 -6
- package/dist/path/type.d.ts.map +1 -1
- package/dist/route/index.d.ts +3 -3
- package/dist/route/module.d.ts +28 -26
- package/dist/route/module.d.ts.map +1 -1
- package/dist/route/type.d.ts +6 -6
- package/dist/route/type.d.ts.map +1 -1
- package/dist/route/utils.d.ts +2 -2
- package/dist/route/utils.d.ts.map +1 -1
- package/dist/router/index.d.ts +2 -2
- package/dist/router/module.d.ts +71 -70
- package/dist/router/module.d.ts.map +1 -1
- package/dist/router/type.d.ts +24 -24
- package/dist/router/type.d.ts.map +1 -1
- package/dist/type.d.ts +13 -13
- package/dist/utils/index.d.ts +4 -4
- package/dist/utils/is-instance.d.ts +1 -1
- package/dist/utils/path.d.ts +2 -2
- package/dist/utils/path.d.ts.map +1 -1
- package/dist/utils/promise.d.ts +1 -1
- package/dist/utils/request.d.ts +2 -2
- package/dist/utils/request.d.ts.map +1 -1
- package/package.json +17 -8
- package/dist/handler/index.js +0 -21
- package/dist/handler/utils.js +0 -29
- package/dist/index.js +0 -28
- package/dist/layer/index.js +0 -23
- package/dist/layer/module.js +0 -74
- package/dist/layer/type.js +0 -9
- package/dist/layer/utils.js +0 -17
- package/dist/path/index.js +0 -22
- package/dist/path/matcher.js +0 -74
- package/dist/path/type.js +0 -9
- package/dist/route/index.js +0 -23
- package/dist/route/module.js +0 -135
- package/dist/route/type.js +0 -9
- package/dist/route/utils.js +0 -17
- package/dist/router/index.js +0 -22
- package/dist/router/module.js +0 -294
- package/dist/router/type.js +0 -9
- package/dist/type.js +0 -9
- package/dist/utils/index.js +0 -24
- package/dist/utils/is-instance.js +0 -16
- package/dist/utils/path.js +0 -16
- package/dist/utils/promise.js +0 -19
- package/dist/utils/request.js +0 -33
package/LICENSE
CHANGED
package/README.md
CHANGED
|
@@ -62,16 +62,17 @@ router.listen(3000);
|
|
|
62
62
|
According to the fact that routup is a minimalistic framework, it depends on plugins to cover some
|
|
63
63
|
typically http framework functions, which are not integrated in the main package.
|
|
64
64
|
|
|
65
|
-
| Name
|
|
66
|
-
|
|
67
|
-
| [body](https://www.npmjs.com/package/@routup/body)
|
|
68
|
-
| [cookie](https://www.npmjs.com/package/@routup/cookie)
|
|
69
|
-
| [decorators](https://www.npmjs.com/package/@routup/decorators)
|
|
70
|
-
| [prometheus](https://www.npmjs.com/package/@routup/prometheus)
|
|
71
|
-
| [query](https://www.npmjs.com/package/@routup/query)
|
|
72
|
-
| [rate-limit](https://www.npmjs.com/package/@routup/rate-limit)
|
|
73
|
-
| [
|
|
74
|
-
| [
|
|
65
|
+
| Name | Description |
|
|
66
|
+
|----------------------------------------------------------------------------|------------------------------------------------------------------------|
|
|
67
|
+
| [body](https://www.npmjs.com/package/@routup/body) | Read and parse the request body. |
|
|
68
|
+
| [cookie](https://www.npmjs.com/package/@routup/cookie) | Read and parse request cookies and serialize cookies for the response. |
|
|
69
|
+
| [decorators](https://www.npmjs.com/package/@routup/decorators) | Create request handlers with class-, method- & parameter-decorators. |
|
|
70
|
+
| [prometheus](https://www.npmjs.com/package/@routup/prometheus) | Collect and serve metrics for prometheus. |
|
|
71
|
+
| [query](https://www.npmjs.com/package/@routup/query) | Read and parse the query string of the request url. |
|
|
72
|
+
| [rate-limit](https://www.npmjs.com/package/@routup/rate-limit) | Rate limit incoming requests. |
|
|
73
|
+
| [rate-limit-redis](https://www.npmjs.com/package/@routup/rate-limit-redis) | Redis adapter for the rate-limit plugin. |
|
|
74
|
+
| [static](https://www.npmjs.com/package/@routup/static) | Serve static files from a directory. |
|
|
75
|
+
| [swagger](https://www.npmjs.com/package/@routup/swagger) | Serve generated docs from URL or based on a JSON file. |
|
|
75
76
|
|
|
76
77
|
## License
|
|
77
78
|
|
package/dist/handler/index.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export * from './utils';
|
|
1
|
+
export * from './utils';
|
|
2
2
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/handler/utils.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { Next, Response } from '@routup/core';
|
|
2
|
-
export declare function processHandlerExecutionOutput(res: Response, next: Next, output?: unknown): void;
|
|
1
|
+
import type { Next, Response } from '@routup/core';
|
|
2
|
+
export declare function processHandlerExecutionOutput(res: Response, next: Next, output?: unknown): void;
|
|
3
3
|
//# sourceMappingURL=utils.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/handler/utils.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,IAAI,EAAE,QAAQ,
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/handler/utils.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAInD,wBAAgB,6BAA6B,CAAC,GAAG,EAAE,QAAQ,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,CAAC,EAAE,OAAO,QAiBxF"}
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,579 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var core = require('@routup/core');
|
|
4
|
+
var smob = require('smob');
|
|
5
|
+
var http = require('@ebec/http');
|
|
6
|
+
var pathToRegexp = require('path-to-regexp');
|
|
7
|
+
var node_http = require('node:http');
|
|
8
|
+
|
|
9
|
+
/*
|
|
10
|
+
* Copyright (c) 2022-2022.
|
|
11
|
+
* Author Peter Placzek (tada5hi)
|
|
12
|
+
* For the full copyright and license information,
|
|
13
|
+
* view the LICENSE file that was distributed with this source code.
|
|
14
|
+
*/ function isInstance(input, name) {
|
|
15
|
+
return typeof input === 'object' && input !== null && input['@instanceof'] === Symbol.for(name);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/*
|
|
19
|
+
* Copyright (c) 2022.
|
|
20
|
+
* Author Peter Placzek (tada5hi)
|
|
21
|
+
* For the full copyright and license information,
|
|
22
|
+
* view the LICENSE file that was distributed with this source code.
|
|
23
|
+
*/ function isPath(input) {
|
|
24
|
+
return typeof input === 'string' || input instanceof RegExp;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function isPromise(p) {
|
|
28
|
+
return smob.isObject(p) && (p instanceof Promise || // eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
29
|
+
// @ts-ignore
|
|
30
|
+
typeof p.then === 'function');
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/* istanbul ignore next */ function createRequestTimeout(res, timeout, done) {
|
|
34
|
+
const instance = setTimeout(()=>{
|
|
35
|
+
res.statusCode = http.GatewayTimeoutErrorOptions.statusCode;
|
|
36
|
+
res.statusMessage = http.GatewayTimeoutErrorOptions.message;
|
|
37
|
+
res.end();
|
|
38
|
+
}, timeout);
|
|
39
|
+
res.once('close', ()=>{
|
|
40
|
+
clearTimeout(instance);
|
|
41
|
+
if (typeof done === 'function') {
|
|
42
|
+
done();
|
|
43
|
+
}
|
|
44
|
+
});
|
|
45
|
+
res.once('error', (e)=>{
|
|
46
|
+
clearTimeout(instance);
|
|
47
|
+
if (typeof done === 'function') {
|
|
48
|
+
done(e);
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function processHandlerExecutionOutput(res, next, output) {
|
|
54
|
+
if (isPromise(output)) {
|
|
55
|
+
output.then((r)=>{
|
|
56
|
+
if (typeof r !== 'undefined') {
|
|
57
|
+
core.send(res, r);
|
|
58
|
+
}
|
|
59
|
+
return r;
|
|
60
|
+
}).catch(next);
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
if (typeof output !== 'undefined') {
|
|
64
|
+
core.send(res, output);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function decodeParam(val) {
|
|
69
|
+
/* istanbul ignore next */ if (typeof val !== 'string' || val.length === 0) {
|
|
70
|
+
return val;
|
|
71
|
+
}
|
|
72
|
+
return decodeURIComponent(val);
|
|
73
|
+
}
|
|
74
|
+
class PathMatcher {
|
|
75
|
+
test(path) {
|
|
76
|
+
const fastSlash = this.path === '/' && this.regexpOptions.end === false;
|
|
77
|
+
if (fastSlash) {
|
|
78
|
+
return true;
|
|
79
|
+
}
|
|
80
|
+
return this.regexp.test(path);
|
|
81
|
+
}
|
|
82
|
+
exec(path) {
|
|
83
|
+
let match = null;
|
|
84
|
+
const fastSlash = this.path === '/' && this.regexpOptions.end === false;
|
|
85
|
+
if (fastSlash) {
|
|
86
|
+
return {
|
|
87
|
+
path: '/',
|
|
88
|
+
params: {}
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
match = this.regexp.exec(path);
|
|
92
|
+
if (!match) {
|
|
93
|
+
return undefined;
|
|
94
|
+
}
|
|
95
|
+
if (this.path instanceof RegExp) {
|
|
96
|
+
return {
|
|
97
|
+
path,
|
|
98
|
+
params: {
|
|
99
|
+
0: decodeParam(match[0])
|
|
100
|
+
}
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
const output = {};
|
|
104
|
+
for(let i = 1; i < match.length; i++){
|
|
105
|
+
const key = this.regexpKeys[i - 1];
|
|
106
|
+
const prop = key.name;
|
|
107
|
+
const val = decodeParam(match[i]);
|
|
108
|
+
if (typeof val !== 'undefined') {
|
|
109
|
+
output[prop] = val;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
return {
|
|
113
|
+
path: match[0],
|
|
114
|
+
params: output
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
constructor(path, options){
|
|
118
|
+
this.regexpKeys = [];
|
|
119
|
+
this.path = path;
|
|
120
|
+
this.regexpOptions = options || {};
|
|
121
|
+
if (path instanceof RegExp) {
|
|
122
|
+
this.regexp = path;
|
|
123
|
+
} else {
|
|
124
|
+
this.regexp = pathToRegexp.pathToRegexp(path, this.regexpKeys, options);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
class Layer {
|
|
130
|
+
// --------------------------------------------------
|
|
131
|
+
isError() {
|
|
132
|
+
return this.fn.length === 4;
|
|
133
|
+
}
|
|
134
|
+
dispatch(req, res, meta, next, err) {
|
|
135
|
+
core.setRequestParams(req, meta.params || {});
|
|
136
|
+
core.setRequestMountPath(req, meta.mountPath || '/');
|
|
137
|
+
if (typeof err !== 'undefined') {
|
|
138
|
+
if (this.fn.length === 4) {
|
|
139
|
+
try {
|
|
140
|
+
this.fn(err, req, res, next);
|
|
141
|
+
} catch (e) {
|
|
142
|
+
/* istanbul ignore next */ /* istanbul ignore next */ if (e instanceof Error) {
|
|
143
|
+
next(e);
|
|
144
|
+
} else {
|
|
145
|
+
next(new http.BadRequestError({
|
|
146
|
+
message: 'The request could not be processed by the error handler.'
|
|
147
|
+
}));
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
152
|
+
/* istanbul ignore next */ next(err);
|
|
153
|
+
/* istanbul ignore next */ return;
|
|
154
|
+
}
|
|
155
|
+
/* istanbul ignore next */ if (this.fn.length > 3) {
|
|
156
|
+
next();
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
159
|
+
try {
|
|
160
|
+
const output = this.fn(req, res, next);
|
|
161
|
+
processHandlerExecutionOutput(res, next, output);
|
|
162
|
+
} catch (e) {
|
|
163
|
+
/* istanbul ignore next */ if (e instanceof Error) {
|
|
164
|
+
next(e);
|
|
165
|
+
} else {
|
|
166
|
+
next(new http.BadRequestError({
|
|
167
|
+
message: 'The request could not be processed by the handler.'
|
|
168
|
+
}));
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
// --------------------------------------------------
|
|
173
|
+
matchPath(path) {
|
|
174
|
+
return this.pathMatcher.test(path);
|
|
175
|
+
}
|
|
176
|
+
exec(path) {
|
|
177
|
+
return this.pathMatcher.exec(path);
|
|
178
|
+
}
|
|
179
|
+
// --------------------------------------------------
|
|
180
|
+
constructor(options, fn){
|
|
181
|
+
this['@instanceof'] = Symbol.for('Layer');
|
|
182
|
+
this.pathMatcher = new PathMatcher(options.path, options.pathMatcher);
|
|
183
|
+
this.fn = fn;
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
function isLayerInstance(input) {
|
|
188
|
+
return isInstance(input, 'Layer');
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
class Route {
|
|
192
|
+
// --------------------------------------------------
|
|
193
|
+
matchPath(path) {
|
|
194
|
+
return this.pathMatcher.test(path);
|
|
195
|
+
}
|
|
196
|
+
matchMethod(method) {
|
|
197
|
+
let name = method.toLowerCase();
|
|
198
|
+
if (name === core.Method.HEAD && !smob.hasOwnProperty(this.layers, name)) {
|
|
199
|
+
name = core.Method.GET;
|
|
200
|
+
}
|
|
201
|
+
return Object.prototype.hasOwnProperty.call(this.layers, name);
|
|
202
|
+
}
|
|
203
|
+
// --------------------------------------------------
|
|
204
|
+
getMethods() {
|
|
205
|
+
const keys = Object.keys(this.layers);
|
|
206
|
+
if (smob.hasOwnProperty(this.layers, core.Method.GET) && !smob.hasOwnProperty(this.layers, core.Method.HEAD)) {
|
|
207
|
+
keys.push(core.Method.HEAD);
|
|
208
|
+
}
|
|
209
|
+
return keys;
|
|
210
|
+
}
|
|
211
|
+
// --------------------------------------------------
|
|
212
|
+
dispatch(req, res, meta, done) {
|
|
213
|
+
/* istanbul ignore next */ if (!req.method) {
|
|
214
|
+
done();
|
|
215
|
+
return;
|
|
216
|
+
}
|
|
217
|
+
let name = req.method.toLowerCase();
|
|
218
|
+
if (name === core.Method.HEAD && !smob.hasOwnProperty(this.layers, name)) {
|
|
219
|
+
name = core.Method.GET;
|
|
220
|
+
}
|
|
221
|
+
const layers = this.layers[name];
|
|
222
|
+
/* istanbul ignore next */ if (typeof layers === 'undefined' || layers.length === 0 || typeof meta.path === 'undefined') {
|
|
223
|
+
done();
|
|
224
|
+
return;
|
|
225
|
+
}
|
|
226
|
+
const layerMeta = {
|
|
227
|
+
...meta
|
|
228
|
+
};
|
|
229
|
+
const output = this.pathMatcher.exec(meta.path);
|
|
230
|
+
if (output) {
|
|
231
|
+
layerMeta.params = smob.merge({}, meta.params || {}, output.params);
|
|
232
|
+
}
|
|
233
|
+
let index = -1;
|
|
234
|
+
const next = (err)=>{
|
|
235
|
+
index++;
|
|
236
|
+
if (index >= layers.length) {
|
|
237
|
+
setImmediate(done, err);
|
|
238
|
+
return;
|
|
239
|
+
}
|
|
240
|
+
const layer = layers[index];
|
|
241
|
+
if (err && !layer.isError()) {
|
|
242
|
+
next(err);
|
|
243
|
+
return;
|
|
244
|
+
}
|
|
245
|
+
layer.dispatch(req, res, {
|
|
246
|
+
...layerMeta
|
|
247
|
+
}, next);
|
|
248
|
+
};
|
|
249
|
+
next();
|
|
250
|
+
}
|
|
251
|
+
// --------------------------------------------------
|
|
252
|
+
register(method, ...handlers) {
|
|
253
|
+
this.layers[method] = [];
|
|
254
|
+
for(let i = 0; i < handlers.length; i++){
|
|
255
|
+
const layer = new Layer({
|
|
256
|
+
path: this.path,
|
|
257
|
+
pathMatcher: this.pathMatcherOptions
|
|
258
|
+
}, handlers[i]);
|
|
259
|
+
this.layers[method].push(layer);
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
get(...handlers) {
|
|
263
|
+
return this.register(core.Method.GET, ...handlers);
|
|
264
|
+
}
|
|
265
|
+
post(...handlers) {
|
|
266
|
+
return this.register(core.Method.POST, ...handlers);
|
|
267
|
+
}
|
|
268
|
+
put(...handlers) {
|
|
269
|
+
return this.register(core.Method.PUT, ...handlers);
|
|
270
|
+
}
|
|
271
|
+
patch(...handlers) {
|
|
272
|
+
return this.register(core.Method.PATCH, ...handlers);
|
|
273
|
+
}
|
|
274
|
+
delete(...handlers) {
|
|
275
|
+
return this.register(core.Method.DELETE, ...handlers);
|
|
276
|
+
}
|
|
277
|
+
head(...handlers) {
|
|
278
|
+
return this.register(core.Method.HEAD, ...handlers);
|
|
279
|
+
}
|
|
280
|
+
options(...handlers) {
|
|
281
|
+
return this.register(core.Method.OPTIONS, ...handlers);
|
|
282
|
+
}
|
|
283
|
+
// --------------------------------------------------
|
|
284
|
+
isStrictPath() {
|
|
285
|
+
return typeof this.path !== 'string' || this.path !== '/' && this.path.length !== 0;
|
|
286
|
+
}
|
|
287
|
+
// --------------------------------------------------
|
|
288
|
+
constructor(options){
|
|
289
|
+
this['@instanceof'] = Symbol.for('Route');
|
|
290
|
+
this.layers = {};
|
|
291
|
+
this.path = options.path;
|
|
292
|
+
this.pathMatcherOptions = {
|
|
293
|
+
end: true,
|
|
294
|
+
strict: this.isStrictPath(),
|
|
295
|
+
...options.pathMatcher
|
|
296
|
+
};
|
|
297
|
+
this.pathMatcher = new PathMatcher(this.path, this.pathMatcherOptions);
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
function isRouteInstance(input) {
|
|
302
|
+
return isInstance(input, 'Route');
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
function isRouterInstance(input) {
|
|
306
|
+
return isInstance(input, 'Router');
|
|
307
|
+
}
|
|
308
|
+
class Router {
|
|
309
|
+
// --------------------------------------------------
|
|
310
|
+
setPathMatcherOptions(input) {
|
|
311
|
+
this.pathMatcherOptions = input;
|
|
312
|
+
if (this.pathMatcher) {
|
|
313
|
+
this.pathMatcher.regexpOptions = this.pathMatcherOptions;
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
setPath(value) {
|
|
317
|
+
if (value === '/' || !isPath(value)) {
|
|
318
|
+
this.path = '/';
|
|
319
|
+
return;
|
|
320
|
+
}
|
|
321
|
+
if (typeof value === 'string') {
|
|
322
|
+
this.path = core.withLeadingSlash(core.withoutTrailingSlash(`${value}`));
|
|
323
|
+
} else {
|
|
324
|
+
this.path = value;
|
|
325
|
+
}
|
|
326
|
+
this.pathMatcher = new PathMatcher(this.path, this.pathMatcherOptions);
|
|
327
|
+
}
|
|
328
|
+
// --------------------------------------------------
|
|
329
|
+
createListener() {
|
|
330
|
+
this.isRoot = true;
|
|
331
|
+
return (req, res)=>{
|
|
332
|
+
this.dispatch(req, res);
|
|
333
|
+
};
|
|
334
|
+
}
|
|
335
|
+
/* istanbul ignore next */ listen(port) {
|
|
336
|
+
const server = node_http.createServer(this.createListener());
|
|
337
|
+
return server.listen(port);
|
|
338
|
+
}
|
|
339
|
+
// --------------------------------------------------
|
|
340
|
+
matchPath(path) {
|
|
341
|
+
if (this.pathMatcher) {
|
|
342
|
+
return this.pathMatcher.test(path);
|
|
343
|
+
}
|
|
344
|
+
return true;
|
|
345
|
+
}
|
|
346
|
+
// --------------------------------------------------
|
|
347
|
+
dispatch(req, res, meta, done) {
|
|
348
|
+
let index = -1;
|
|
349
|
+
meta = meta || {};
|
|
350
|
+
let allowedMethods = [];
|
|
351
|
+
if (this.isRoot && typeof this.timeout === 'number') {
|
|
352
|
+
createRequestTimeout(res, this.timeout, done);
|
|
353
|
+
}
|
|
354
|
+
const fn = (err)=>{
|
|
355
|
+
/* istanbul ignore if */ if (!this.isRoot) {
|
|
356
|
+
if (typeof done !== 'undefined') {
|
|
357
|
+
setImmediate(()=>done(err));
|
|
358
|
+
}
|
|
359
|
+
return;
|
|
360
|
+
}
|
|
361
|
+
if (typeof err !== 'undefined') {
|
|
362
|
+
res.statusCode = 400;
|
|
363
|
+
res.end();
|
|
364
|
+
return;
|
|
365
|
+
}
|
|
366
|
+
if (req.method && req.method.toLowerCase() === core.Method.OPTIONS) {
|
|
367
|
+
const options = allowedMethods.map((key)=>key.toUpperCase()).join(',');
|
|
368
|
+
res.setHeader(core.HeaderName.ALLOW, options);
|
|
369
|
+
core.send(res, options);
|
|
370
|
+
return;
|
|
371
|
+
}
|
|
372
|
+
res.statusCode = 404;
|
|
373
|
+
res.end();
|
|
374
|
+
};
|
|
375
|
+
let path = meta.path || core.useRequestPath(req);
|
|
376
|
+
if (this.pathMatcher) {
|
|
377
|
+
const output = this.pathMatcher.exec(path);
|
|
378
|
+
if (typeof output !== 'undefined') {
|
|
379
|
+
meta.mountPath = core.cleanDoubleSlashes(`${meta.mountPath || ''}/${output.path}`);
|
|
380
|
+
if (path === output.path) {
|
|
381
|
+
path = '/';
|
|
382
|
+
} else {
|
|
383
|
+
path = core.withLeadingSlash(path.substring(output.path.length));
|
|
384
|
+
}
|
|
385
|
+
meta.params = smob.merge(meta.params || {}, output.params);
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
meta.path = path;
|
|
389
|
+
if (!meta.mountPath) {
|
|
390
|
+
meta.mountPath = '/';
|
|
391
|
+
}
|
|
392
|
+
const next = (err)=>{
|
|
393
|
+
if (index >= this.stack.length) {
|
|
394
|
+
setImmediate(fn, err);
|
|
395
|
+
return;
|
|
396
|
+
}
|
|
397
|
+
let layer;
|
|
398
|
+
let match = false;
|
|
399
|
+
while(!match && index < this.stack.length){
|
|
400
|
+
index++;
|
|
401
|
+
layer = this.stack[index];
|
|
402
|
+
if (isLayerInstance(layer)) {
|
|
403
|
+
if (!layer.isError() && err) {
|
|
404
|
+
continue;
|
|
405
|
+
}
|
|
406
|
+
match = layer.matchPath(path);
|
|
407
|
+
}
|
|
408
|
+
if (isRouterInstance(layer)) {
|
|
409
|
+
match = layer.matchPath(path);
|
|
410
|
+
}
|
|
411
|
+
if (isRouteInstance(layer)) {
|
|
412
|
+
match = layer.matchPath(path);
|
|
413
|
+
if (req.method && !layer.matchMethod(req.method)) {
|
|
414
|
+
match = false;
|
|
415
|
+
if (req.method.toLowerCase() === core.Method.OPTIONS) {
|
|
416
|
+
allowedMethods = smob.mergeArrays(allowedMethods, layer.getMethods(), true);
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
if (!match || !layer) {
|
|
422
|
+
setImmediate(fn, err);
|
|
423
|
+
return;
|
|
424
|
+
}
|
|
425
|
+
const layerMeta = {
|
|
426
|
+
...meta
|
|
427
|
+
};
|
|
428
|
+
if (isLayerInstance(layer)) {
|
|
429
|
+
const output = layer.exec(path);
|
|
430
|
+
if (output) {
|
|
431
|
+
layerMeta.params = smob.merge(output.params, layerMeta.params || {});
|
|
432
|
+
layerMeta.mountPath = core.cleanDoubleSlashes(`${layerMeta.mountPath || ''}/${output.path}`);
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
if (err) {
|
|
436
|
+
if (isLayerInstance(layer) && layer.isError()) {
|
|
437
|
+
layer.dispatch(req, res, layerMeta, next, err);
|
|
438
|
+
return;
|
|
439
|
+
}
|
|
440
|
+
/* istanbul ignore next */ setImmediate(next, err);
|
|
441
|
+
return;
|
|
442
|
+
}
|
|
443
|
+
layer.dispatch(req, res, layerMeta, next);
|
|
444
|
+
};
|
|
445
|
+
next();
|
|
446
|
+
}
|
|
447
|
+
/* istanbul ignore next */ dispatchAsync(req, res) {
|
|
448
|
+
return new Promise((resolve, reject)=>{
|
|
449
|
+
this.dispatch(req, res, {}, (err)=>{
|
|
450
|
+
if (err) {
|
|
451
|
+
reject(err);
|
|
452
|
+
return;
|
|
453
|
+
}
|
|
454
|
+
resolve();
|
|
455
|
+
});
|
|
456
|
+
});
|
|
457
|
+
}
|
|
458
|
+
// --------------------------------------------------
|
|
459
|
+
route(path) {
|
|
460
|
+
if (typeof path === 'string' && path.length > 0) {
|
|
461
|
+
path = core.withLeadingSlash(path);
|
|
462
|
+
}
|
|
463
|
+
const index = this.stack.findIndex((item)=>isRouteInstance(item) && item.path === path);
|
|
464
|
+
if (index !== -1) {
|
|
465
|
+
return this.stack[index];
|
|
466
|
+
}
|
|
467
|
+
const route = new Route({
|
|
468
|
+
path,
|
|
469
|
+
pathMatcher: {
|
|
470
|
+
sensitive: this.pathMatcherOptions.sensitive
|
|
471
|
+
}
|
|
472
|
+
});
|
|
473
|
+
this.stack.push(route);
|
|
474
|
+
return route;
|
|
475
|
+
}
|
|
476
|
+
delete(path, ...handlers) {
|
|
477
|
+
const route = this.route(path);
|
|
478
|
+
route.delete(...handlers);
|
|
479
|
+
return this;
|
|
480
|
+
}
|
|
481
|
+
get(path, ...handlers) {
|
|
482
|
+
const route = this.route(path);
|
|
483
|
+
route.get(...handlers);
|
|
484
|
+
return this;
|
|
485
|
+
}
|
|
486
|
+
post(path, ...handlers) {
|
|
487
|
+
const route = this.route(path);
|
|
488
|
+
route.post(...handlers);
|
|
489
|
+
return this;
|
|
490
|
+
}
|
|
491
|
+
put(path, ...handlers) {
|
|
492
|
+
const route = this.route(path);
|
|
493
|
+
route.put(...handlers);
|
|
494
|
+
return this;
|
|
495
|
+
}
|
|
496
|
+
patch(path, ...handlers) {
|
|
497
|
+
const route = this.route(path);
|
|
498
|
+
route.patch(...handlers);
|
|
499
|
+
return this;
|
|
500
|
+
}
|
|
501
|
+
head(path, ...handlers) {
|
|
502
|
+
const route = this.route(path);
|
|
503
|
+
route.head(...handlers);
|
|
504
|
+
return this;
|
|
505
|
+
}
|
|
506
|
+
options(path, ...handlers) {
|
|
507
|
+
const route = this.route(path);
|
|
508
|
+
route.options(...handlers);
|
|
509
|
+
return this;
|
|
510
|
+
}
|
|
511
|
+
use(...input) {
|
|
512
|
+
/* istanbul ignore next */ if (input.length === 0) {
|
|
513
|
+
return this;
|
|
514
|
+
}
|
|
515
|
+
let path;
|
|
516
|
+
if (isPath(input[0])) {
|
|
517
|
+
path = input.shift();
|
|
518
|
+
}
|
|
519
|
+
for(let i = 0; i < input.length; i++){
|
|
520
|
+
const item = input[i];
|
|
521
|
+
if (isRouterInstance(item)) {
|
|
522
|
+
if (path) {
|
|
523
|
+
item.setPath(path);
|
|
524
|
+
}
|
|
525
|
+
item.setPathMatcherOptions(this.pathMatcherOptions);
|
|
526
|
+
this.stack.push(item);
|
|
527
|
+
continue;
|
|
528
|
+
}
|
|
529
|
+
if (typeof item === 'function') {
|
|
530
|
+
this.stack.push(new Layer({
|
|
531
|
+
path: path || '/',
|
|
532
|
+
pathMatcher: {
|
|
533
|
+
strict: false,
|
|
534
|
+
end: false,
|
|
535
|
+
sensitive: this.pathMatcherOptions.sensitive
|
|
536
|
+
}
|
|
537
|
+
}, item));
|
|
538
|
+
}
|
|
539
|
+
}
|
|
540
|
+
return this;
|
|
541
|
+
}
|
|
542
|
+
// --------------------------------------------------
|
|
543
|
+
constructor(ctx){
|
|
544
|
+
this['@instanceof'] = Symbol.for('Router');
|
|
545
|
+
/**
|
|
546
|
+
* Array of mounted layers, routes & routers.
|
|
547
|
+
*
|
|
548
|
+
* @protected
|
|
549
|
+
*/ this.stack = [];
|
|
550
|
+
ctx = ctx || {};
|
|
551
|
+
this.pathMatcherOptions = {
|
|
552
|
+
end: false,
|
|
553
|
+
sensitive: true,
|
|
554
|
+
...ctx.pathMatcher || {}
|
|
555
|
+
};
|
|
556
|
+
this.timeout = ctx.timeout;
|
|
557
|
+
this.setPath(ctx.path || '/');
|
|
558
|
+
}
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
exports.Layer = Layer;
|
|
562
|
+
exports.PathMatcher = PathMatcher;
|
|
563
|
+
exports.Route = Route;
|
|
564
|
+
exports.Router = Router;
|
|
565
|
+
exports.createRequestTimeout = createRequestTimeout;
|
|
566
|
+
exports.isInstance = isInstance;
|
|
567
|
+
exports.isLayerInstance = isLayerInstance;
|
|
568
|
+
exports.isPath = isPath;
|
|
569
|
+
exports.isPromise = isPromise;
|
|
570
|
+
exports.isRouteInstance = isRouteInstance;
|
|
571
|
+
exports.isRouterInstance = isRouterInstance;
|
|
572
|
+
exports.processHandlerExecutionOutput = processHandlerExecutionOutput;
|
|
573
|
+
Object.keys(core).forEach(function (k) {
|
|
574
|
+
if (k !== 'default' && !exports.hasOwnProperty(k)) Object.defineProperty(exports, k, {
|
|
575
|
+
enumerable: true,
|
|
576
|
+
get: function () { return core[k]; }
|
|
577
|
+
});
|
|
578
|
+
});
|
|
579
|
+
//# sourceMappingURL=index.cjs.map
|