@eggjs/router 2.0.1 → 3.0.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 +90 -53
- package/dist/commonjs/EggRouter.d.ts +102 -0
- package/dist/commonjs/EggRouter.js +235 -0
- package/dist/commonjs/Layer.d.ts +114 -0
- package/dist/commonjs/Layer.js +237 -0
- package/dist/commonjs/Router.d.ts +494 -0
- package/dist/commonjs/Router.js +760 -0
- package/dist/commonjs/index.d.ts +5 -0
- package/dist/commonjs/index.js +23 -0
- package/dist/commonjs/package.json +3 -0
- package/dist/commonjs/types.d.ts +18 -0
- package/dist/commonjs/types.js +3 -0
- package/dist/esm/EggRouter.d.ts +102 -0
- package/dist/esm/EggRouter.js +228 -0
- package/dist/esm/Layer.d.ts +114 -0
- package/dist/esm/Layer.js +230 -0
- package/dist/esm/Router.d.ts +494 -0
- package/dist/esm/Router.js +753 -0
- package/dist/esm/index.d.ts +5 -0
- package/dist/esm/index.js +6 -0
- package/dist/esm/package.json +3 -0
- package/dist/esm/types.d.ts +18 -0
- package/dist/esm/types.js +2 -0
- package/package.json +64 -33
- package/src/EggRouter.ts +338 -0
- package/src/Layer.ts +274 -0
- package/src/Router.ts +1060 -0
- package/src/index.ts +7 -0
- package/src/types.ts +15 -0
- package/History.md +0 -187
- package/index.js +0 -10
- package/lib/egg_router.js +0 -327
- package/lib/layer.js +0 -217
- package/lib/router.js +0 -724
- package/lib/utils.js +0 -18
package/lib/router.js
DELETED
|
@@ -1,724 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* RESTful resource routing middleware for eggjs.
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
const debug = require('debug')('egg-router');
|
|
8
|
-
const compose = require('koa-compose');
|
|
9
|
-
const HttpError = require('http-errors');
|
|
10
|
-
const methods = require('methods');
|
|
11
|
-
const Layer = require('./layer');
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* @module koa-router
|
|
15
|
-
*/
|
|
16
|
-
class Router {
|
|
17
|
-
/**
|
|
18
|
-
* Create a new router.
|
|
19
|
-
*
|
|
20
|
-
* @example
|
|
21
|
-
*
|
|
22
|
-
* Basic usage:
|
|
23
|
-
*
|
|
24
|
-
* ```javascript
|
|
25
|
-
* var Koa = require('koa');
|
|
26
|
-
* var Router = require('koa-router');
|
|
27
|
-
*
|
|
28
|
-
* var app = new Koa();
|
|
29
|
-
* var router = new Router();
|
|
30
|
-
*
|
|
31
|
-
* router.get('/', (ctx, next) => {
|
|
32
|
-
* // ctx.router available
|
|
33
|
-
* });
|
|
34
|
-
*
|
|
35
|
-
* app
|
|
36
|
-
* .use(router.routes())
|
|
37
|
-
* .use(router.allowedMethods());
|
|
38
|
-
* ```
|
|
39
|
-
*
|
|
40
|
-
* @alias module:koa-router
|
|
41
|
-
* @param {Object=} opts optional
|
|
42
|
-
* @param {String=} opts.prefix prefix router paths
|
|
43
|
-
* @class
|
|
44
|
-
*/
|
|
45
|
-
constructor(opts) {
|
|
46
|
-
this.opts = opts || {};
|
|
47
|
-
this.methods = this.opts.methods || [
|
|
48
|
-
'HEAD',
|
|
49
|
-
'OPTIONS',
|
|
50
|
-
'GET',
|
|
51
|
-
'PUT',
|
|
52
|
-
'PATCH',
|
|
53
|
-
'POST',
|
|
54
|
-
'DELETE',
|
|
55
|
-
];
|
|
56
|
-
|
|
57
|
-
this.params = {};
|
|
58
|
-
this.stack = [];
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
/**
|
|
62
|
-
* Use given middleware.
|
|
63
|
-
*
|
|
64
|
-
* Middleware run in the order they are defined by `.use()`. They are invoked
|
|
65
|
-
* sequentially, requests start at the first middleware and work their way
|
|
66
|
-
* "down" the middleware stack.
|
|
67
|
-
*
|
|
68
|
-
* @example
|
|
69
|
-
*
|
|
70
|
-
* ```javascript
|
|
71
|
-
* // session middleware will run before authorize
|
|
72
|
-
* router
|
|
73
|
-
* .use(session())
|
|
74
|
-
* .use(authorize());
|
|
75
|
-
*
|
|
76
|
-
* // use middleware only with given path
|
|
77
|
-
* router.use('/users', userAuth());
|
|
78
|
-
*
|
|
79
|
-
* // or with an array of paths
|
|
80
|
-
* router.use(['/users', '/admin'], userAuth());
|
|
81
|
-
*
|
|
82
|
-
* app.use(router.routes());
|
|
83
|
-
* ```
|
|
84
|
-
*
|
|
85
|
-
* @param {String=} path path string
|
|
86
|
-
* @param {Function} middleware middleware function
|
|
87
|
-
* @return {Router} router instance
|
|
88
|
-
*/
|
|
89
|
-
use(/* path, middleware */) {
|
|
90
|
-
const router = this;
|
|
91
|
-
const middleware = Array.prototype.slice.call(arguments);
|
|
92
|
-
let path;
|
|
93
|
-
|
|
94
|
-
// support array of paths
|
|
95
|
-
if (Array.isArray(middleware[0]) && typeof middleware[0][0] === 'string') {
|
|
96
|
-
middleware[0].forEach(function(p) {
|
|
97
|
-
router.use.apply(router, [ p ].concat(middleware.slice(1)));
|
|
98
|
-
});
|
|
99
|
-
|
|
100
|
-
return this;
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
const hasPath = typeof middleware[0] === 'string';
|
|
104
|
-
if (hasPath) {
|
|
105
|
-
path = middleware.shift();
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
middleware.forEach(function(m) {
|
|
109
|
-
if (m.router) {
|
|
110
|
-
m.router.stack.forEach(function(nestedLayer) {
|
|
111
|
-
if (path) nestedLayer.setPrefix(path);
|
|
112
|
-
if (router.opts.prefix) nestedLayer.setPrefix(router.opts.prefix);
|
|
113
|
-
router.stack.push(nestedLayer);
|
|
114
|
-
});
|
|
115
|
-
|
|
116
|
-
if (router.params) {
|
|
117
|
-
Object.keys(router.params).forEach(function(key) {
|
|
118
|
-
m.router.param(key, router.params[key]);
|
|
119
|
-
});
|
|
120
|
-
}
|
|
121
|
-
} else {
|
|
122
|
-
router.register(path || '(.*)', [], m, { end: false, ignoreCaptures: !hasPath });
|
|
123
|
-
}
|
|
124
|
-
});
|
|
125
|
-
|
|
126
|
-
return this;
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
/**
|
|
130
|
-
* Set the path prefix for a Router instance that was already initialized.
|
|
131
|
-
*
|
|
132
|
-
* @example
|
|
133
|
-
*
|
|
134
|
-
* ```javascript
|
|
135
|
-
* router.prefix('/things/:thing_id')
|
|
136
|
-
* ```
|
|
137
|
-
*
|
|
138
|
-
* @param {String} prefix prefix string
|
|
139
|
-
* @return {Router} router instance
|
|
140
|
-
*/
|
|
141
|
-
prefix(prefix) {
|
|
142
|
-
prefix = prefix.replace(/\/$/, '');
|
|
143
|
-
|
|
144
|
-
this.opts.prefix = prefix;
|
|
145
|
-
|
|
146
|
-
this.stack.forEach(function(route) {
|
|
147
|
-
route.setPrefix(prefix);
|
|
148
|
-
});
|
|
149
|
-
|
|
150
|
-
return this;
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
/**
|
|
154
|
-
* Returns router middleware which dispatches a route matching the request.
|
|
155
|
-
*
|
|
156
|
-
* @return {Function} middleware function
|
|
157
|
-
*/
|
|
158
|
-
routes() {
|
|
159
|
-
const router = this;
|
|
160
|
-
|
|
161
|
-
const dispatch = function dispatch(ctx, next) {
|
|
162
|
-
debug('%s %s', ctx.method, ctx.path);
|
|
163
|
-
|
|
164
|
-
const path = router.opts.routerPath || ctx.routerPath || ctx.path;
|
|
165
|
-
const matched = router.match(path, ctx.method);
|
|
166
|
-
|
|
167
|
-
if (ctx.matched) {
|
|
168
|
-
ctx.matched.push.apply(ctx.matched, matched.path);
|
|
169
|
-
} else {
|
|
170
|
-
ctx.matched = matched.path;
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
ctx.router = router;
|
|
174
|
-
|
|
175
|
-
if (!matched.route) return next();
|
|
176
|
-
|
|
177
|
-
const matchedLayers = matched.pathAndMethod;
|
|
178
|
-
const layerChain = matchedLayers.reduce(function(memo, layer) {
|
|
179
|
-
memo.push(function(ctx, next) {
|
|
180
|
-
ctx.captures = layer.captures(path, ctx.captures);
|
|
181
|
-
ctx.params = layer.params(path, ctx.captures, ctx.params);
|
|
182
|
-
// ctx._matchedRouteName & ctx._matchedRoute for compatibility
|
|
183
|
-
ctx._matchedRouteName = ctx.routerName = layer.name;
|
|
184
|
-
if (!layer.name) ctx._matchedRouteName = undefined;
|
|
185
|
-
ctx._matchedRoute = ctx.routerPath = layer.path;
|
|
186
|
-
return next();
|
|
187
|
-
});
|
|
188
|
-
return memo.concat(layer.stack);
|
|
189
|
-
}, []);
|
|
190
|
-
|
|
191
|
-
return compose(layerChain)(ctx, next);
|
|
192
|
-
};
|
|
193
|
-
|
|
194
|
-
dispatch.router = this;
|
|
195
|
-
|
|
196
|
-
return dispatch;
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
/**
|
|
200
|
-
* Returns separate middleware for responding to `OPTIONS` requests with
|
|
201
|
-
* an `Allow` header containing the allowed methods, as well as responding
|
|
202
|
-
* with `405 Method Not Allowed` and `501 Not Implemented` as appropriate.
|
|
203
|
-
*
|
|
204
|
-
* @example
|
|
205
|
-
*
|
|
206
|
-
* ```javascript
|
|
207
|
-
* var Koa = require('koa');
|
|
208
|
-
* var Router = require('koa-router');
|
|
209
|
-
*
|
|
210
|
-
* var app = new Koa();
|
|
211
|
-
* var router = new Router();
|
|
212
|
-
*
|
|
213
|
-
* app.use(router.routes());
|
|
214
|
-
* app.use(router.allowedMethods());
|
|
215
|
-
* ```
|
|
216
|
-
*
|
|
217
|
-
* **Example with [Boom](https://github.com/hapijs/boom)**
|
|
218
|
-
*
|
|
219
|
-
* ```javascript
|
|
220
|
-
* var Koa = require('koa');
|
|
221
|
-
* var Router = require('koa-router');
|
|
222
|
-
* var Boom = require('boom');
|
|
223
|
-
*
|
|
224
|
-
* var app = new Koa();
|
|
225
|
-
* var router = new Router();
|
|
226
|
-
*
|
|
227
|
-
* app.use(router.routes());
|
|
228
|
-
* app.use(router.allowedMethods({
|
|
229
|
-
* throw: true,
|
|
230
|
-
* notImplemented: () => new Boom.notImplemented(),
|
|
231
|
-
* methodNotAllowed: () => new Boom.methodNotAllowed()
|
|
232
|
-
* }));
|
|
233
|
-
* ```
|
|
234
|
-
*
|
|
235
|
-
* @param {Object=} options optional params
|
|
236
|
-
* @param {Boolean=} options.throw throw error instead of setting status and header
|
|
237
|
-
* @param {Function=} options.notImplemented throw the returned value in place of the default NotImplemented error
|
|
238
|
-
* @param {Function=} options.methodNotAllowed throw the returned value in place of the default MethodNotAllowed error
|
|
239
|
-
* @return {Function} middleware function
|
|
240
|
-
*/
|
|
241
|
-
allowedMethods(options) {
|
|
242
|
-
options = options || {};
|
|
243
|
-
const implemented = this.methods;
|
|
244
|
-
|
|
245
|
-
return function allowedMethods(ctx, next) {
|
|
246
|
-
return next().then(function() {
|
|
247
|
-
const allowed = {};
|
|
248
|
-
|
|
249
|
-
if (!ctx.status || ctx.status === 404) {
|
|
250
|
-
ctx.matched.forEach(function(route) {
|
|
251
|
-
route.methods.forEach(function(method) {
|
|
252
|
-
allowed[method] = method;
|
|
253
|
-
});
|
|
254
|
-
});
|
|
255
|
-
|
|
256
|
-
const allowedArr = Object.keys(allowed);
|
|
257
|
-
|
|
258
|
-
if (!implemented.includes(ctx.method)) {
|
|
259
|
-
if (options.throw) {
|
|
260
|
-
let notImplementedThrowable;
|
|
261
|
-
if (typeof options.notImplemented === 'function') {
|
|
262
|
-
notImplementedThrowable = options.notImplemented(); // set whatever the user returns from their function
|
|
263
|
-
} else {
|
|
264
|
-
notImplementedThrowable = new HttpError.NotImplemented();
|
|
265
|
-
}
|
|
266
|
-
throw notImplementedThrowable;
|
|
267
|
-
} else {
|
|
268
|
-
ctx.status = 501;
|
|
269
|
-
ctx.set('Allow', allowedArr.join(', '));
|
|
270
|
-
}
|
|
271
|
-
} else if (allowedArr.length) {
|
|
272
|
-
if (ctx.method === 'OPTIONS') {
|
|
273
|
-
ctx.status = 200;
|
|
274
|
-
ctx.body = '';
|
|
275
|
-
ctx.set('Allow', allowedArr.join(', '));
|
|
276
|
-
} else if (!allowed[ctx.method]) {
|
|
277
|
-
if (options.throw) {
|
|
278
|
-
let notAllowedThrowable;
|
|
279
|
-
if (typeof options.methodNotAllowed === 'function') {
|
|
280
|
-
notAllowedThrowable = options.methodNotAllowed(); // set whatever the user returns from their function
|
|
281
|
-
} else {
|
|
282
|
-
notAllowedThrowable = new HttpError.MethodNotAllowed();
|
|
283
|
-
}
|
|
284
|
-
throw notAllowedThrowable;
|
|
285
|
-
} else {
|
|
286
|
-
ctx.status = 405;
|
|
287
|
-
ctx.set('Allow', allowedArr.join(', '));
|
|
288
|
-
}
|
|
289
|
-
}
|
|
290
|
-
}
|
|
291
|
-
}
|
|
292
|
-
});
|
|
293
|
-
};
|
|
294
|
-
}
|
|
295
|
-
|
|
296
|
-
/**
|
|
297
|
-
* Register route with all methods.
|
|
298
|
-
*
|
|
299
|
-
* @param {String} name Optional.
|
|
300
|
-
* @param {String} path path string
|
|
301
|
-
* @param {Function=} middleware You may also pass multiple middleware.
|
|
302
|
-
* @param {Function} callback callback function
|
|
303
|
-
* @return {Router} router instance
|
|
304
|
-
* @private
|
|
305
|
-
*/
|
|
306
|
-
all(name, path/* , middleware */) {
|
|
307
|
-
let middleware;
|
|
308
|
-
|
|
309
|
-
if (typeof path === 'string') {
|
|
310
|
-
middleware = Array.prototype.slice.call(arguments, 2);
|
|
311
|
-
} else {
|
|
312
|
-
middleware = Array.prototype.slice.call(arguments, 1);
|
|
313
|
-
path = name;
|
|
314
|
-
name = null;
|
|
315
|
-
}
|
|
316
|
-
|
|
317
|
-
this.register(path, methods, middleware, {
|
|
318
|
-
name,
|
|
319
|
-
});
|
|
320
|
-
|
|
321
|
-
return this;
|
|
322
|
-
}
|
|
323
|
-
|
|
324
|
-
/**
|
|
325
|
-
* Redirect `source` to `destination` URL with optional 30x status `code`.
|
|
326
|
-
*
|
|
327
|
-
* Both `source` and `destination` can be route names.
|
|
328
|
-
*
|
|
329
|
-
* ```javascript
|
|
330
|
-
* router.redirect('/login', 'sign-in');
|
|
331
|
-
* ```
|
|
332
|
-
*
|
|
333
|
-
* This is equivalent to:
|
|
334
|
-
*
|
|
335
|
-
* ```javascript
|
|
336
|
-
* router.all('/login', ctx => {
|
|
337
|
-
* ctx.redirect('/sign-in');
|
|
338
|
-
* ctx.status = 301;
|
|
339
|
-
* });
|
|
340
|
-
* ```
|
|
341
|
-
*
|
|
342
|
-
* @param {String} source URL or route name.
|
|
343
|
-
* @param {String} destination URL or route name.
|
|
344
|
-
* @param {Number=} code HTTP status code (default: 301).
|
|
345
|
-
* @return {Router} router instance
|
|
346
|
-
*/
|
|
347
|
-
redirect(source, destination, code) {
|
|
348
|
-
// lookup source route by name
|
|
349
|
-
if (source[0] !== '/') {
|
|
350
|
-
source = this.url(source);
|
|
351
|
-
}
|
|
352
|
-
|
|
353
|
-
// lookup destination route by name
|
|
354
|
-
if (destination[0] !== '/') {
|
|
355
|
-
destination = this.url(destination);
|
|
356
|
-
}
|
|
357
|
-
|
|
358
|
-
return this.all(source, ctx => {
|
|
359
|
-
ctx.redirect(destination);
|
|
360
|
-
ctx.status = code || 301;
|
|
361
|
-
});
|
|
362
|
-
}
|
|
363
|
-
|
|
364
|
-
/**
|
|
365
|
-
* Create and register a route.
|
|
366
|
-
*
|
|
367
|
-
* @param {String} path Path string.
|
|
368
|
-
* @param {Array.<String>} methods Array of HTTP verbs.
|
|
369
|
-
* @param {Function} middleware Multiple middleware also accepted.
|
|
370
|
-
* @param {Object} [opts] optional params
|
|
371
|
-
* @return {Layer} layer instance
|
|
372
|
-
* @private
|
|
373
|
-
*/
|
|
374
|
-
register(path, methods, middleware, opts) {
|
|
375
|
-
opts = opts || {};
|
|
376
|
-
|
|
377
|
-
const router = this;
|
|
378
|
-
const stack = this.stack;
|
|
379
|
-
|
|
380
|
-
// support array of paths
|
|
381
|
-
if (Array.isArray(path)) {
|
|
382
|
-
path.forEach(function(p) {
|
|
383
|
-
router.register.call(router, p, methods, middleware, opts);
|
|
384
|
-
});
|
|
385
|
-
|
|
386
|
-
return this;
|
|
387
|
-
}
|
|
388
|
-
|
|
389
|
-
// create route
|
|
390
|
-
const route = new Layer(path, methods, middleware, {
|
|
391
|
-
end: opts.end === false ? opts.end : true,
|
|
392
|
-
name: opts.name,
|
|
393
|
-
sensitive: opts.sensitive || this.opts.sensitive || false,
|
|
394
|
-
strict: opts.strict || this.opts.strict || false,
|
|
395
|
-
prefix: opts.prefix || this.opts.prefix || '',
|
|
396
|
-
ignoreCaptures: opts.ignoreCaptures,
|
|
397
|
-
});
|
|
398
|
-
|
|
399
|
-
if (this.opts.prefix) {
|
|
400
|
-
route.setPrefix(this.opts.prefix);
|
|
401
|
-
}
|
|
402
|
-
|
|
403
|
-
// add parameter middleware
|
|
404
|
-
Object.keys(this.params).forEach(function(param) {
|
|
405
|
-
route.param(param, this.params[param]);
|
|
406
|
-
}, this);
|
|
407
|
-
|
|
408
|
-
stack.push(route);
|
|
409
|
-
|
|
410
|
-
return route;
|
|
411
|
-
}
|
|
412
|
-
|
|
413
|
-
/**
|
|
414
|
-
* Lookup route with given `name`.
|
|
415
|
-
*
|
|
416
|
-
* @param {String} name route name
|
|
417
|
-
* @return {Layer|false} layer instance of false
|
|
418
|
-
*/
|
|
419
|
-
route(name) {
|
|
420
|
-
const routes = this.stack;
|
|
421
|
-
|
|
422
|
-
for (let len = routes.length, i = 0; i < len; i++) {
|
|
423
|
-
if (routes[i].name && routes[i].name === name) {
|
|
424
|
-
return routes[i];
|
|
425
|
-
}
|
|
426
|
-
}
|
|
427
|
-
|
|
428
|
-
return false;
|
|
429
|
-
}
|
|
430
|
-
|
|
431
|
-
/**
|
|
432
|
-
* Generate URL for route. Takes a route name and map of named `params`.
|
|
433
|
-
*
|
|
434
|
-
* @example
|
|
435
|
-
*
|
|
436
|
-
* ```javascript
|
|
437
|
-
* router.get('user', '/users/:id', (ctx, next) => {
|
|
438
|
-
* // ...
|
|
439
|
-
* });
|
|
440
|
-
*
|
|
441
|
-
* router.url('user', 3);
|
|
442
|
-
* // => "/users/3"
|
|
443
|
-
*
|
|
444
|
-
* router.url('user', { id: 3 });
|
|
445
|
-
* // => "/users/3"
|
|
446
|
-
*
|
|
447
|
-
* router.use((ctx, next) => {
|
|
448
|
-
* // redirect to named route
|
|
449
|
-
* ctx.redirect(ctx.router.url('sign-in'));
|
|
450
|
-
* })
|
|
451
|
-
*
|
|
452
|
-
* router.url('user', { id: 3 }, { query: { limit: 1 } });
|
|
453
|
-
* // => "/users/3?limit=1"
|
|
454
|
-
*
|
|
455
|
-
* router.url('user', { id: 3 }, { query: "limit=1" });
|
|
456
|
-
* // => "/users/3?limit=1"
|
|
457
|
-
* ```
|
|
458
|
-
*
|
|
459
|
-
* @param {String} name route name
|
|
460
|
-
* @param {Object} params url parameters
|
|
461
|
-
* @param {Object} [options] options parameter
|
|
462
|
-
* @param {Object|String} [options.query] query options
|
|
463
|
-
* @return {String|Error} string or error instance
|
|
464
|
-
*/
|
|
465
|
-
url(name/* , params */) {
|
|
466
|
-
const route = this.route(name);
|
|
467
|
-
|
|
468
|
-
if (route) {
|
|
469
|
-
const args = Array.prototype.slice.call(arguments, 1);
|
|
470
|
-
return route.url.apply(route, args);
|
|
471
|
-
}
|
|
472
|
-
|
|
473
|
-
return new Error('No route found for name: ' + name);
|
|
474
|
-
}
|
|
475
|
-
|
|
476
|
-
/**
|
|
477
|
-
* Match given `path` and return corresponding routes.
|
|
478
|
-
*
|
|
479
|
-
* @param {String} path path string
|
|
480
|
-
* @param {String} method method name
|
|
481
|
-
* @return {Object.<path, pathAndMethod>} returns layers that matched path and
|
|
482
|
-
* path and method.
|
|
483
|
-
* @private
|
|
484
|
-
*/
|
|
485
|
-
match(path, method) {
|
|
486
|
-
const layers = this.stack;
|
|
487
|
-
let layer;
|
|
488
|
-
const matched = {
|
|
489
|
-
// matched path
|
|
490
|
-
path: [],
|
|
491
|
-
// matched path and method(including none method)
|
|
492
|
-
pathAndMethod: [],
|
|
493
|
-
// method matched or not
|
|
494
|
-
route: false,
|
|
495
|
-
};
|
|
496
|
-
|
|
497
|
-
for (let len = layers.length, i = 0; i < len; i++) {
|
|
498
|
-
layer = layers[i];
|
|
499
|
-
|
|
500
|
-
debug('test %s %s', layer.path, layer.regexp);
|
|
501
|
-
|
|
502
|
-
if (layer.match(path)) {
|
|
503
|
-
matched.path.push(layer);
|
|
504
|
-
|
|
505
|
-
if (layer.methods.length === 0 || layer.methods.includes(method)) {
|
|
506
|
-
matched.pathAndMethod.push(layer);
|
|
507
|
-
if (layer.methods.length) matched.route = true;
|
|
508
|
-
}
|
|
509
|
-
// if (layer.methods.length === 0) {
|
|
510
|
-
// matched.pathAndMethod.push(layer);
|
|
511
|
-
// } else if (layer.methods.includes(method)) {
|
|
512
|
-
// matched.pathAndMethod.push(layer);
|
|
513
|
-
// matched.route = true;
|
|
514
|
-
// }
|
|
515
|
-
}
|
|
516
|
-
}
|
|
517
|
-
|
|
518
|
-
return matched;
|
|
519
|
-
}
|
|
520
|
-
|
|
521
|
-
/**
|
|
522
|
-
* Run middleware for named route parameters. Useful for auto-loading or
|
|
523
|
-
* validation.
|
|
524
|
-
*
|
|
525
|
-
* @example
|
|
526
|
-
*
|
|
527
|
-
* ```javascript
|
|
528
|
-
* router
|
|
529
|
-
* .param('user', (id, ctx, next) => {
|
|
530
|
-
* ctx.user = users[id];
|
|
531
|
-
* if (!ctx.user) return ctx.status = 404;
|
|
532
|
-
* return next();
|
|
533
|
-
* })
|
|
534
|
-
* .get('/users/:user', ctx => {
|
|
535
|
-
* ctx.body = ctx.user;
|
|
536
|
-
* })
|
|
537
|
-
* .get('/users/:user/friends', ctx => {
|
|
538
|
-
* return ctx.user.getFriends().then(function(friends) {
|
|
539
|
-
* ctx.body = friends;
|
|
540
|
-
* });
|
|
541
|
-
* })
|
|
542
|
-
* // /users/3 => {"id": 3, "name": "Alex"}
|
|
543
|
-
* // /users/3/friends => [{"id": 4, "name": "TJ"}]
|
|
544
|
-
* ```
|
|
545
|
-
*
|
|
546
|
-
* @param {String} param param
|
|
547
|
-
* @param {Function} middleware route middleware
|
|
548
|
-
* @return {Router} instance
|
|
549
|
-
*/
|
|
550
|
-
param(param, middleware) {
|
|
551
|
-
this.params[param] = middleware;
|
|
552
|
-
this.stack.forEach(function(route) {
|
|
553
|
-
route.param(param, middleware);
|
|
554
|
-
});
|
|
555
|
-
return this;
|
|
556
|
-
}
|
|
557
|
-
}
|
|
558
|
-
|
|
559
|
-
/**
|
|
560
|
-
* Create `router.verb()` methods, where *verb* is one of the HTTP verbs such
|
|
561
|
-
* as `router.get()` or `router.post()`.
|
|
562
|
-
*
|
|
563
|
-
* Match URL patterns to callback functions or controller actions using `router.verb()`,
|
|
564
|
-
* where **verb** is one of the HTTP verbs such as `router.get()` or `router.post()`.
|
|
565
|
-
*
|
|
566
|
-
* Additionaly, `router.all()` can be used to match against all methods.
|
|
567
|
-
*
|
|
568
|
-
* ```javascript
|
|
569
|
-
* router
|
|
570
|
-
* .get('/', (ctx, next) => {
|
|
571
|
-
* ctx.body = 'Hello World!';
|
|
572
|
-
* })
|
|
573
|
-
* .post('/users', (ctx, next) => {
|
|
574
|
-
* // ...
|
|
575
|
-
* })
|
|
576
|
-
* .put('/users/:id', (ctx, next) => {
|
|
577
|
-
* // ...
|
|
578
|
-
* })
|
|
579
|
-
* .del('/users/:id', (ctx, next) => {
|
|
580
|
-
* // ...
|
|
581
|
-
* })
|
|
582
|
-
* .all('/users/:id', (ctx, next) => {
|
|
583
|
-
* // ...
|
|
584
|
-
* });
|
|
585
|
-
* ```
|
|
586
|
-
*
|
|
587
|
-
* When a route is matched, its path is available at `ctx._matchedRoute` and if named,
|
|
588
|
-
* the name is available at `ctx._matchedRouteName`
|
|
589
|
-
*
|
|
590
|
-
* Route paths will be translated to regular expressions using
|
|
591
|
-
* [path-to-regexp](https://github.com/pillarjs/path-to-regexp).
|
|
592
|
-
*
|
|
593
|
-
* Query strings will not be considered when matching requests.
|
|
594
|
-
*
|
|
595
|
-
* #### Named routes
|
|
596
|
-
*
|
|
597
|
-
* Routes can optionally have names. This allows generation of URLs and easy
|
|
598
|
-
* renaming of URLs during development.
|
|
599
|
-
*
|
|
600
|
-
* ```javascript
|
|
601
|
-
* router.get('user', '/users/:id', (ctx, next) => {
|
|
602
|
-
* // ...
|
|
603
|
-
* });
|
|
604
|
-
*
|
|
605
|
-
* router.url('user', 3);
|
|
606
|
-
* // => "/users/3"
|
|
607
|
-
* ```
|
|
608
|
-
*
|
|
609
|
-
* #### Multiple middleware
|
|
610
|
-
*
|
|
611
|
-
* Multiple middleware may be given:
|
|
612
|
-
*
|
|
613
|
-
* ```javascript
|
|
614
|
-
* router.get(
|
|
615
|
-
* '/users/:id',
|
|
616
|
-
* (ctx, next) => {
|
|
617
|
-
* return User.findOne(ctx.params.id).then(function(user) {
|
|
618
|
-
* ctx.user = user;
|
|
619
|
-
* next();
|
|
620
|
-
* });
|
|
621
|
-
* },
|
|
622
|
-
* ctx => {
|
|
623
|
-
* console.log(ctx.user);
|
|
624
|
-
* // => { id: 17, name: "Alex" }
|
|
625
|
-
* }
|
|
626
|
-
* );
|
|
627
|
-
* ```
|
|
628
|
-
*
|
|
629
|
-
* ### Nested routers
|
|
630
|
-
*
|
|
631
|
-
* Nesting routers is supported:
|
|
632
|
-
*
|
|
633
|
-
* ```javascript
|
|
634
|
-
* var forums = new Router();
|
|
635
|
-
* var posts = new Router();
|
|
636
|
-
*
|
|
637
|
-
* posts.get('/', (ctx, next) => {...});
|
|
638
|
-
* posts.get('/:pid', (ctx, next) => {...});
|
|
639
|
-
* forums.use('/forums/:fid/posts', posts.routes(), posts.allowedMethods());
|
|
640
|
-
*
|
|
641
|
-
* // responds to "/forums/123/posts" and "/forums/123/posts/123"
|
|
642
|
-
* app.use(forums.routes());
|
|
643
|
-
* ```
|
|
644
|
-
*
|
|
645
|
-
* #### Router prefixes
|
|
646
|
-
*
|
|
647
|
-
* Route paths can be prefixed at the router level:
|
|
648
|
-
*
|
|
649
|
-
* ```javascript
|
|
650
|
-
* var router = new Router({
|
|
651
|
-
* prefix: '/users'
|
|
652
|
-
* });
|
|
653
|
-
*
|
|
654
|
-
* router.get('/', ...); // responds to "/users"
|
|
655
|
-
* router.get('/:id', ...); // responds to "/users/:id"
|
|
656
|
-
* ```
|
|
657
|
-
*
|
|
658
|
-
* #### URL parameters
|
|
659
|
-
*
|
|
660
|
-
* Named route parameters are captured and added to `ctx.params`.
|
|
661
|
-
*
|
|
662
|
-
* ```javascript
|
|
663
|
-
* router.get('/:category/:title', (ctx, next) => {
|
|
664
|
-
* console.log(ctx.params);
|
|
665
|
-
* // => { category: 'programming', title: 'how-to-node' }
|
|
666
|
-
* });
|
|
667
|
-
* ```
|
|
668
|
-
*
|
|
669
|
-
* The [path-to-regexp](https://github.com/pillarjs/path-to-regexp) module is
|
|
670
|
-
* used to convert paths to regular expressions.
|
|
671
|
-
*
|
|
672
|
-
* @name get|put|post|patch|delete|del
|
|
673
|
-
* @memberof module:koa-router.prototype
|
|
674
|
-
* @param {String} path
|
|
675
|
-
* @param {Function=} middleware route middleware(s)
|
|
676
|
-
* @param {Function} callback route callback
|
|
677
|
-
* @returns {Router}
|
|
678
|
-
*/
|
|
679
|
-
|
|
680
|
-
methods.forEach(function(method) {
|
|
681
|
-
Router.prototype[method] = function(name, path /* , middleware */) {
|
|
682
|
-
let middleware;
|
|
683
|
-
|
|
684
|
-
if (typeof path === 'string' || path instanceof RegExp) {
|
|
685
|
-
middleware = Array.prototype.slice.call(arguments, 2);
|
|
686
|
-
} else {
|
|
687
|
-
middleware = Array.prototype.slice.call(arguments, 1);
|
|
688
|
-
path = name;
|
|
689
|
-
name = null;
|
|
690
|
-
}
|
|
691
|
-
|
|
692
|
-
this.register(path, [ method ], middleware, {
|
|
693
|
-
name,
|
|
694
|
-
});
|
|
695
|
-
|
|
696
|
-
return this;
|
|
697
|
-
};
|
|
698
|
-
});
|
|
699
|
-
|
|
700
|
-
// Alias for `router.delete()` because delete is a reserved word
|
|
701
|
-
Router.prototype.del = Router.prototype.delete;
|
|
702
|
-
|
|
703
|
-
/**
|
|
704
|
-
* Generate URL from url pattern and given `params`.
|
|
705
|
-
*
|
|
706
|
-
* @example
|
|
707
|
-
*
|
|
708
|
-
* ```javascript
|
|
709
|
-
* var url = Router.url('/users/:id', {id: 1});
|
|
710
|
-
* // => "/users/1"
|
|
711
|
-
* ```
|
|
712
|
-
*
|
|
713
|
-
* @param {String} path url pattern
|
|
714
|
-
* @param {Object} params url parameters
|
|
715
|
-
* @return {String} url string
|
|
716
|
-
*/
|
|
717
|
-
Router.url = function(path/* , params */) {
|
|
718
|
-
const args = Array.prototype.slice.call(arguments, 1);
|
|
719
|
-
return Layer.prototype.url.apply({ path }, args);
|
|
720
|
-
};
|
|
721
|
-
|
|
722
|
-
Router.prototype.middleware = Router.prototype.routes;
|
|
723
|
-
|
|
724
|
-
module.exports = Router;
|