@eggjs/router 3.0.6 → 4.0.0-beta.17

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/src/Router.ts DELETED
@@ -1,1087 +0,0 @@
1
- /**
2
- * RESTful resource routing middleware for eggjs.
3
- */
4
-
5
- import { debuglog } from 'node:util';
6
- import assert from 'node:assert';
7
- import compose from 'koa-compose';
8
- import HttpError from 'http-errors';
9
- import methods from 'methods';
10
- import { Layer, LayerURLOptions } from './Layer.js';
11
- import { MiddlewareFunc, MiddlewareFuncWithRouter, Next, ParamMiddlewareFunc, ResourcesController } from './types.js';
12
-
13
- const debug = debuglog('@eggjs/router:Router');
14
-
15
- export type RouterMethod = typeof methods[0];
16
-
17
- export interface RouterOptions {
18
- methods?: string[];
19
- prefix?: string;
20
- sensitive?: boolean;
21
- strict?: boolean;
22
- routerPath?: string;
23
- }
24
-
25
- export interface RegisterOptions {
26
- name?: string;
27
- prefix?: string;
28
- sensitive?: boolean;
29
- strict?: boolean;
30
- ignoreCaptures?: boolean;
31
- end?: boolean;
32
- }
33
-
34
- export interface AllowedMethodsOptions {
35
- throw?: boolean;
36
- notImplemented?: () => Error;
37
- methodNotAllowed?: () => Error;
38
- }
39
-
40
- export interface MatchedResult {
41
- // matched path
42
- path: Layer[];
43
- // matched path and method(including none method)
44
- pathAndMethod: Layer[];
45
- // method matched or not
46
- route: boolean;
47
- }
48
-
49
- export class Router {
50
- readonly opts: RouterOptions;
51
- readonly methods: string[];
52
- /** Layer stack */
53
- readonly stack: Layer[] = [];
54
- readonly params: Record<string, ParamMiddlewareFunc> = {};
55
-
56
- /**
57
- * Create a new router.
58
- *
59
- * @example
60
- *
61
- * Basic usage:
62
- *
63
- * ```javascript
64
- * var Koa = require('koa');
65
- * var Router = require('koa-router');
66
- *
67
- * var app = new Koa();
68
- * var router = new Router();
69
- *
70
- * router.get('/', (ctx, next) => {
71
- * // ctx.router available
72
- * });
73
- *
74
- * app
75
- * .use(router.routes())
76
- * .use(router.allowedMethods());
77
- * ```
78
- *
79
- * @alias module:koa-router
80
- * @param {Object=} opts optional
81
- * @param {String=} opts.prefix prefix router paths
82
- * @class
83
- */
84
- constructor(opts?: RouterOptions) {
85
- this.opts = opts ?? {};
86
- this.methods = this.opts.methods ?? [
87
- 'HEAD',
88
- 'OPTIONS',
89
- 'GET',
90
- 'PUT',
91
- 'PATCH',
92
- 'POST',
93
- 'DELETE',
94
- ];
95
- }
96
-
97
- /**
98
- * Use given middleware.
99
- *
100
- * Middleware run in the order they are defined by `.use()`. They are invoked
101
- * sequentially, requests start at the first middleware and work their way
102
- * "down" the middleware stack.
103
- *
104
- * @example
105
- *
106
- * ```javascript
107
- * // session middleware will run before authorize
108
- * router
109
- * .use(session())
110
- * .use(authorize());
111
- *
112
- * // use middleware only with given path
113
- * router.use('/users', userAuth());
114
- *
115
- * // or with an array of paths
116
- * router.use(['/users', '/admin'], userAuth());
117
- *
118
- * app.use(router.routes());
119
- * ```
120
- *
121
- * @param {String=} path path string
122
- * @param {Function} middleware middleware function
123
- * @return {Router} router instance
124
- */
125
- use(...middlewares: MiddlewareFunc[]): Router;
126
- use(path: string | string[], ...middlewares: MiddlewareFunc[]): Router;
127
- use(pathOrMiddleware: string | string[] | MiddlewareFunc, ...middlewares: MiddlewareFunc[]): Router {
128
- // support array of paths
129
- // use(paths, ...middlewares)
130
- if (Array.isArray(pathOrMiddleware) && typeof pathOrMiddleware[0] === 'string') {
131
- for (const path of pathOrMiddleware) {
132
- this.use(path, ...middlewares);
133
- }
134
- return this;
135
- }
136
-
137
- let path = '';
138
- let hasPath = false;
139
- if (typeof pathOrMiddleware === 'string') {
140
- // use(path, ...middlewares)
141
- path = pathOrMiddleware;
142
- hasPath = true;
143
- } else if (typeof pathOrMiddleware === 'function') {
144
- // use(...middlewares)
145
- middlewares = [ pathOrMiddleware, ...middlewares ];
146
- }
147
-
148
- for (const m of middlewares as MiddlewareFuncWithRouter<Router>[]) {
149
- if (m.router) {
150
- for (const nestedLayer of m.router.stack) {
151
- if (path) {
152
- nestedLayer.setPrefix(path);
153
- }
154
- if (this.opts.prefix) {
155
- nestedLayer.setPrefix(this.opts.prefix);
156
- }
157
- this.stack.push(nestedLayer);
158
- }
159
-
160
- if (this.params) {
161
- for (const key in this.params) {
162
- m.router.param(key, this.params[key]);
163
- }
164
- }
165
- } else {
166
- this.register(path || '(.*)', [], m, { end: false, ignoreCaptures: !hasPath });
167
- }
168
- }
169
-
170
- return this;
171
- }
172
-
173
- /**
174
- * Set the path prefix for a Router instance that was already initialized.
175
- *
176
- * @example
177
- *
178
- * ```javascript
179
- * router.prefix('/things/:thing_id')
180
- * ```
181
- *
182
- * @param {String} prefix prefix string
183
- * @return {Router} router instance
184
- */
185
- prefix(prefix: string): Router {
186
- prefix = prefix.replace(/\/$/, '');
187
- this.opts.prefix = prefix;
188
-
189
- for (const layer of this.stack) {
190
- layer.setPrefix(prefix);
191
- }
192
-
193
- return this;
194
- }
195
-
196
- /**
197
- * Returns router middleware which dispatches a route matching the request.
198
- *
199
- * @return {Function} middleware function
200
- */
201
- routes(): MiddlewareFuncWithRouter<Router> {
202
- const dispatch = (ctx: any, next: Next) => {
203
- const routerPath: string = this.opts.routerPath || ctx.routerPath || ctx.path;
204
- const matched = this.match(routerPath, ctx.method);
205
- debug('dispatch: %s %s, routerPath: %s, matched: %s',
206
- ctx.method, ctx.path, routerPath, matched.route);
207
-
208
- if (ctx.matched) {
209
- (ctx.matched as Layer[]).push(...matched.path);
210
- } else {
211
- ctx.matched = matched.path;
212
- }
213
- ctx.router = this;
214
-
215
- if (!matched.route) {
216
- return next();
217
- }
218
-
219
- const matchedLayers = matched.pathAndMethod;
220
- const layerChain = matchedLayers.reduce<MiddlewareFunc[]>((memo, layer) => {
221
- memo.push((ctx, next) => {
222
- // ctx.captures = layer.captures(routerPath, ctx.captures);
223
- ctx.captures = layer.captures(routerPath);
224
- ctx.params = layer.params(routerPath, ctx.captures, ctx.params);
225
- // ctx._matchedRouteName & ctx._matchedRoute for compatibility
226
- ctx._matchedRouteName = ctx.routerName = layer.name;
227
- if (!layer.name) {
228
- ctx._matchedRouteName = undefined;
229
- }
230
- ctx._matchedRoute = ctx.routerPath = layer.path;
231
- return next();
232
- });
233
- return memo.concat(layer.stack);
234
- }, []);
235
-
236
- return compose(layerChain)(ctx, next);
237
- };
238
-
239
- dispatch.router = this;
240
- return dispatch;
241
- }
242
-
243
- /**
244
- * @alias to routes()
245
- */
246
- middleware() {
247
- return this.routes();
248
- }
249
-
250
- /**
251
- * Returns separate middleware for responding to `OPTIONS` requests with
252
- * an `Allow` header containing the allowed methods, as well as responding
253
- * with `405 Method Not Allowed` and `501 Not Implemented` as appropriate.
254
- *
255
- * @example
256
- *
257
- * ```javascript
258
- * var Koa = require('koa');
259
- * var Router = require('koa-router');
260
- *
261
- * var app = new Koa();
262
- * var router = new Router();
263
- *
264
- * app.use(router.routes());
265
- * app.use(router.allowedMethods());
266
- * ```
267
- *
268
- * **Example with [Boom](https://github.com/hapijs/boom)**
269
- *
270
- * ```javascript
271
- * var Koa = require('koa');
272
- * var Router = require('koa-router');
273
- * var Boom = require('boom');
274
- *
275
- * var app = new Koa();
276
- * var router = new Router();
277
- *
278
- * app.use(router.routes());
279
- * app.use(router.allowedMethods({
280
- * throw: true,
281
- * notImplemented: () => new Boom.notImplemented(),
282
- * methodNotAllowed: () => new Boom.methodNotAllowed()
283
- * }));
284
- * ```
285
- *
286
- * @param {Object=} options optional params
287
- * @param {Boolean=} options.throw throw error instead of setting status and header
288
- * @param {Function=} options.notImplemented throw the returned value in place of the default NotImplemented error
289
- * @param {Function=} options.methodNotAllowed throw the returned value in place of the default MethodNotAllowed error
290
- * @return {Function} middleware function
291
- */
292
- allowedMethods(options?: AllowedMethodsOptions): MiddlewareFunc {
293
- const implemented = this.methods;
294
-
295
- return async function allowedMethods(ctx: any, next: Next) {
296
- await next();
297
- if (ctx.status && ctx.status !== 404) return;
298
-
299
- const allowed: Record<string, string> = {};
300
- ctx.matched.forEach((route: Router) => {
301
- route.methods.forEach(method => {
302
- allowed[method] = method;
303
- });
304
- });
305
- const allowedMethods = Object.keys(allowed);
306
-
307
- if (!implemented.includes(ctx.method)) {
308
- if (options?.throw) {
309
- let notImplementedThrowable: Error;
310
- if (typeof options?.notImplemented === 'function') {
311
- notImplementedThrowable = options.notImplemented(); // set whatever the user returns from their function
312
- } else {
313
- notImplementedThrowable = new HttpError.NotImplemented();
314
- }
315
- throw notImplementedThrowable;
316
- } else {
317
- ctx.status = 501;
318
- ctx.set('Allow', allowedMethods.join(', '));
319
- }
320
- } else if (allowedMethods.length > 0) {
321
- if (ctx.method === 'OPTIONS') {
322
- ctx.status = 200;
323
- ctx.body = '';
324
- ctx.set('Allow', allowedMethods.join(', '));
325
- } else if (!allowed[ctx.method]) {
326
- if (options?.throw) {
327
- let notAllowedThrowable: Error;
328
- if (typeof options?.methodNotAllowed === 'function') {
329
- notAllowedThrowable = options.methodNotAllowed(); // set whatever the user returns from their function
330
- } else {
331
- notAllowedThrowable = new HttpError.MethodNotAllowed();
332
- }
333
- throw notAllowedThrowable;
334
- } else {
335
- ctx.status = 405;
336
- ctx.set('Allow', allowedMethods.join(', '));
337
- }
338
- }
339
- }
340
- };
341
- }
342
-
343
- /**
344
- * Redirect `source` to `destination` URL with optional 30x status `code`.
345
- *
346
- * Both `source` and `destination` can be route names.
347
- *
348
- * ```javascript
349
- * router.redirect('/login', 'sign-in');
350
- * ```
351
- *
352
- * This is equivalent to:
353
- *
354
- * ```javascript
355
- * router.all('/login', ctx => {
356
- * ctx.redirect('/sign-in');
357
- * ctx.status = 301;
358
- * });
359
- * ```
360
- *
361
- * @param {String} source URL or route name.
362
- * @param {String} destination URL or route name.
363
- * @param {Number=} status HTTP status code (default: 301).
364
- * @return {Router} router instance
365
- */
366
- redirect(source: string, destination: string, status: number = 301): Router {
367
- // lookup source route by name
368
- if (source[0] !== '/') {
369
- const routeUrl = this.url(source);
370
- if (routeUrl instanceof Error) {
371
- throw routeUrl;
372
- }
373
- source = routeUrl;
374
- }
375
-
376
- // lookup destination route by name
377
- if (destination[0] !== '/') {
378
- const routeUrl = this.url(destination);
379
- if (routeUrl instanceof Error) {
380
- throw routeUrl;
381
- }
382
- destination = routeUrl;
383
- }
384
-
385
- return this.all(source, ctx => {
386
- ctx.redirect(destination);
387
- ctx.status = status;
388
- });
389
- }
390
-
391
- /**
392
- * Create and register a route.
393
- *
394
- * @param {String|RegExp|(String|RegExp)[]} path Path string.
395
- * @param {String[]} methods Array of HTTP verbs.
396
- * @param {Function|Function[]} middleware Multiple middleware also accepted.
397
- * @param {Object} [opts] optional params
398
- * @private
399
- */
400
- register(path: string | RegExp | (string | RegExp)[],
401
- methods: string[],
402
- middleware: MiddlewareFunc | MiddlewareFunc[],
403
- opts?: RegisterOptions): Layer | Layer[] {
404
- // support array of paths
405
- if (Array.isArray(path)) {
406
- const routes: Layer[] = [];
407
- for (const p of path) {
408
- const route = this.#register(p, methods, middleware, opts);
409
- routes.push(route);
410
- }
411
- return routes;
412
- }
413
-
414
- // create route
415
- const route = this.#register(path, methods, middleware, opts);
416
- return route;
417
- }
418
-
419
- #register(path: string | RegExp,
420
- methods: string[],
421
- middleware: MiddlewareFunc | MiddlewareFunc[],
422
- opts?: RegisterOptions): Layer {
423
- opts = opts ?? {};
424
- // create route
425
- const route = new Layer(path, methods, middleware, {
426
- end: opts.end === false ? opts.end : true,
427
- name: opts.name,
428
- sensitive: opts.sensitive ?? this.opts.sensitive ?? false,
429
- strict: opts.strict ?? this.opts.strict ?? false,
430
- prefix: opts.prefix ?? this.opts.prefix ?? '',
431
- ignoreCaptures: opts.ignoreCaptures,
432
- });
433
-
434
- // FIXME: why???
435
- if (this.opts.prefix) {
436
- route.setPrefix(this.opts.prefix);
437
- }
438
-
439
- // add parameter middleware to the new route layer
440
- for (const param in this.params) {
441
- route.param(param, this.params[param]);
442
- }
443
-
444
- this.stack.push(route);
445
- return route;
446
- }
447
-
448
- /**
449
- * Lookup route with given `name`.
450
- *
451
- * @param {String} name route name
452
- * @return {Layer|false} layer instance of false
453
- */
454
- route(name: string): Layer | false {
455
- for (const route of this.stack) {
456
- if (route.name === name) {
457
- return route;
458
- }
459
- }
460
- return false;
461
- }
462
-
463
- /**
464
- * Generate URL for route. Takes a route name and map of named `params`.
465
- *
466
- * @example
467
- *
468
- * ```javascript
469
- * router.get('user', '/users/:id', (ctx, next) => {
470
- * // ...
471
- * });
472
- *
473
- * router.url('user', 3);
474
- * // => "/users/3"
475
- *
476
- * router.url('user', { id: 3 });
477
- * // => "/users/3"
478
- *
479
- * router.use((ctx, next) => {
480
- * // redirect to named route
481
- * ctx.redirect(ctx.router.url('sign-in'));
482
- * })
483
- *
484
- * router.url('user', { id: 3 }, { query: { limit: 1 } });
485
- * // => "/users/3?limit=1"
486
- *
487
- * router.url('user', { id: 3 }, { query: "limit=1" });
488
- * // => "/users/3?limit=1"
489
- * ```
490
- */
491
- url(name: string, params?: string | number | object,
492
- ...paramsOrOptions: (string | number | object | LayerURLOptions)[]): string | Error {
493
- const route = this.route(name);
494
- if (route) {
495
- return route.url(params, ...paramsOrOptions);
496
- }
497
- return new Error(`No route found for name: ${name}`);
498
- }
499
-
500
- /**
501
- * Generate URL from url pattern and given `params`.
502
- *
503
- * @example
504
- *
505
- * ```javascript
506
- * var url = Router.url('/users/:id', { id: 1 });
507
- * // => "/users/1"
508
- * ```
509
- *
510
- * @param {String} path url pattern
511
- * @param {Object} params url parameters
512
- * @return {String} url string
513
- */
514
- static url(path: string, params?: string | number | object,
515
- ...paramsOrOptions: (string | number | object | LayerURLOptions)[]): string {
516
- return Layer.prototype.url.call({ path }, params, ...paramsOrOptions);
517
- }
518
-
519
- /**
520
- * Match given `path` and return corresponding routes.
521
- *
522
- * @param {String} path path string
523
- * @param {String} method method name
524
- * @return {Object.<path, pathAndMethod>} returns layers that matched path and
525
- * path and method.
526
- * @private
527
- */
528
- match(path: string, method: string): MatchedResult {
529
- const matched: MatchedResult = {
530
- // matched path
531
- path: [],
532
- // matched path and method(including none method)
533
- pathAndMethod: [],
534
- // method matched or not
535
- route: false,
536
- };
537
-
538
- for (const layer of this.stack) {
539
- debug('test %s %s', layer.path, layer.regexp);
540
-
541
- if (layer.match(path)) {
542
- matched.path.push(layer);
543
-
544
- if (layer.methods.length === 0 || layer.methods.includes(method)) {
545
- matched.pathAndMethod.push(layer);
546
- if (layer.methods.length > 0) {
547
- matched.route = true;
548
- }
549
- }
550
- // if (layer.methods.length === 0) {
551
- // matched.pathAndMethod.push(layer);
552
- // } else if (layer.methods.includes(method)) {
553
- // matched.pathAndMethod.push(layer);
554
- // matched.route = true;
555
- // }
556
- }
557
- }
558
-
559
- return matched;
560
- }
561
-
562
- /**
563
- * Run middleware for named route parameters. Useful for auto-loading or
564
- * validation.
565
- *
566
- * @example
567
- *
568
- * ```javascript
569
- * router
570
- * .param('user', (id, ctx, next) => {
571
- * ctx.user = users[id];
572
- * if (!ctx.user) return ctx.status = 404;
573
- * return next();
574
- * })
575
- * .get('/users/:user', ctx => {
576
- * ctx.body = ctx.user;
577
- * })
578
- * .get('/users/:user/friends', ctx => {
579
- * return ctx.user.getFriends().then(function(friends) {
580
- * ctx.body = friends;
581
- * });
582
- * })
583
- * // /users/3 => {"id": 3, "name": "Alex"}
584
- * // /users/3/friends => [{"id": 4, "name": "TJ"}]
585
- * ```
586
- *
587
- * @param {String} param param
588
- * @param {Function} middleware route middleware
589
- * @return {Router} instance
590
- */
591
- param(param: string, middleware: ParamMiddlewareFunc): Router {
592
- this.params[param] = middleware;
593
- for (const route of this.stack) {
594
- route.param(param, middleware);
595
- }
596
- return this;
597
- }
598
-
599
- protected _formatRouteParams(nameOrPath: string | RegExp | (string | RegExp)[],
600
- pathOrMiddleware: string | RegExp | (string | RegExp)[] | MiddlewareFunc | ResourcesController,
601
- middlewares: (MiddlewareFunc | string | ResourcesController)[]) {
602
- const options: RegisterOptions = {};
603
- let path: string | RegExp | (string | RegExp)[];
604
- if (typeof nameOrPath === 'string' && nameOrPath.startsWith('/')) {
605
- // verb(method, path, ...middlewares)
606
- path = nameOrPath;
607
- middlewares = [ pathOrMiddleware as string, ...middlewares ];
608
- if (typeof pathOrMiddleware === 'string') {
609
- // verb(method, path, controllerString)
610
- // set controller name to router name
611
- options.name = pathOrMiddleware;
612
- }
613
- } else if (nameOrPath instanceof RegExp) {
614
- // verb(method, pathRegex, ...middlewares)
615
- path = nameOrPath;
616
- middlewares = [ pathOrMiddleware as string, ...middlewares ];
617
- if (typeof pathOrMiddleware === 'string') {
618
- // verb(method, pathRegex, controllerString)
619
- // set controller name to router name
620
- options.name = pathOrMiddleware;
621
- }
622
- } else if (Array.isArray(nameOrPath)) {
623
- // verb(method, paths, ...middlewares)
624
- path = nameOrPath;
625
- middlewares = [ pathOrMiddleware as string, ...middlewares ];
626
- if (typeof pathOrMiddleware === 'string') {
627
- // verb(method, pathRegex, controllerString)
628
- // set controller name to router name
629
- options.name = pathOrMiddleware;
630
- }
631
- } else if (typeof pathOrMiddleware === 'string' || pathOrMiddleware instanceof RegExp) {
632
- // verb(method, name, path, ...middlewares)
633
- path = pathOrMiddleware;
634
- assert(typeof nameOrPath === 'string', 'route name should be string');
635
- options.name = nameOrPath;
636
- } else if (Array.isArray(pathOrMiddleware)) {
637
- // verb(method, name, paths, ...middlewares)
638
- path = pathOrMiddleware;
639
- assert(typeof nameOrPath === 'string', 'route name should be string');
640
- options.name = nameOrPath;
641
- } else {
642
- // verb(method, path, ...middlewares)
643
- path = nameOrPath;
644
- middlewares = [ pathOrMiddleware, ...middlewares ];
645
- }
646
- return {
647
- path,
648
- middlewares,
649
- options,
650
- };
651
- }
652
-
653
- /**
654
- * Create `router.verb()` methods, where *verb* is one of the HTTP verbs such
655
- * as `router.get()` or `router.post()`.
656
- *
657
- * Match URL patterns to callback functions or controller actions using `router.verb()`,
658
- * where **verb** is one of the HTTP verbs such as `router.get()` or `router.post()`.
659
- *
660
- * Additionally, `router.all()` can be used to match against all methods.
661
- *
662
- * ```javascript
663
- * router
664
- * .get('/', (ctx, next) => {
665
- * ctx.body = 'Hello World!';
666
- * })
667
- * .post('/users', (ctx, next) => {
668
- * // ...
669
- * })
670
- * .put('/users/:id', (ctx, next) => {
671
- * // ...
672
- * })
673
- * .del('/users/:id', (ctx, next) => {
674
- * // ...
675
- * })
676
- * .all('/users/:id', (ctx, next) => {
677
- * // ...
678
- * });
679
- * ```
680
- *
681
- * When a route is matched, its path is available at `ctx._matchedRoute` and if named,
682
- * the name is available at `ctx._matchedRouteName`
683
- *
684
- * Route paths will be translated to regular expressions using
685
- * [path-to-regexp](https://github.com/pillarjs/path-to-regexp).
686
- *
687
- * Query strings will not be considered when matching requests.
688
- *
689
- * #### Named routes
690
- *
691
- * Routes can optionally have names. This allows generation of URLs and easy
692
- * renaming of URLs during development.
693
- *
694
- * ```javascript
695
- * router.get('user', '/users/:id', (ctx, next) => {
696
- * // ...
697
- * });
698
- *
699
- * router.url('user', 3);
700
- * // => "/users/3"
701
- * ```
702
- *
703
- * #### Multiple middleware
704
- *
705
- * Multiple middleware may be given:
706
- *
707
- * ```javascript
708
- * router.get(
709
- * '/users/:id',
710
- * (ctx, next) => {
711
- * return User.findOne(ctx.params.id).then(function(user) {
712
- * ctx.user = user;
713
- * next();
714
- * });
715
- * },
716
- * ctx => {
717
- * console.log(ctx.user);
718
- * // => { id: 17, name: "Alex" }
719
- * }
720
- * );
721
- * ```
722
- *
723
- * ### Nested routers
724
- *
725
- * Nesting routers is supported:
726
- *
727
- * ```javascript
728
- * var forums = new Router();
729
- * var posts = new Router();
730
- *
731
- * posts.get('/', (ctx, next) => {...});
732
- * posts.get('/:pid', (ctx, next) => {...});
733
- * forums.use('/forums/:fid/posts', posts.routes(), posts.allowedMethods());
734
- *
735
- * // responds to "/forums/123/posts" and "/forums/123/posts/123"
736
- * app.use(forums.routes());
737
- * ```
738
- *
739
- * #### Router prefixes
740
- *
741
- * Route paths can be prefixed at the router level:
742
- *
743
- * ```javascript
744
- * var router = new Router({
745
- * prefix: '/users'
746
- * });
747
- *
748
- * router.get('/', ...); // responds to "/users"
749
- * router.get('/:id', ...); // responds to "/users/:id"
750
- * ```
751
- *
752
- * #### URL parameters
753
- *
754
- * Named route parameters are captured and added to `ctx.params`.
755
- *
756
- * ```javascript
757
- * router.get('/:category/:title', (ctx, next) => {
758
- * console.log(ctx.params);
759
- * // => { category: 'programming', title: 'how-to-node' }
760
- * });
761
- * ```
762
- *
763
- * The [path-to-regexp](https://github.com/pillarjs/path-to-regexp) module is
764
- * used to convert paths to regular expressions.
765
- *
766
- */
767
- verb(method: string | string[],
768
- nameOrPath: string | RegExp | (string | RegExp)[],
769
- pathOrMiddleware: string | RegExp | (string | RegExp)[] | MiddlewareFunc,
770
- ...middleware: MiddlewareFunc[]): Router {
771
- const { options, path, middlewares } = this._formatRouteParams(nameOrPath, pathOrMiddleware, middleware);
772
- if (typeof method === 'string') {
773
- method = [ method ];
774
- }
775
- this.register(path, method, middlewares as MiddlewareFunc[], options);
776
- return this;
777
- }
778
-
779
- /**
780
- * Register route with all methods.
781
- *
782
- * @param {String} name Optional.
783
- * @param {String} path path string
784
- * @param {Function=} middleware You may also pass multiple middleware.
785
- * @return {Router} router instance
786
- * @private
787
- */
788
- all(path: string | RegExp | (string | RegExp)[], ...middlewares: MiddlewareFunc[]): Router;
789
- all(name: string, path: string | RegExp | (string | RegExp)[], ...middlewares: MiddlewareFunc[]): Router;
790
- all(nameOrPath: string | RegExp | (string | RegExp)[],
791
- pathOrMiddleware: string | RegExp | (string | RegExp)[] | MiddlewareFunc,
792
- ...middlewares: MiddlewareFunc[]): Router {
793
- return this.verb(methods, nameOrPath, pathOrMiddleware, ...middlewares);
794
- }
795
-
796
- // "acl", "bind", "checkout", "connect", "copy", "delete", "get", "head", "link", "lock",
797
- // "m-search", "merge", "mkactivity", "mkcalendar", "mkcol", "move", "notify", "options",
798
- // "patch", "post", "propfind", "proppatch", "purge", "put", "rebind", "report", "search",
799
- // "source", "subscribe", "trace", "unbind", "unlink", "unlock", "unsubscribe"
800
- acl(path: string | RegExp | (string | RegExp)[], ...middlewares: MiddlewareFunc[]): Router;
801
- acl(name: string, path: string | RegExp | (string | RegExp)[], ...middlewares: MiddlewareFunc[]): Router;
802
- acl(nameOrPath: string | RegExp | (string | RegExp)[],
803
- pathOrMiddleware: string | RegExp | (string | RegExp)[] | MiddlewareFunc,
804
- ...middlewares: MiddlewareFunc[]): Router {
805
- return this.verb('acl', nameOrPath, pathOrMiddleware, ...middlewares);
806
- }
807
-
808
- bind(path: string | RegExp | (string | RegExp)[], ...middlewares: MiddlewareFunc[]): Router;
809
- bind(name: string, path: string | RegExp | (string | RegExp)[], ...middlewares: MiddlewareFunc[]): Router;
810
- bind(nameOrPath: string | RegExp | (string | RegExp)[],
811
- pathOrMiddleware: string | RegExp | (string | RegExp)[] | MiddlewareFunc,
812
- ...middlewares: MiddlewareFunc[]): Router {
813
- return this.verb('bind', nameOrPath, pathOrMiddleware, ...middlewares);
814
- }
815
-
816
- checkout(path: string | RegExp | (string | RegExp)[], ...middlewares: MiddlewareFunc[]): Router;
817
- checkout(name: string, path: string | RegExp | (string | RegExp)[], ...middlewares: MiddlewareFunc[]): Router;
818
- checkout(nameOrPath: string | RegExp | (string | RegExp)[],
819
- pathOrMiddleware: string | RegExp | (string | RegExp)[] | MiddlewareFunc,
820
- ...middlewares: MiddlewareFunc[]): Router {
821
- return this.verb('checkout', nameOrPath, pathOrMiddleware, ...middlewares);
822
- }
823
-
824
- connect(path: string | RegExp | (string | RegExp)[], ...middlewares: MiddlewareFunc[]): Router;
825
- connect(name: string, path: string | RegExp | (string | RegExp)[], ...middlewares: MiddlewareFunc[]): Router;
826
- connect(nameOrPath: string | RegExp | (string | RegExp)[],
827
- pathOrMiddleware: string | RegExp | (string | RegExp)[] | MiddlewareFunc,
828
- ...middlewares: MiddlewareFunc[]): Router {
829
- return this.verb('connect', nameOrPath, pathOrMiddleware, ...middlewares);
830
- }
831
-
832
- copy(path: string | RegExp | (string | RegExp)[], ...middlewares: MiddlewareFunc[]): Router;
833
- copy(name: string, path: string | RegExp | (string | RegExp)[], ...middlewares: MiddlewareFunc[]): Router;
834
- copy(nameOrPath: string | RegExp | (string | RegExp)[],
835
- pathOrMiddleware: string | RegExp | (string | RegExp)[] | MiddlewareFunc,
836
- ...middlewares: MiddlewareFunc[]): Router {
837
- return this.verb('copy', nameOrPath, pathOrMiddleware, ...middlewares);
838
- }
839
-
840
- delete(path: string | RegExp | (string | RegExp)[], ...middlewares: MiddlewareFunc[]): Router;
841
- delete(name: string, path: string | RegExp | (string | RegExp)[], ...middlewares: MiddlewareFunc[]): Router;
842
- delete(nameOrPath: string | RegExp | (string | RegExp)[],
843
- pathOrMiddleware: string | RegExp | (string | RegExp)[] | MiddlewareFunc,
844
- ...middlewares: MiddlewareFunc[]): Router {
845
- return this.verb('delete', nameOrPath, pathOrMiddleware, ...middlewares);
846
- }
847
-
848
- /** Alias for `router.delete()` because delete is a reserved word */
849
- del(path: string | RegExp | (string | RegExp)[], ...middlewares: MiddlewareFunc[]): Router;
850
- del(name: string, path: string | RegExp | (string | RegExp)[], ...middlewares: MiddlewareFunc[]): Router;
851
- del(nameOrPath: string | RegExp | (string | RegExp)[],
852
- pathOrMiddleware: string | RegExp | (string | RegExp)[] | MiddlewareFunc,
853
- ...middlewares: MiddlewareFunc[]): Router {
854
- return this.verb('delete', nameOrPath, pathOrMiddleware, ...middlewares);
855
- }
856
-
857
- get(path: string | RegExp | (string | RegExp)[], ...middlewares: MiddlewareFunc[]): Router;
858
- get(name: string, path: string | RegExp | (string | RegExp)[], ...middlewares: MiddlewareFunc[]): Router;
859
- get(nameOrPath: string | RegExp | (string | RegExp)[],
860
- pathOrMiddleware: string | RegExp | (string | RegExp)[] | MiddlewareFunc,
861
- ...middlewares: MiddlewareFunc[]): Router {
862
- return this.verb('get', nameOrPath, pathOrMiddleware, ...middlewares);
863
- }
864
-
865
- query(path: string | RegExp | (string | RegExp)[], ...middlewares: MiddlewareFunc[]): Router;
866
- query(name: string, path: string | RegExp | (string | RegExp)[], ...middlewares: MiddlewareFunc[]): Router;
867
- query(nameOrPath: string | RegExp | (string | RegExp)[],
868
- pathOrMiddleware: string | RegExp | (string | RegExp)[] | MiddlewareFunc,
869
- ...middlewares: MiddlewareFunc[]): Router {
870
- return this.verb('query', nameOrPath, pathOrMiddleware, ...middlewares);
871
- }
872
-
873
- head(path: string | RegExp | (string | RegExp)[], ...middlewares: MiddlewareFunc[]): Router;
874
- head(name: string, path: string | RegExp | (string | RegExp)[], ...middlewares: MiddlewareFunc[]): Router;
875
- head(nameOrPath: string | RegExp | (string | RegExp)[],
876
- pathOrMiddleware: string | RegExp | (string | RegExp)[] | MiddlewareFunc,
877
- ...middlewares: MiddlewareFunc[]): Router {
878
- return this.verb('head', nameOrPath, pathOrMiddleware, ...middlewares);
879
- }
880
-
881
- link(path: string | RegExp | (string | RegExp)[], ...middlewares: MiddlewareFunc[]): Router;
882
- link(name: string, path: string | RegExp | (string | RegExp)[], ...middlewares: MiddlewareFunc[]): Router;
883
- link(nameOrPath: string | RegExp | (string | RegExp)[],
884
- pathOrMiddleware: string | RegExp | (string | RegExp)[] | MiddlewareFunc,
885
- ...middlewares: MiddlewareFunc[]): Router {
886
- return this.verb('link', nameOrPath, pathOrMiddleware, ...middlewares);
887
- }
888
-
889
- lock(path: string | RegExp | (string | RegExp)[], ...middlewares: MiddlewareFunc[]): Router;
890
- lock(name: string, path: string | RegExp | (string | RegExp)[], ...middlewares: MiddlewareFunc[]): Router;
891
- lock(nameOrPath: string | RegExp | (string | RegExp)[],
892
- pathOrMiddleware: string | RegExp | (string | RegExp)[] | MiddlewareFunc,
893
- ...middlewares: MiddlewareFunc[]): Router {
894
- return this.verb('lock', nameOrPath, pathOrMiddleware, ...middlewares);
895
- }
896
-
897
- ['m-search'](path: string | RegExp | (string | RegExp)[], ...middlewares: MiddlewareFunc[]): Router;
898
- ['m-search'](name: string, path: string | RegExp | (string | RegExp)[], ...middlewares: MiddlewareFunc[]): Router;
899
- ['m-search'](nameOrPath: string | RegExp | (string | RegExp)[],
900
- pathOrMiddleware: string | RegExp | (string | RegExp)[] | MiddlewareFunc,
901
- ...middlewares: MiddlewareFunc[]): Router {
902
- return this.verb('m-search', nameOrPath, pathOrMiddleware, ...middlewares);
903
- }
904
-
905
- merge(path: string | RegExp | (string | RegExp)[], ...middlewares: MiddlewareFunc[]): Router;
906
- merge(name: string, path: string | RegExp | (string | RegExp)[], ...middlewares: MiddlewareFunc[]): Router;
907
- merge(nameOrPath: string | RegExp | (string | RegExp)[],
908
- pathOrMiddleware: string | RegExp | (string | RegExp)[] | MiddlewareFunc,
909
- ...middlewares: MiddlewareFunc[]): Router {
910
- return this.verb('merge', nameOrPath, pathOrMiddleware, ...middlewares);
911
- }
912
-
913
- mkactivity(path: string | RegExp | (string | RegExp)[], ...middlewares: MiddlewareFunc[]): Router;
914
- mkactivity(name: string, path: string | RegExp | (string | RegExp)[], ...middlewares: MiddlewareFunc[]): Router;
915
- mkactivity(nameOrPath: string | RegExp | (string | RegExp)[],
916
- pathOrMiddleware: string | RegExp | (string | RegExp)[] | MiddlewareFunc,
917
- ...middlewares: MiddlewareFunc[]): Router {
918
- return this.verb('mkactivity', nameOrPath, pathOrMiddleware, ...middlewares);
919
- }
920
-
921
- mkcalendar(path: string | RegExp | (string | RegExp)[], ...middlewares: MiddlewareFunc[]): Router;
922
- mkcalendar(name: string, path: string | RegExp | (string | RegExp)[], ...middlewares: MiddlewareFunc[]): Router;
923
- mkcalendar(nameOrPath: string | RegExp | (string | RegExp)[],
924
- pathOrMiddleware: string | RegExp | (string | RegExp)[] | MiddlewareFunc,
925
- ...middlewares: MiddlewareFunc[]): Router {
926
- return this.verb('mkcalendar', nameOrPath, pathOrMiddleware, ...middlewares);
927
- }
928
-
929
- mkcol(path: string | RegExp | (string | RegExp)[], ...middlewares: MiddlewareFunc[]): Router;
930
- mkcol(name: string, path: string | RegExp | (string | RegExp)[], ...middlewares: MiddlewareFunc[]): Router;
931
- mkcol(nameOrPath: string | RegExp | (string | RegExp)[],
932
- pathOrMiddleware: string | RegExp | (string | RegExp)[] | MiddlewareFunc,
933
- ...middlewares: MiddlewareFunc[]): Router {
934
- return this.verb('mkcol', nameOrPath, pathOrMiddleware, ...middlewares);
935
- }
936
-
937
- move(path: string | RegExp | (string | RegExp)[], ...middlewares: MiddlewareFunc[]): Router;
938
- move(name: string, path: string | RegExp | (string | RegExp)[], ...middlewares: MiddlewareFunc[]): Router;
939
- move(nameOrPath: string | RegExp | (string | RegExp)[],
940
- pathOrMiddleware: string | RegExp | (string | RegExp)[] | MiddlewareFunc,
941
- ...middlewares: MiddlewareFunc[]): Router {
942
- return this.verb('move', nameOrPath, pathOrMiddleware, ...middlewares);
943
- }
944
-
945
- notify(path: string | RegExp | (string | RegExp)[], ...middlewares: MiddlewareFunc[]): Router;
946
- notify(name: string, path: string | RegExp | (string | RegExp)[], ...middlewares: MiddlewareFunc[]): Router;
947
- notify(nameOrPath: string | RegExp | (string | RegExp)[],
948
- pathOrMiddleware: string | RegExp | (string | RegExp)[] | MiddlewareFunc,
949
- ...middlewares: MiddlewareFunc[]): Router {
950
- return this.verb('notify', nameOrPath, pathOrMiddleware, ...middlewares);
951
- }
952
-
953
- options(path: string | RegExp | (string | RegExp)[], ...middlewares: MiddlewareFunc[]): Router;
954
- options(name: string, path: string | RegExp | (string | RegExp)[], ...middlewares: MiddlewareFunc[]): Router;
955
- options(nameOrPath: string | RegExp | (string | RegExp)[],
956
- pathOrMiddleware: string | RegExp | (string | RegExp)[] | MiddlewareFunc,
957
- ...middlewares: MiddlewareFunc[]): Router {
958
- return this.verb('options', nameOrPath, pathOrMiddleware, ...middlewares);
959
- }
960
-
961
- patch(path: string | RegExp | (string | RegExp)[], ...middlewares: MiddlewareFunc[]): Router;
962
- patch(name: string, path: string | RegExp | (string | RegExp)[], ...middlewares: MiddlewareFunc[]): Router;
963
- patch(nameOrPath: string | RegExp | (string | RegExp)[],
964
- pathOrMiddleware: string | RegExp | (string | RegExp)[] | MiddlewareFunc,
965
- ...middlewares: MiddlewareFunc[]): Router {
966
- return this.verb('patch', nameOrPath, pathOrMiddleware, ...middlewares);
967
- }
968
-
969
- post(path: string | RegExp | (string | RegExp)[], ...middlewares: MiddlewareFunc[]): Router;
970
- post(name: string, path: string | RegExp | (string | RegExp)[], ...middlewares: MiddlewareFunc[]): Router;
971
- post(nameOrPath: string | RegExp | (string | RegExp)[],
972
- pathOrMiddleware: string | RegExp | (string | RegExp)[] | MiddlewareFunc,
973
- ...middlewares: MiddlewareFunc[]): Router {
974
- return this.verb('post', nameOrPath, pathOrMiddleware, ...middlewares);
975
- }
976
-
977
- propfind(path: string | RegExp | (string | RegExp)[], ...middlewares: MiddlewareFunc[]): Router;
978
- propfind(name: string, path: string | RegExp | (string | RegExp)[], ...middlewares: MiddlewareFunc[]): Router;
979
- propfind(nameOrPath: string | RegExp | (string | RegExp)[],
980
- pathOrMiddleware: string | RegExp | (string | RegExp)[] | MiddlewareFunc,
981
- ...middlewares: MiddlewareFunc[]): Router {
982
- return this.verb('propfind', nameOrPath, pathOrMiddleware, ...middlewares);
983
- }
984
-
985
- proppatch(path: string | RegExp | (string | RegExp)[], ...middlewares: MiddlewareFunc[]): Router;
986
- proppatch(name: string, path: string | RegExp | (string | RegExp)[], ...middlewares: MiddlewareFunc[]): Router;
987
- proppatch(nameOrPath: string | RegExp | (string | RegExp)[],
988
- pathOrMiddleware: string | RegExp | (string | RegExp)[] | MiddlewareFunc,
989
- ...middlewares: MiddlewareFunc[]): Router {
990
- return this.verb('proppatch', nameOrPath, pathOrMiddleware, ...middlewares);
991
- }
992
-
993
- purge(path: string | RegExp | (string | RegExp)[], ...middlewares: MiddlewareFunc[]): Router;
994
- purge(name: string, path: string | RegExp | (string | RegExp)[], ...middlewares: MiddlewareFunc[]): Router;
995
- purge(nameOrPath: string | RegExp | (string | RegExp)[],
996
- pathOrMiddleware: string | RegExp | (string | RegExp)[] | MiddlewareFunc,
997
- ...middlewares: MiddlewareFunc[]): Router {
998
- return this.verb('purge', nameOrPath, pathOrMiddleware, ...middlewares);
999
- }
1000
-
1001
- put(path: string | RegExp | (string | RegExp)[], ...middlewares: MiddlewareFunc[]): Router;
1002
- put(name: string, path: string | RegExp | (string | RegExp)[], ...middlewares: MiddlewareFunc[]): Router;
1003
- put(nameOrPath: string | RegExp | (string | RegExp)[],
1004
- pathOrMiddleware: string | RegExp | (string | RegExp)[] | MiddlewareFunc,
1005
- ...middlewares: MiddlewareFunc[]): Router {
1006
- return this.verb('put', nameOrPath, pathOrMiddleware, ...middlewares);
1007
- }
1008
-
1009
- rebind(path: string | RegExp, ...middlewares: MiddlewareFunc[]): Router;
1010
- rebind(name: string, path: string | RegExp, ...middlewares: MiddlewareFunc[]): Router;
1011
- rebind(nameOrPath: string | RegExp, pathOrMiddleware: string | RegExp | MiddlewareFunc,
1012
- ...middlewares: MiddlewareFunc[]): Router {
1013
- return this.verb('rebind', nameOrPath, pathOrMiddleware, ...middlewares);
1014
- }
1015
-
1016
- report(path: string | RegExp | (string | RegExp)[], ...middlewares: MiddlewareFunc[]): Router;
1017
- report(name: string, path: string | RegExp | (string | RegExp)[], ...middlewares: MiddlewareFunc[]): Router;
1018
- report(nameOrPath: string | RegExp | (string | RegExp)[],
1019
- pathOrMiddleware: string | RegExp | (string | RegExp)[] | MiddlewareFunc,
1020
- ...middlewares: MiddlewareFunc[]): Router {
1021
- return this.verb('report', nameOrPath, pathOrMiddleware, ...middlewares);
1022
- }
1023
-
1024
- search(path: string | RegExp | (string | RegExp)[], ...middlewares: MiddlewareFunc[]): Router;
1025
- search(name: string, path: string | RegExp | (string | RegExp)[], ...middlewares: MiddlewareFunc[]): Router;
1026
- search(nameOrPath: string | RegExp | (string | RegExp)[],
1027
- pathOrMiddleware: string | RegExp | (string | RegExp)[] | MiddlewareFunc,
1028
- ...middlewares: MiddlewareFunc[]): Router {
1029
- return this.verb('search', nameOrPath, pathOrMiddleware, ...middlewares);
1030
- }
1031
-
1032
- source(path: string | RegExp | (string | RegExp)[], ...middlewares: MiddlewareFunc[]): Router;
1033
- source(name: string, path: string | RegExp | (string | RegExp)[], ...middlewares: MiddlewareFunc[]): Router;
1034
- source(nameOrPath: string | RegExp | (string | RegExp)[],
1035
- pathOrMiddleware: string | RegExp | (string | RegExp)[] | MiddlewareFunc,
1036
- ...middlewares: MiddlewareFunc[]): Router {
1037
- return this.verb('source', nameOrPath, pathOrMiddleware, ...middlewares);
1038
- }
1039
-
1040
- subscribe(path: string | RegExp | (string | RegExp)[], ...middlewares: MiddlewareFunc[]): Router;
1041
- subscribe(name: string, path: string | RegExp | (string | RegExp)[], ...middlewares: MiddlewareFunc[]): Router;
1042
- subscribe(nameOrPath: string | RegExp | (string | RegExp)[],
1043
- pathOrMiddleware: string | RegExp | (string | RegExp)[] | MiddlewareFunc,
1044
- ...middlewares: MiddlewareFunc[]): Router {
1045
- return this.verb('subscribe', nameOrPath, pathOrMiddleware, ...middlewares);
1046
- }
1047
-
1048
- trace(path: string | RegExp | (string | RegExp)[], ...middlewares: MiddlewareFunc[]): Router;
1049
- trace(name: string, path: string | RegExp | (string | RegExp)[], ...middlewares: MiddlewareFunc[]): Router;
1050
- trace(nameOrPath: string | RegExp | (string | RegExp)[],
1051
- pathOrMiddleware: string | RegExp | (string | RegExp)[] | MiddlewareFunc,
1052
- ...middlewares: MiddlewareFunc[]): Router {
1053
- return this.verb('trace', nameOrPath, pathOrMiddleware, ...middlewares);
1054
- }
1055
-
1056
- unbind(path: string | RegExp | (string | RegExp)[], ...middlewares: MiddlewareFunc[]): Router;
1057
- unbind(name: string, path: string | RegExp | (string | RegExp)[], ...middlewares: MiddlewareFunc[]): Router;
1058
- unbind(nameOrPath: string | RegExp | (string | RegExp)[],
1059
- pathOrMiddleware: string | RegExp | (string | RegExp)[] | MiddlewareFunc,
1060
- ...middlewares: MiddlewareFunc[]): Router {
1061
- return this.verb('unbind', nameOrPath, pathOrMiddleware, ...middlewares);
1062
- }
1063
-
1064
- unlink(path: string | RegExp | (string | RegExp)[], ...middlewares: MiddlewareFunc[]): Router;
1065
- unlink(name: string, path: string | RegExp | (string | RegExp)[], ...middlewares: MiddlewareFunc[]): Router;
1066
- unlink(nameOrPath: string | RegExp | (string | RegExp)[],
1067
- pathOrMiddleware: string | RegExp | (string | RegExp)[] | MiddlewareFunc,
1068
- ...middlewares: MiddlewareFunc[]): Router {
1069
- return this.verb('unlink', nameOrPath, pathOrMiddleware, ...middlewares);
1070
- }
1071
-
1072
- unlock(path: string | RegExp | (string | RegExp)[], ...middlewares: MiddlewareFunc[]): Router;
1073
- unlock(name: string, path: string | RegExp | (string | RegExp)[], ...middlewares: MiddlewareFunc[]): Router;
1074
- unlock(nameOrPath: string | RegExp | (string | RegExp)[],
1075
- pathOrMiddleware: string | RegExp | (string | RegExp)[] | MiddlewareFunc,
1076
- ...middlewares: MiddlewareFunc[]): Router {
1077
- return this.verb('unlock', nameOrPath, pathOrMiddleware, ...middlewares);
1078
- }
1079
-
1080
- unsubscribe(path: string | RegExp | (string | RegExp)[], ...middlewares: MiddlewareFunc[]): Router;
1081
- unsubscribe(name: string, path: string | RegExp | (string | RegExp)[], ...middlewares: MiddlewareFunc[]): Router;
1082
- unsubscribe(nameOrPath: string | RegExp | (string | RegExp)[],
1083
- pathOrMiddleware: string | RegExp | (string | RegExp)[] | MiddlewareFunc,
1084
- ...middlewares: MiddlewareFunc[]): Router {
1085
- return this.verb('unsubscribe', nameOrPath, pathOrMiddleware, ...middlewares);
1086
- }
1087
- }