@dcl/http-server 1.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 +3 -0
- package/dist/benchmark.d.ts +1 -0
- package/dist/benchmark.js +94 -0
- package/dist/benchmark.js.map +1 -0
- package/dist/cors.d.ts +35 -0
- package/dist/cors.js +138 -0
- package/dist/cors.js.map +1 -0
- package/dist/helpers.d.ts +1 -0
- package/dist/helpers.js +3 -0
- package/dist/helpers.js.map +1 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.js +25 -0
- package/dist/index.js.map +1 -0
- package/dist/injectors.d.ts +5 -0
- package/dist/injectors.js +22 -0
- package/dist/injectors.js.map +1 -0
- package/dist/layer.d.ts +58 -0
- package/dist/layer.js +102 -0
- package/dist/layer.js.map +1 -0
- package/dist/logic.d.ts +12 -0
- package/dist/logic.js +288 -0
- package/dist/logic.js.map +1 -0
- package/dist/methods.d.ts +6 -0
- package/dist/methods.js +16 -0
- package/dist/methods.js.map +1 -0
- package/dist/metrics.d.ts +36 -0
- package/dist/metrics.js +107 -0
- package/dist/metrics.js.map +1 -0
- package/dist/middleware.d.ts +9 -0
- package/dist/middleware.js +35 -0
- package/dist/middleware.js.map +1 -0
- package/dist/router.d.ts +190 -0
- package/dist/router.js +516 -0
- package/dist/router.js.map +1 -0
- package/dist/server-handler.d.ts +1 -0
- package/dist/server-handler.js +34 -0
- package/dist/server-handler.js.map +1 -0
- package/dist/server.d.ts +17 -0
- package/dist/server.js +176 -0
- package/dist/server.js.map +1 -0
- package/dist/status-checks.d.ts +33 -0
- package/dist/status-checks.js +154 -0
- package/dist/status-checks.js.map +1 -0
- package/dist/terminator.d.ts +18 -0
- package/dist/terminator.js +128 -0
- package/dist/terminator.js.map +1 -0
- package/dist/test-component.d.ts +22 -0
- package/dist/test-component.js +89 -0
- package/dist/test-component.js.map +1 -0
- package/dist/test-server.d.ts +21 -0
- package/dist/test-server.js +81 -0
- package/dist/test-server.js.map +1 -0
- package/dist/types.d.ts +32 -0
- package/dist/types.js +3 -0
- package/dist/types.js.map +1 -0
- package/dist/ws.d.ts +8 -0
- package/dist/ws.js +32 -0
- package/dist/ws.js.map +1 -0
- package/package.json +49 -0
package/dist/router.d.ts
ADDED
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
import { Layer, LayerOptions } from './layer';
|
|
2
|
+
import type { IHttpServerComponent } from '@well-known-components/interfaces';
|
|
3
|
+
/** @public */
|
|
4
|
+
export type RouterOptions = Partial<{
|
|
5
|
+
methods: IHttpServerComponent.HTTPMethod[];
|
|
6
|
+
prefix: string;
|
|
7
|
+
routerPath: string;
|
|
8
|
+
sensitive: boolean;
|
|
9
|
+
strict: boolean;
|
|
10
|
+
}>;
|
|
11
|
+
/** @public */
|
|
12
|
+
export type AllowedMethodOptions = Partial<{
|
|
13
|
+
throw: boolean;
|
|
14
|
+
notImplemented: NewableFunction;
|
|
15
|
+
methodNotAllowed: NewableFunction;
|
|
16
|
+
}>;
|
|
17
|
+
/** @public */
|
|
18
|
+
export type RoutedContext<Context, Path extends string> = IHttpServerComponent.PathAwareContext<Context, Path> & {
|
|
19
|
+
captures: string[];
|
|
20
|
+
matched?: Layer<Context, Path>[];
|
|
21
|
+
routerPath?: string;
|
|
22
|
+
};
|
|
23
|
+
/** @public */
|
|
24
|
+
export type RoutePathSignature<Context extends {}> = <T extends string>(path: T, ...middlewares: Array<IHttpServerComponent.IRequestHandler<RoutedContext<Context, T>>>) => Router<Context>;
|
|
25
|
+
/**
|
|
26
|
+
* Create a new router.
|
|
27
|
+
*
|
|
28
|
+
* @example
|
|
29
|
+
*
|
|
30
|
+
* Basic usage:
|
|
31
|
+
*
|
|
32
|
+
* ```javascript
|
|
33
|
+
* const app = createTestServerComponent();
|
|
34
|
+
* const router = new Router();
|
|
35
|
+
*
|
|
36
|
+
* router.get('/', (ctx, next) => {
|
|
37
|
+
* // ctx.router available
|
|
38
|
+
* });
|
|
39
|
+
*
|
|
40
|
+
* app
|
|
41
|
+
* .use(router.routes())
|
|
42
|
+
* .use(router.allowedMethods());
|
|
43
|
+
* ```
|
|
44
|
+
* @public
|
|
45
|
+
*/
|
|
46
|
+
export declare class Router<Context extends {}> implements IHttpServerComponent.MethodHandlers<Context> {
|
|
47
|
+
opts: RouterOptions;
|
|
48
|
+
methods: (IHttpServerComponent.HTTPMethod | string)[];
|
|
49
|
+
stack: Layer<Context, any>[];
|
|
50
|
+
constructor(opts?: RouterOptions);
|
|
51
|
+
connect: RoutePathSignature<Context>;
|
|
52
|
+
delete: RoutePathSignature<Context>;
|
|
53
|
+
get: RoutePathSignature<Context>;
|
|
54
|
+
head: RoutePathSignature<Context>;
|
|
55
|
+
options: RoutePathSignature<Context>;
|
|
56
|
+
patch: RoutePathSignature<Context>;
|
|
57
|
+
post: RoutePathSignature<Context>;
|
|
58
|
+
put: RoutePathSignature<Context>;
|
|
59
|
+
trace: RoutePathSignature<Context>;
|
|
60
|
+
/**
|
|
61
|
+
* Use given middleware.
|
|
62
|
+
*
|
|
63
|
+
* Middleware run in the order they are defined by `.use()`. They are invoked
|
|
64
|
+
* sequentially, requests start at the first middleware and work their way
|
|
65
|
+
* "down" the middleware stack.
|
|
66
|
+
*
|
|
67
|
+
* @example
|
|
68
|
+
*
|
|
69
|
+
* ```javascript
|
|
70
|
+
* // session middleware will run before authorize
|
|
71
|
+
* router
|
|
72
|
+
* .use(session())
|
|
73
|
+
* .use(authorize());
|
|
74
|
+
*
|
|
75
|
+
* // use middleware only with given path
|
|
76
|
+
* router.use('/users', userAuth());
|
|
77
|
+
*
|
|
78
|
+
* // or with an array of paths
|
|
79
|
+
* router.use(['/users', '/admin'], userAuth());
|
|
80
|
+
*
|
|
81
|
+
* app.use(router.routes());
|
|
82
|
+
* ```
|
|
83
|
+
*
|
|
84
|
+
* @param path -
|
|
85
|
+
* @param middleware -
|
|
86
|
+
*/
|
|
87
|
+
use(...middlewares: IHttpServerComponent.IRequestHandler<RoutedContext<Context, string>>[]): this;
|
|
88
|
+
use<P extends string>(route: P, ...middlewares: IHttpServerComponent.IRequestHandler<RoutedContext<Context, P>>[]): this;
|
|
89
|
+
/**
|
|
90
|
+
* Set the path prefix for a Router instance that was already initialized.
|
|
91
|
+
*
|
|
92
|
+
* @example
|
|
93
|
+
*
|
|
94
|
+
* ```javascript
|
|
95
|
+
* router.prefix('/things/:thing_id')
|
|
96
|
+
* ```
|
|
97
|
+
*
|
|
98
|
+
* @param prefix -
|
|
99
|
+
*/
|
|
100
|
+
prefix(prefix: string): this;
|
|
101
|
+
/**
|
|
102
|
+
* Returns router middleware which dispatches a route matching the request.
|
|
103
|
+
*/
|
|
104
|
+
middleware(): IHttpServerComponent.IRequestHandler<Context>;
|
|
105
|
+
/**
|
|
106
|
+
* Returns separate middleware for responding to `OPTIONS` requests with
|
|
107
|
+
* an `Allow` header containing the allowed methods, as well as responding
|
|
108
|
+
* with `405 Method Not Allowed` and `501 Not Implemented` as appropriate.
|
|
109
|
+
*
|
|
110
|
+
* @example
|
|
111
|
+
*
|
|
112
|
+
* ```javascript
|
|
113
|
+
* const app = createTestServerComponent();
|
|
114
|
+
* const router = new Router();
|
|
115
|
+
*
|
|
116
|
+
* app.use(router.routes());
|
|
117
|
+
* app.use(router.allowedMethods());
|
|
118
|
+
* ```
|
|
119
|
+
*
|
|
120
|
+
* **Example with [Boom](https://github.com/hapijs/boom)**
|
|
121
|
+
*
|
|
122
|
+
* ```javascript
|
|
123
|
+
* const Boom = require('boom');
|
|
124
|
+
*
|
|
125
|
+
* const app = createTestServerComponent();
|
|
126
|
+
* const router = new Router();
|
|
127
|
+
*
|
|
128
|
+
* app.use(router.routes());
|
|
129
|
+
* app.use(router.allowedMethods({
|
|
130
|
+
* throw: true,
|
|
131
|
+
* notImplemented: () => new Boom.notImplemented(),
|
|
132
|
+
* methodNotAllowed: () => new Boom.methodNotAllowed()
|
|
133
|
+
* }));
|
|
134
|
+
* ```
|
|
135
|
+
*
|
|
136
|
+
* @param options -
|
|
137
|
+
*/
|
|
138
|
+
allowedMethods(options?: AllowedMethodOptions): IHttpServerComponent.IRequestHandler<Context>;
|
|
139
|
+
/**
|
|
140
|
+
* Register route with all methods.
|
|
141
|
+
*
|
|
142
|
+
* @param name - Optional.
|
|
143
|
+
* @param path -
|
|
144
|
+
* @param middleware - You may also pass multiple middleware.
|
|
145
|
+
* @param callback -
|
|
146
|
+
*/
|
|
147
|
+
all<T extends string>(path: T, middleware: IHttpServerComponent.IRequestHandler<RoutedContext<Context, T>>): this;
|
|
148
|
+
/**
|
|
149
|
+
* Redirect `source` to `destination` URL with optional 30x status `code`.
|
|
150
|
+
*
|
|
151
|
+
* Both `source` and `destination` can be route names.
|
|
152
|
+
*
|
|
153
|
+
* ```javascript
|
|
154
|
+
* router.redirect('/login', 'sign-in');
|
|
155
|
+
* ```
|
|
156
|
+
*
|
|
157
|
+
* This is equivalent to:
|
|
158
|
+
*
|
|
159
|
+
* ```javascript
|
|
160
|
+
* router.all('/login', ctx => {
|
|
161
|
+
* ctx.redirect('/sign-in');
|
|
162
|
+
* ctx.status = 301;
|
|
163
|
+
* });
|
|
164
|
+
* ```
|
|
165
|
+
*
|
|
166
|
+
* @param source - URL or route name.
|
|
167
|
+
* @param destination - URL or route name.
|
|
168
|
+
* @param code - HTTP status code (default: 301).
|
|
169
|
+
*/
|
|
170
|
+
redirect(source: string, destination: string, code?: number): this;
|
|
171
|
+
/**
|
|
172
|
+
* Create and register a route.
|
|
173
|
+
*
|
|
174
|
+
* @param path - Path string.
|
|
175
|
+
* @param methods - Array of HTTP verbs.
|
|
176
|
+
* @param middleware - Multiple middleware also accepted.
|
|
177
|
+
*/
|
|
178
|
+
register<Path extends string>(path: Path, methods: ReadonlyArray<IHttpServerComponent.HTTPMethod>, middleware: IHttpServerComponent.IRequestHandler<Context>, opts?: LayerOptions): Layer<Context, Path>;
|
|
179
|
+
/**
|
|
180
|
+
* Match given `path` and return corresponding routes.
|
|
181
|
+
*
|
|
182
|
+
* @param path -
|
|
183
|
+
* @param method -
|
|
184
|
+
*/
|
|
185
|
+
match(path: string, method: string): {
|
|
186
|
+
path: Layer<Context, string>[];
|
|
187
|
+
pathAndMethod: Layer<Context, string>[];
|
|
188
|
+
route: boolean;
|
|
189
|
+
};
|
|
190
|
+
}
|
package/dist/router.js
ADDED
|
@@ -0,0 +1,516 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.Router = void 0;
|
|
7
|
+
const http_errors_1 = __importDefault(require("http-errors"));
|
|
8
|
+
const layer_1 = require("./layer");
|
|
9
|
+
const path_to_regexp_1 = require("path-to-regexp");
|
|
10
|
+
const middleware_1 = require("./middleware");
|
|
11
|
+
const methods_1 = require("./methods");
|
|
12
|
+
const injectedMiddlewareRouterSymbol = Symbol('injected-router');
|
|
13
|
+
/** @internal */
|
|
14
|
+
function getInjectedRouter(middleware) {
|
|
15
|
+
return middleware[injectedMiddlewareRouterSymbol] || null;
|
|
16
|
+
}
|
|
17
|
+
/** @internal */
|
|
18
|
+
function setInjectedRouter(middleware, router) {
|
|
19
|
+
;
|
|
20
|
+
middleware[injectedMiddlewareRouterSymbol] = router;
|
|
21
|
+
}
|
|
22
|
+
function createMethodHandler(router, method) {
|
|
23
|
+
return function (path, ...middlewares) {
|
|
24
|
+
router.register(path, [method], (0, middleware_1.compose)(...middlewares), {});
|
|
25
|
+
return router;
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Create a new router.
|
|
30
|
+
*
|
|
31
|
+
* @example
|
|
32
|
+
*
|
|
33
|
+
* Basic usage:
|
|
34
|
+
*
|
|
35
|
+
* ```javascript
|
|
36
|
+
* const app = createTestServerComponent();
|
|
37
|
+
* const router = new Router();
|
|
38
|
+
*
|
|
39
|
+
* router.get('/', (ctx, next) => {
|
|
40
|
+
* // ctx.router available
|
|
41
|
+
* });
|
|
42
|
+
*
|
|
43
|
+
* app
|
|
44
|
+
* .use(router.routes())
|
|
45
|
+
* .use(router.allowedMethods());
|
|
46
|
+
* ```
|
|
47
|
+
* @public
|
|
48
|
+
*/
|
|
49
|
+
class Router {
|
|
50
|
+
constructor(opts) {
|
|
51
|
+
this.stack = [];
|
|
52
|
+
this.connect = createMethodHandler(this, 'CONNECT');
|
|
53
|
+
this.delete = createMethodHandler(this, 'DELETE');
|
|
54
|
+
this.get = createMethodHandler(this, 'GET');
|
|
55
|
+
this.head = createMethodHandler(this, 'HEAD');
|
|
56
|
+
this.options = createMethodHandler(this, 'OPTIONS');
|
|
57
|
+
this.patch = createMethodHandler(this, 'PATCH');
|
|
58
|
+
this.post = createMethodHandler(this, 'POST');
|
|
59
|
+
this.put = createMethodHandler(this, 'PUT');
|
|
60
|
+
this.trace = createMethodHandler(this, 'TRACE');
|
|
61
|
+
this.opts = opts || {};
|
|
62
|
+
this.methods = this.opts?.methods?.map(($) => $.toUpperCase()) || [
|
|
63
|
+
'HEAD',
|
|
64
|
+
'OPTIONS',
|
|
65
|
+
'GET',
|
|
66
|
+
'PUT',
|
|
67
|
+
'PATCH',
|
|
68
|
+
'POST',
|
|
69
|
+
'DELETE'
|
|
70
|
+
];
|
|
71
|
+
}
|
|
72
|
+
use() {
|
|
73
|
+
const middleware = Array.prototype.slice.call(arguments);
|
|
74
|
+
let path;
|
|
75
|
+
let router = this;
|
|
76
|
+
const hasPath = typeof middleware[0] === 'string';
|
|
77
|
+
if (hasPath)
|
|
78
|
+
path = middleware.shift();
|
|
79
|
+
for (let i = 0; i < middleware.length; i++) {
|
|
80
|
+
const m = middleware[i];
|
|
81
|
+
const injectedRouter = getInjectedRouter(m);
|
|
82
|
+
if (injectedRouter) {
|
|
83
|
+
const cloneRouter = Object.assign(Object.create(Router.prototype), injectedRouter, {
|
|
84
|
+
stack: injectedRouter.stack.slice(0)
|
|
85
|
+
});
|
|
86
|
+
for (let j = 0; j < cloneRouter.stack.length; j++) {
|
|
87
|
+
const nestedLayer = cloneRouter.stack[j];
|
|
88
|
+
const cloneLayer = Object.assign(Object.create(layer_1.Layer.prototype), nestedLayer);
|
|
89
|
+
if (path)
|
|
90
|
+
cloneLayer.setPrefix(path);
|
|
91
|
+
if (router.opts.prefix)
|
|
92
|
+
cloneLayer.setPrefix(router.opts.prefix);
|
|
93
|
+
router.stack.push(cloneLayer);
|
|
94
|
+
cloneRouter.stack[j] = cloneLayer;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
else {
|
|
98
|
+
const keys = [];
|
|
99
|
+
(0, path_to_regexp_1.pathToRegexp)(router.opts.prefix || '', keys);
|
|
100
|
+
const routerPrefixHasParam = router.opts.prefix && keys.length;
|
|
101
|
+
router.register(path || '([^/]*)', [], m, { end: false, ignoreCaptures: !hasPath && !routerPrefixHasParam });
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
return this;
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Set the path prefix for a Router instance that was already initialized.
|
|
108
|
+
*
|
|
109
|
+
* @example
|
|
110
|
+
*
|
|
111
|
+
* ```javascript
|
|
112
|
+
* router.prefix('/things/:thing_id')
|
|
113
|
+
* ```
|
|
114
|
+
*
|
|
115
|
+
* @param prefix -
|
|
116
|
+
*/
|
|
117
|
+
prefix(prefix) {
|
|
118
|
+
prefix = prefix.replace(/\/$/, '');
|
|
119
|
+
this.opts.prefix = prefix;
|
|
120
|
+
for (let i = 0; i < this.stack.length; i++) {
|
|
121
|
+
const route = this.stack[i];
|
|
122
|
+
route.setPrefix(prefix);
|
|
123
|
+
}
|
|
124
|
+
return this;
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Returns router middleware which dispatches a route matching the request.
|
|
128
|
+
*/
|
|
129
|
+
middleware() {
|
|
130
|
+
const router = this;
|
|
131
|
+
const routerMiddleware = function routerMiddleware(ctx, next) {
|
|
132
|
+
const path = router.opts.routerPath || ctx.routerPath || ctx.url.pathname;
|
|
133
|
+
const matched = router.match(path, ctx.request.method);
|
|
134
|
+
let layerChain;
|
|
135
|
+
if (ctx.matched) {
|
|
136
|
+
ctx.matched.push.apply(ctx.matched, matched.path);
|
|
137
|
+
}
|
|
138
|
+
else {
|
|
139
|
+
ctx.matched = matched.path;
|
|
140
|
+
}
|
|
141
|
+
ctx.router = router;
|
|
142
|
+
if (!matched.route)
|
|
143
|
+
return next();
|
|
144
|
+
const matchedLayers = matched.pathAndMethod;
|
|
145
|
+
const mostSpecificLayer = matchedLayers[matchedLayers.length - 1];
|
|
146
|
+
ctx._matchedRoute = mostSpecificLayer.path;
|
|
147
|
+
if (mostSpecificLayer.name) {
|
|
148
|
+
ctx._matchedRouteName = mostSpecificLayer.name;
|
|
149
|
+
}
|
|
150
|
+
layerChain = matchedLayers.reduce(function (memo, layer) {
|
|
151
|
+
memo.push(async function (ctx, next) {
|
|
152
|
+
ctx.captures = layer.captures(path);
|
|
153
|
+
ctx.params = ctx.params = layer.params(ctx.captures, ctx.params);
|
|
154
|
+
ctx.routerPath = layer.path;
|
|
155
|
+
// ctx.routerName = layer.name || undefined
|
|
156
|
+
ctx._matchedRoute = layer.path;
|
|
157
|
+
if (layer.name) {
|
|
158
|
+
ctx._matchedRouteName = layer.name;
|
|
159
|
+
}
|
|
160
|
+
return await next();
|
|
161
|
+
});
|
|
162
|
+
return memo.concat(layer.stack);
|
|
163
|
+
}, []);
|
|
164
|
+
return (0, middleware_1.compose)(...layerChain)(ctx, next);
|
|
165
|
+
};
|
|
166
|
+
setInjectedRouter(routerMiddleware, this);
|
|
167
|
+
return routerMiddleware;
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* Returns separate middleware for responding to `OPTIONS` requests with
|
|
171
|
+
* an `Allow` header containing the allowed methods, as well as responding
|
|
172
|
+
* with `405 Method Not Allowed` and `501 Not Implemented` as appropriate.
|
|
173
|
+
*
|
|
174
|
+
* @example
|
|
175
|
+
*
|
|
176
|
+
* ```javascript
|
|
177
|
+
* const app = createTestServerComponent();
|
|
178
|
+
* const router = new Router();
|
|
179
|
+
*
|
|
180
|
+
* app.use(router.routes());
|
|
181
|
+
* app.use(router.allowedMethods());
|
|
182
|
+
* ```
|
|
183
|
+
*
|
|
184
|
+
* **Example with [Boom](https://github.com/hapijs/boom)**
|
|
185
|
+
*
|
|
186
|
+
* ```javascript
|
|
187
|
+
* const Boom = require('boom');
|
|
188
|
+
*
|
|
189
|
+
* const app = createTestServerComponent();
|
|
190
|
+
* const router = new Router();
|
|
191
|
+
*
|
|
192
|
+
* app.use(router.routes());
|
|
193
|
+
* app.use(router.allowedMethods({
|
|
194
|
+
* throw: true,
|
|
195
|
+
* notImplemented: () => new Boom.notImplemented(),
|
|
196
|
+
* methodNotAllowed: () => new Boom.methodNotAllowed()
|
|
197
|
+
* }));
|
|
198
|
+
* ```
|
|
199
|
+
*
|
|
200
|
+
* @param options -
|
|
201
|
+
*/
|
|
202
|
+
allowedMethods(options = {}) {
|
|
203
|
+
options = options || {};
|
|
204
|
+
const implemented = this.methods;
|
|
205
|
+
const routerMiddleware = async function routerMiddleware(ctx, next) {
|
|
206
|
+
const response = await next();
|
|
207
|
+
const allowed = {};
|
|
208
|
+
if (!response.status || response.status === 404) {
|
|
209
|
+
if ('matched' in ctx && ctx.matched) {
|
|
210
|
+
for (let i = 0; i < ctx.matched.length; i++) {
|
|
211
|
+
const route = ctx.matched[i];
|
|
212
|
+
for (let j = 0; j < route.methods.length; j++) {
|
|
213
|
+
const method = route.methods[j];
|
|
214
|
+
allowed[method] = method;
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
const allowedArr = Object.keys(allowed);
|
|
219
|
+
const currentMethod = ctx.request.method.toUpperCase();
|
|
220
|
+
if (!~implemented.indexOf(currentMethod)) {
|
|
221
|
+
if (options.throw) {
|
|
222
|
+
let notImplementedThrowable = typeof options.notImplemented === 'function'
|
|
223
|
+
? options.notImplemented() // set whatever the user returns from their function
|
|
224
|
+
: new http_errors_1.default.NotImplemented();
|
|
225
|
+
throw notImplementedThrowable;
|
|
226
|
+
}
|
|
227
|
+
else {
|
|
228
|
+
return {
|
|
229
|
+
status: 501,
|
|
230
|
+
headers: { Allow: allowedArr.join(', ') }
|
|
231
|
+
};
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
else if (allowedArr.length) {
|
|
235
|
+
if (currentMethod === 'OPTIONS') {
|
|
236
|
+
return {
|
|
237
|
+
status: 200,
|
|
238
|
+
headers: { Allow: allowedArr.join(', ') }
|
|
239
|
+
};
|
|
240
|
+
}
|
|
241
|
+
else if (!allowed[currentMethod]) {
|
|
242
|
+
if (options.throw) {
|
|
243
|
+
let notAllowedThrowable = typeof options.methodNotAllowed === 'function'
|
|
244
|
+
? options.methodNotAllowed() // set whatever the user returns from their function
|
|
245
|
+
: new http_errors_1.default.MethodNotAllowed();
|
|
246
|
+
throw notAllowedThrowable;
|
|
247
|
+
}
|
|
248
|
+
else {
|
|
249
|
+
return {
|
|
250
|
+
status: 405,
|
|
251
|
+
headers: { Allow: allowedArr.join(', ') }
|
|
252
|
+
};
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
return response;
|
|
258
|
+
};
|
|
259
|
+
return routerMiddleware;
|
|
260
|
+
}
|
|
261
|
+
/**
|
|
262
|
+
* Register route with all methods.
|
|
263
|
+
*
|
|
264
|
+
* @param name - Optional.
|
|
265
|
+
* @param path -
|
|
266
|
+
* @param middleware - You may also pass multiple middleware.
|
|
267
|
+
* @param callback -
|
|
268
|
+
*/
|
|
269
|
+
all(path, middleware) {
|
|
270
|
+
this.register(path, methods_1.methodsList, middleware, {});
|
|
271
|
+
return this;
|
|
272
|
+
}
|
|
273
|
+
/**
|
|
274
|
+
* Redirect `source` to `destination` URL with optional 30x status `code`.
|
|
275
|
+
*
|
|
276
|
+
* Both `source` and `destination` can be route names.
|
|
277
|
+
*
|
|
278
|
+
* ```javascript
|
|
279
|
+
* router.redirect('/login', 'sign-in');
|
|
280
|
+
* ```
|
|
281
|
+
*
|
|
282
|
+
* This is equivalent to:
|
|
283
|
+
*
|
|
284
|
+
* ```javascript
|
|
285
|
+
* router.all('/login', ctx => {
|
|
286
|
+
* ctx.redirect('/sign-in');
|
|
287
|
+
* ctx.status = 301;
|
|
288
|
+
* });
|
|
289
|
+
* ```
|
|
290
|
+
*
|
|
291
|
+
* @param source - URL or route name.
|
|
292
|
+
* @param destination - URL or route name.
|
|
293
|
+
* @param code - HTTP status code (default: 301).
|
|
294
|
+
*/
|
|
295
|
+
redirect(source, destination, code = 301) {
|
|
296
|
+
// lookup source route by name
|
|
297
|
+
if (source[0] !== '/')
|
|
298
|
+
throw new Error(`Relative URL must start with / got ${JSON.stringify(source)} instead`);
|
|
299
|
+
// lookup destination route by name
|
|
300
|
+
if (destination[0] !== '/' && !destination.includes('://'))
|
|
301
|
+
throw new Error(`Can't resolve target URL, it is neither a relative or absolute URL. Got ${JSON.stringify(source)}`);
|
|
302
|
+
return this.all(source, async (ctx) => {
|
|
303
|
+
return { status: code, headers: { Location: destination } };
|
|
304
|
+
});
|
|
305
|
+
}
|
|
306
|
+
/**
|
|
307
|
+
* Create and register a route.
|
|
308
|
+
*
|
|
309
|
+
* @param path - Path string.
|
|
310
|
+
* @param methods - Array of HTTP verbs.
|
|
311
|
+
* @param middleware - Multiple middleware also accepted.
|
|
312
|
+
*/
|
|
313
|
+
register(path, methods, middleware, opts) {
|
|
314
|
+
opts = opts || {};
|
|
315
|
+
const router = this;
|
|
316
|
+
const stack = this.stack;
|
|
317
|
+
// support array of paths
|
|
318
|
+
if (Array.isArray(path)) {
|
|
319
|
+
for (let i = 0; i < path.length; i++) {
|
|
320
|
+
const curPath = path[i];
|
|
321
|
+
router.register.call(router, curPath, methods, middleware, opts);
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
// create route
|
|
325
|
+
const route = new layer_1.Layer(path, methods, middleware, {
|
|
326
|
+
end: opts.end === false ? opts.end : true,
|
|
327
|
+
name: opts.name,
|
|
328
|
+
sensitive: opts.sensitive || this.opts.sensitive || false,
|
|
329
|
+
strict: opts.strict || this.opts.strict || false,
|
|
330
|
+
prefix: opts.prefix || this.opts.prefix || '',
|
|
331
|
+
ignoreCaptures: opts.ignoreCaptures
|
|
332
|
+
});
|
|
333
|
+
if (this.opts.prefix) {
|
|
334
|
+
route.setPrefix(this.opts.prefix);
|
|
335
|
+
}
|
|
336
|
+
stack.push(route);
|
|
337
|
+
// debug("defined route %s %s", route.methods, route.path)
|
|
338
|
+
return route;
|
|
339
|
+
}
|
|
340
|
+
/**
|
|
341
|
+
* Match given `path` and return corresponding routes.
|
|
342
|
+
*
|
|
343
|
+
* @param path -
|
|
344
|
+
* @param method -
|
|
345
|
+
*/
|
|
346
|
+
match(path, method) {
|
|
347
|
+
const layers = this.stack;
|
|
348
|
+
let layer;
|
|
349
|
+
const matched = {
|
|
350
|
+
path: [],
|
|
351
|
+
pathAndMethod: [],
|
|
352
|
+
route: false
|
|
353
|
+
};
|
|
354
|
+
for (let len = layers.length, i = 0; i < len; i++) {
|
|
355
|
+
layer = layers[i];
|
|
356
|
+
// debug("test %s %s", layer.path, layer.regexp)
|
|
357
|
+
if (layer.match(path)) {
|
|
358
|
+
matched.path.push(layer);
|
|
359
|
+
if (layer.methods.length === 0 || ~layer.methods.indexOf(method)) {
|
|
360
|
+
matched.pathAndMethod.push(layer);
|
|
361
|
+
if (layer.methods.length)
|
|
362
|
+
matched.route = true;
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
return matched;
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
exports.Router = Router;
|
|
370
|
+
// /**
|
|
371
|
+
// * Generate URL from url pattern and given `params`.
|
|
372
|
+
// *
|
|
373
|
+
// * @example
|
|
374
|
+
// *
|
|
375
|
+
// * ```javascript
|
|
376
|
+
// * const url = Router.url('/users/:id', {id: 1});
|
|
377
|
+
// * // => "/users/1"
|
|
378
|
+
// * ```
|
|
379
|
+
// *
|
|
380
|
+
// * @param path - url pattern
|
|
381
|
+
// * @param params - url parameters
|
|
382
|
+
// */
|
|
383
|
+
// export function processUrl(path: string, ...rest: any[]): string {
|
|
384
|
+
// return Layer.prototype.url.apply({ path }, rest)
|
|
385
|
+
// }
|
|
386
|
+
// /**
|
|
387
|
+
// * Create `router.verb()` methods, where *verb* is one of the HTTP verbs such
|
|
388
|
+
// * as `router.get()` or `router.post()`.
|
|
389
|
+
// *
|
|
390
|
+
// * Match URL patterns to callback functions or controller actions using `router.verb()`,
|
|
391
|
+
// * where **verb** is one of the HTTP verbs such as `router.get()` or `router.post()`.
|
|
392
|
+
// *
|
|
393
|
+
// * Additionaly, `router.all()` can be used to match against all methods.
|
|
394
|
+
// *
|
|
395
|
+
// * ```javascript
|
|
396
|
+
// * router
|
|
397
|
+
// * .get('/', (ctx, next) => {
|
|
398
|
+
// * return ctx.body = 'Hello World!';
|
|
399
|
+
// * })
|
|
400
|
+
// * .post('/users', (ctx, next) => {
|
|
401
|
+
// * // ...
|
|
402
|
+
// * })
|
|
403
|
+
// * .put('/users/:id', (ctx, next) => {
|
|
404
|
+
// * // ...
|
|
405
|
+
// * })
|
|
406
|
+
// * .del('/users/:id', (ctx, next) => {
|
|
407
|
+
// * // ...
|
|
408
|
+
// * })
|
|
409
|
+
// * .all('/users/:id', (ctx, next) => {
|
|
410
|
+
// * // ...
|
|
411
|
+
// * });
|
|
412
|
+
// * ```
|
|
413
|
+
// *
|
|
414
|
+
// * When a route is matched, its path is available at `ctx._matchedRoute` and if named,
|
|
415
|
+
// * the name is available at `ctx._matchedRouteName`
|
|
416
|
+
// *
|
|
417
|
+
// * Route paths will be translated to regular expressions using
|
|
418
|
+
// * [path-to-regexp](https://github.com/pillarjs/path-to-regexp).
|
|
419
|
+
// *
|
|
420
|
+
// * Query strings will not be considered when matching requests.
|
|
421
|
+
// *
|
|
422
|
+
// * #### Named routes
|
|
423
|
+
// *
|
|
424
|
+
// * Routes can optionally have names. This allows generation of URLs and easy
|
|
425
|
+
// * renaming of URLs during development.
|
|
426
|
+
// *
|
|
427
|
+
// * ```javascript
|
|
428
|
+
// * router.get('user', '/users/:id', (ctx, next) => {
|
|
429
|
+
// * // ...
|
|
430
|
+
// * });
|
|
431
|
+
// *
|
|
432
|
+
// * router.url('user', 3);
|
|
433
|
+
// * // => "/users/3"
|
|
434
|
+
// * ```
|
|
435
|
+
// *
|
|
436
|
+
// * #### Multiple middleware
|
|
437
|
+
// *
|
|
438
|
+
// * Multiple middleware may be given:
|
|
439
|
+
// *
|
|
440
|
+
// * ```javascript
|
|
441
|
+
// * router.get(
|
|
442
|
+
// * '/users/:id',
|
|
443
|
+
// * (ctx, next) => {
|
|
444
|
+
// * return User.findOne(ctx.params.id).then(function(user) {
|
|
445
|
+
// * ctx.user = user;
|
|
446
|
+
// * next();
|
|
447
|
+
// * });
|
|
448
|
+
// * },
|
|
449
|
+
// * ctx => {
|
|
450
|
+
// * console.log(ctx.user);
|
|
451
|
+
// * // => { id: 17, name: "Alex" }
|
|
452
|
+
// * }
|
|
453
|
+
// * );
|
|
454
|
+
// * ```
|
|
455
|
+
// *
|
|
456
|
+
// * ### Nested routers
|
|
457
|
+
// *
|
|
458
|
+
// * Nesting routers is supported:
|
|
459
|
+
// *
|
|
460
|
+
// * ```javascript
|
|
461
|
+
// * const forums = new Router();
|
|
462
|
+
// * const posts = new Router();
|
|
463
|
+
// *
|
|
464
|
+
// * posts.get('/', (ctx, next) => {...});
|
|
465
|
+
// * posts.get('/:pid', (ctx, next) => {...});
|
|
466
|
+
// * forums.use('/forums/:fid/posts', posts.routes(), posts.allowedMethods());
|
|
467
|
+
// *
|
|
468
|
+
// * // responds to "/forums/123/posts" and "/forums/123/posts/123"
|
|
469
|
+
// * app.use(forums.routes());
|
|
470
|
+
// * ```
|
|
471
|
+
// *
|
|
472
|
+
// * #### Router prefixes
|
|
473
|
+
// *
|
|
474
|
+
// * Route paths can be prefixed at the router level:
|
|
475
|
+
// *
|
|
476
|
+
// * ```javascript
|
|
477
|
+
// * const router = new Router({
|
|
478
|
+
// * prefix: '/users'
|
|
479
|
+
// * });
|
|
480
|
+
// *
|
|
481
|
+
// * router.get('/', ...); // responds to "/users"
|
|
482
|
+
// * router.get('/:id', ...); // responds to "/users/:id"
|
|
483
|
+
// * ```
|
|
484
|
+
// *
|
|
485
|
+
// * #### URL parameters
|
|
486
|
+
// *
|
|
487
|
+
// * Named route parameters are captured and added to `ctx.params`.
|
|
488
|
+
// *
|
|
489
|
+
// * ```javascript
|
|
490
|
+
// * router.get('/:category/:title', (ctx, next) => {
|
|
491
|
+
// * console.log(ctx.params);
|
|
492
|
+
// * // => { category: 'programming', title: 'how-to-node' }
|
|
493
|
+
// * });
|
|
494
|
+
// * ```
|
|
495
|
+
// *
|
|
496
|
+
// * The [path-to-regexp](https://github.com/pillarjs/path-to-regexp) module is
|
|
497
|
+
// * used to convert paths to regular expressions.
|
|
498
|
+
// *
|
|
499
|
+
// * @name get|put|post|patch|delete|del
|
|
500
|
+
// * @memberof module:koa-router.prototype
|
|
501
|
+
// * @param path -
|
|
502
|
+
// * @param middleware - route middleware(s)
|
|
503
|
+
// * @param callback - route callback
|
|
504
|
+
// */
|
|
505
|
+
// for (let i = 0; i < methods.length; i++) {
|
|
506
|
+
// function setMethodVerb(method) {
|
|
507
|
+
// Router.prototype[method] = function (path, middleware: Middleware<any>) {
|
|
508
|
+
// this.register(path, [method], middleware, {})
|
|
509
|
+
// return this
|
|
510
|
+
// }
|
|
511
|
+
// }
|
|
512
|
+
// setMethodVerb(methods[i])
|
|
513
|
+
// }
|
|
514
|
+
// // Alias for `router.delete()` because delete is a reserved word
|
|
515
|
+
// Router.prototype.del = Router.prototype["delete"]
|
|
516
|
+
//# sourceMappingURL=router.js.map
|