@depup/hapi 18.1.0-depup.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/.npmignore +4 -0
- package/LICENSE +26 -0
- package/README.md +47 -0
- package/lib/auth.js +545 -0
- package/lib/compression.js +107 -0
- package/lib/config.js +436 -0
- package/lib/core.js +680 -0
- package/lib/cors.js +207 -0
- package/lib/ext.js +94 -0
- package/lib/handler.js +165 -0
- package/lib/headers.js +200 -0
- package/lib/index.js +11 -0
- package/lib/methods.js +123 -0
- package/lib/request.js +623 -0
- package/lib/response.js +730 -0
- package/lib/route.js +519 -0
- package/lib/security.js +84 -0
- package/lib/server.js +557 -0
- package/lib/streams.js +37 -0
- package/lib/toolkit.js +201 -0
- package/lib/transmit.js +369 -0
- package/lib/validation.js +198 -0
- package/npm-shrinkwrap.json +2456 -0
- package/package.json +132 -0
package/lib/server.js
ADDED
|
@@ -0,0 +1,557 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const Hoek = require('hoek');
|
|
4
|
+
const Joi = require('joi');
|
|
5
|
+
const Shot = require('shot');
|
|
6
|
+
const Somever = require('somever');
|
|
7
|
+
|
|
8
|
+
const Config = require('./config');
|
|
9
|
+
const Core = require('./core');
|
|
10
|
+
const Cors = require('./cors');
|
|
11
|
+
const Ext = require('./ext');
|
|
12
|
+
const Package = require('../package.json');
|
|
13
|
+
const Request = require('./request');
|
|
14
|
+
const Route = require('./route');
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
const internals = {};
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
exports = module.exports = function (options) {
|
|
21
|
+
|
|
22
|
+
const core = new Core(options);
|
|
23
|
+
return new internals.Server(core);
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
internals.Server = class {
|
|
28
|
+
|
|
29
|
+
constructor(core, name, parent) {
|
|
30
|
+
|
|
31
|
+
this._core = core;
|
|
32
|
+
|
|
33
|
+
// Public interface
|
|
34
|
+
|
|
35
|
+
this.app = core.app;
|
|
36
|
+
this.auth = Object.create(this._core.auth);
|
|
37
|
+
this.auth.strategy = this.auth._strategy.bind(this.auth, this);
|
|
38
|
+
this.decorations = core.decorations;
|
|
39
|
+
this.cache = internals.cache(this);
|
|
40
|
+
this.events = core.events;
|
|
41
|
+
this.info = core.info;
|
|
42
|
+
this.listener = core.listener;
|
|
43
|
+
this.load = core.heavy.load;
|
|
44
|
+
this.methods = core.methods.methods;
|
|
45
|
+
this.mime = core.mime;
|
|
46
|
+
this.plugins = core.plugins;
|
|
47
|
+
this.registrations = core.registrations;
|
|
48
|
+
this.settings = core.settings;
|
|
49
|
+
this.states = core.states;
|
|
50
|
+
this.type = core.type;
|
|
51
|
+
this.version = Package.version;
|
|
52
|
+
|
|
53
|
+
this.realm = {
|
|
54
|
+
_extensions: {
|
|
55
|
+
onPreAuth: new Ext('onPreAuth', core),
|
|
56
|
+
onCredentials: new Ext('onCredentials', core),
|
|
57
|
+
onPostAuth: new Ext('onPostAuth', core),
|
|
58
|
+
onPreHandler: new Ext('onPreHandler', core),
|
|
59
|
+
onPostHandler: new Ext('onPostHandler', core),
|
|
60
|
+
onPreResponse: new Ext('onPreResponse', core)
|
|
61
|
+
},
|
|
62
|
+
modifiers: {
|
|
63
|
+
route: {}
|
|
64
|
+
},
|
|
65
|
+
parent: (parent ? parent.realm : null),
|
|
66
|
+
plugin: name,
|
|
67
|
+
pluginOptions: {},
|
|
68
|
+
plugins: {},
|
|
69
|
+
_rules: null,
|
|
70
|
+
settings: {
|
|
71
|
+
bind: undefined,
|
|
72
|
+
files: {
|
|
73
|
+
relativeTo: undefined
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
// Decorations
|
|
79
|
+
|
|
80
|
+
for (const method of core.decorations.server) {
|
|
81
|
+
this[method] = core._decorations.server[method];
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
core.registerServer(this);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
_clone(name) {
|
|
88
|
+
|
|
89
|
+
return new internals.Server(this._core, name, this);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
bind(context) {
|
|
93
|
+
|
|
94
|
+
Hoek.assert(typeof context === 'object', 'bind must be an object');
|
|
95
|
+
this.realm.settings.bind = context;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
control(server) {
|
|
99
|
+
|
|
100
|
+
Hoek.assert(server instanceof internals.Server, 'Can only control Server objects');
|
|
101
|
+
|
|
102
|
+
this._core.controlled = this._core.controlled || [];
|
|
103
|
+
this._core.controlled.push(server);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
decoder(encoding, decoder) {
|
|
107
|
+
|
|
108
|
+
return this._core.compression.addDecoder(encoding, decoder);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
decorate(type, property, method, options = {}) {
|
|
112
|
+
|
|
113
|
+
Hoek.assert(this._core.decorations[type], 'Unknown decoration type:', type);
|
|
114
|
+
Hoek.assert(property, 'Missing decoration property name');
|
|
115
|
+
Hoek.assert(typeof property === 'string' || typeof property === 'symbol', 'Decoration property must be a string or a symbol');
|
|
116
|
+
|
|
117
|
+
const propertyName = property.toString();
|
|
118
|
+
Hoek.assert(propertyName[0] !== '_', 'Property name cannot begin with an underscore:', propertyName);
|
|
119
|
+
|
|
120
|
+
const existing = this._core._decorations[type][property];
|
|
121
|
+
if (options.extend) {
|
|
122
|
+
Hoek.assert(type !== 'handler', 'Cannot extent handler decoration:', propertyName);
|
|
123
|
+
Hoek.assert(existing, `Cannot extend missing ${type} decoration: ${propertyName}`);
|
|
124
|
+
Hoek.assert(typeof method === 'function', `Extended ${type} decoration method must be a function: ${propertyName}`);
|
|
125
|
+
|
|
126
|
+
method = method(existing);
|
|
127
|
+
}
|
|
128
|
+
else {
|
|
129
|
+
Hoek.assert(existing === undefined, `${type[0].toUpperCase() + type.slice(1)} decoration already defined: ${propertyName}`);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
if (type === 'handler') {
|
|
133
|
+
|
|
134
|
+
// Handler
|
|
135
|
+
|
|
136
|
+
Hoek.assert(typeof method === 'function', 'Handler must be a function:', propertyName);
|
|
137
|
+
Hoek.assert(!method.defaults || typeof method.defaults === 'object' || typeof method.defaults === 'function', 'Handler defaults property must be an object or function');
|
|
138
|
+
Hoek.assert(!options.extend, 'Cannot extend handler decoration:', propertyName);
|
|
139
|
+
}
|
|
140
|
+
else if (type === 'request') {
|
|
141
|
+
|
|
142
|
+
// Request
|
|
143
|
+
|
|
144
|
+
Hoek.assert(Request.reserved.indexOf(property) === -1, 'Cannot override built-in request interface decoration:', propertyName);
|
|
145
|
+
|
|
146
|
+
if (options.apply) {
|
|
147
|
+
this._core._decorations.requestApply = this._core._decorations.requestApply || {};
|
|
148
|
+
this._core._decorations.requestApply[property] = method;
|
|
149
|
+
}
|
|
150
|
+
else {
|
|
151
|
+
this._core.Request.prototype[property] = method;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
else if (type === 'toolkit') {
|
|
155
|
+
|
|
156
|
+
// Toolkit
|
|
157
|
+
|
|
158
|
+
Hoek.assert(this._core.toolkit.reserved.indexOf(property) === -1, 'Cannot override built-in toolkit decoration:', propertyName);
|
|
159
|
+
}
|
|
160
|
+
else {
|
|
161
|
+
|
|
162
|
+
// Server
|
|
163
|
+
|
|
164
|
+
if (typeof property === 'string') {
|
|
165
|
+
Hoek.assert(Object.getOwnPropertyNames(internals.Server.prototype).indexOf(property) === -1, 'Cannot override the built-in server interface method:', propertyName);
|
|
166
|
+
}
|
|
167
|
+
else {
|
|
168
|
+
Hoek.assert(Object.getOwnPropertySymbols(internals.Server.prototype).indexOf(property) === -1, 'Cannot override the built-in server interface method:', propertyName);
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
this._core.instances.forEach((server) => {
|
|
172
|
+
|
|
173
|
+
server[property] = method;
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
this._core._decorations[type][property] = method;
|
|
178
|
+
this._core.decorations[type].push(property);
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
dependency(dependencies, after) {
|
|
182
|
+
|
|
183
|
+
Hoek.assert(this.realm.plugin, 'Cannot call dependency() outside of a plugin');
|
|
184
|
+
Hoek.assert(!after || typeof after === 'function', 'Invalid after method');
|
|
185
|
+
|
|
186
|
+
// Normalize to { plugin: version }
|
|
187
|
+
|
|
188
|
+
if (typeof dependencies === 'string') {
|
|
189
|
+
dependencies = { [dependencies]: '*' };
|
|
190
|
+
}
|
|
191
|
+
else if (Array.isArray(dependencies)) {
|
|
192
|
+
const map = {};
|
|
193
|
+
for (const dependency of dependencies) {
|
|
194
|
+
map[dependency] = '*';
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
dependencies = map;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
this._core.dependencies.push({ plugin: this.realm.plugin, deps: dependencies });
|
|
201
|
+
|
|
202
|
+
if (after) {
|
|
203
|
+
this.ext('onPreStart', after, { after: Object.keys(dependencies) });
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
encoder(encoding, encoder) {
|
|
208
|
+
|
|
209
|
+
return this._core.compression.addEncoder(encoding, encoder);
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
event(event) {
|
|
213
|
+
|
|
214
|
+
this._core.events.registerEvent(event);
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
expose(key, value) {
|
|
218
|
+
|
|
219
|
+
Hoek.assert(this.realm.plugin, 'Cannot call expose() outside of a plugin');
|
|
220
|
+
|
|
221
|
+
const plugin = this.realm.plugin;
|
|
222
|
+
this._core.plugins[plugin] = this._core.plugins[plugin] || {};
|
|
223
|
+
|
|
224
|
+
if (typeof key === 'string') {
|
|
225
|
+
this._core.plugins[plugin][key] = value;
|
|
226
|
+
}
|
|
227
|
+
else {
|
|
228
|
+
Hoek.merge(this._core.plugins[plugin], key);
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
ext(events, method, options) { // (event, method, options) -OR- (events)
|
|
233
|
+
|
|
234
|
+
if (typeof events === 'string') {
|
|
235
|
+
events = { type: events, method, options };
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
events = Config.apply('exts', events);
|
|
239
|
+
for (const event of events) {
|
|
240
|
+
this._ext(event);
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
_ext(event) {
|
|
245
|
+
|
|
246
|
+
event = Object.assign({}, event); // Shallow cloned
|
|
247
|
+
event.realm = this.realm;
|
|
248
|
+
const type = event.type;
|
|
249
|
+
|
|
250
|
+
if (!this._core.extensions.server[type]) {
|
|
251
|
+
|
|
252
|
+
// Realm route extensions
|
|
253
|
+
|
|
254
|
+
if (event.options.sandbox === 'plugin') {
|
|
255
|
+
Hoek.assert(this.realm._extensions[type], 'Unknown event type', type);
|
|
256
|
+
return this.realm._extensions[type].add(event);
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
// Connection route extensions
|
|
260
|
+
|
|
261
|
+
Hoek.assert(this._core.extensions.route[type], 'Unknown event type', type);
|
|
262
|
+
return this._core.extensions.route[type].add(event);
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
// Server extensions
|
|
266
|
+
|
|
267
|
+
Hoek.assert(!event.options.sandbox, 'Cannot specify sandbox option for server extension');
|
|
268
|
+
Hoek.assert(type !== 'onPreStart' || this._core.phase === 'stopped', 'Cannot add onPreStart (after) extension after the server was initialized');
|
|
269
|
+
|
|
270
|
+
event.server = this;
|
|
271
|
+
this._core.extensions.server[type].add(event);
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
async inject(options) {
|
|
275
|
+
|
|
276
|
+
let settings = options;
|
|
277
|
+
if (typeof settings === 'string') {
|
|
278
|
+
settings = { url: settings };
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
if (!settings.authority ||
|
|
282
|
+
settings.auth ||
|
|
283
|
+
settings.app ||
|
|
284
|
+
settings.plugins ||
|
|
285
|
+
settings.allowInternals !== undefined) { // Can be false
|
|
286
|
+
|
|
287
|
+
settings = Object.assign({}, settings); // options can be reused (shallow cloned)
|
|
288
|
+
delete settings.auth;
|
|
289
|
+
delete settings.app;
|
|
290
|
+
delete settings.plugins;
|
|
291
|
+
delete settings.allowInternals;
|
|
292
|
+
|
|
293
|
+
settings.authority = settings.authority || (this._core.info.host + ':' + this._core.info.port);
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
Hoek.assert(!options.credentials, 'options.credentials no longer supported (use options.auth)');
|
|
297
|
+
|
|
298
|
+
if (options.auth) {
|
|
299
|
+
Hoek.assert(typeof options.auth === 'object', 'options.auth must be an object');
|
|
300
|
+
Hoek.assert(options.auth.credentials, 'options.auth.credentials is missing');
|
|
301
|
+
Hoek.assert(options.auth.strategy, 'options.auth.strategy is missing');
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
const needle = this._core._dispatch({
|
|
305
|
+
auth: options.auth,
|
|
306
|
+
allowInternals: options.allowInternals,
|
|
307
|
+
app: options.app,
|
|
308
|
+
plugins: options.plugins
|
|
309
|
+
});
|
|
310
|
+
|
|
311
|
+
const res = await Shot.inject(needle, settings);
|
|
312
|
+
const custom = res.raw.res[Config.symbol];
|
|
313
|
+
if (custom) {
|
|
314
|
+
res.result = custom.result;
|
|
315
|
+
res.request = custom.request;
|
|
316
|
+
delete res.raw.res[Config.symbol];
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
if (res.result === undefined) {
|
|
320
|
+
res.result = res.payload;
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
return res;
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
log(tags, data) {
|
|
327
|
+
|
|
328
|
+
return this._core.log(tags, data);
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
lookup(id) {
|
|
332
|
+
|
|
333
|
+
Hoek.assert(id && typeof id === 'string', 'Invalid route id:', id);
|
|
334
|
+
|
|
335
|
+
const record = this._core.router.ids[id];
|
|
336
|
+
if (!record) {
|
|
337
|
+
return null;
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
return record.route.public;
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
match(method, path, host) {
|
|
344
|
+
|
|
345
|
+
Hoek.assert(method && typeof method === 'string', 'Invalid method:', method);
|
|
346
|
+
Hoek.assert(path && typeof path === 'string' && path[0] === '/', 'Invalid path:', path);
|
|
347
|
+
Hoek.assert(!host || typeof host === 'string', 'Invalid host:', host);
|
|
348
|
+
|
|
349
|
+
const match = this._core.router.route(method.toLowerCase(), path, host);
|
|
350
|
+
Hoek.assert(match !== this._core.router.specials.badRequest, 'Invalid path:', path);
|
|
351
|
+
if (match === this._core.router.specials.notFound) {
|
|
352
|
+
return null;
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
return match.route.public;
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
method(name, method, options = {}) {
|
|
359
|
+
|
|
360
|
+
return this._core.methods.add(name, method, options, this.realm);
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
path(relativeTo) {
|
|
364
|
+
|
|
365
|
+
Hoek.assert(relativeTo && typeof relativeTo === 'string', 'relativeTo must be a non-empty string');
|
|
366
|
+
this.realm.settings.files.relativeTo = relativeTo;
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
async register(plugins, options = {}) {
|
|
370
|
+
|
|
371
|
+
if (this.realm.modifiers.route.prefix ||
|
|
372
|
+
this.realm.modifiers.route.vhost) {
|
|
373
|
+
|
|
374
|
+
options = Hoek.clone(options);
|
|
375
|
+
options.routes = options.routes || {};
|
|
376
|
+
|
|
377
|
+
options.routes.prefix = (this.realm.modifiers.route.prefix || '') + (options.routes.prefix || '') || undefined;
|
|
378
|
+
options.routes.vhost = this.realm.modifiers.route.vhost || options.routes.vhost;
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
options = Config.apply('register', options);
|
|
382
|
+
|
|
383
|
+
++this._core.registring;
|
|
384
|
+
|
|
385
|
+
try {
|
|
386
|
+
const items = [].concat(plugins);
|
|
387
|
+
for (let item of items) {
|
|
388
|
+
|
|
389
|
+
/*
|
|
390
|
+
{ register, ...attributes }
|
|
391
|
+
{ plugin: { register, ...attributes }, options, once, routes }
|
|
392
|
+
{ plugin: { plugin: { register, ...attributes } }, options, once, routes } // Required module
|
|
393
|
+
*/
|
|
394
|
+
|
|
395
|
+
if (!item.plugin) {
|
|
396
|
+
item = {
|
|
397
|
+
plugin: item
|
|
398
|
+
};
|
|
399
|
+
}
|
|
400
|
+
else if (!item.plugin.register) {
|
|
401
|
+
item = {
|
|
402
|
+
options: item.options,
|
|
403
|
+
once: item.once,
|
|
404
|
+
routes: item.routes,
|
|
405
|
+
plugin: item.plugin.plugin
|
|
406
|
+
};
|
|
407
|
+
}
|
|
408
|
+
else if (typeof item === 'function') {
|
|
409
|
+
item = Object.assign({}, item); // Shallow cloned
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
item = Config.apply('plugin', item);
|
|
413
|
+
|
|
414
|
+
const name = item.plugin.name || item.plugin.pkg.name;
|
|
415
|
+
const clone = this._clone(name);
|
|
416
|
+
|
|
417
|
+
clone.realm.modifiers.route.prefix = item.routes.prefix || options.routes.prefix;
|
|
418
|
+
clone.realm.modifiers.route.vhost = item.routes.vhost || options.routes.vhost;
|
|
419
|
+
clone.realm.pluginOptions = item.options || {};
|
|
420
|
+
|
|
421
|
+
// Validate requirements
|
|
422
|
+
|
|
423
|
+
const requirements = item.plugin.requirements;
|
|
424
|
+
Hoek.assert(!requirements.node || Somever.match(process.version, requirements.node), 'Plugin', name, 'requires node version', requirements.node, 'but found', process.version);
|
|
425
|
+
Hoek.assert(!requirements.hapi || Somever.match(this.version, requirements.hapi), 'Plugin', name, 'requires hapi version', requirements.hapi, 'but found', this.version);
|
|
426
|
+
|
|
427
|
+
// Protect against multiple registrations
|
|
428
|
+
|
|
429
|
+
if (this._core.registrations[name]) {
|
|
430
|
+
if (item.plugin.once ||
|
|
431
|
+
item.once ||
|
|
432
|
+
options.once) {
|
|
433
|
+
|
|
434
|
+
continue;
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
Hoek.assert(item.plugin.multiple, 'Plugin', name, 'already registered');
|
|
438
|
+
}
|
|
439
|
+
else {
|
|
440
|
+
this._core.registrations[name] = {
|
|
441
|
+
version: item.plugin.version || item.plugin.pkg.version,
|
|
442
|
+
name,
|
|
443
|
+
options: item.options
|
|
444
|
+
};
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
if (item.plugin.dependencies) {
|
|
448
|
+
clone.dependency(item.plugin.dependencies);
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
// Register
|
|
452
|
+
|
|
453
|
+
await item.plugin.register(clone, item.options || {});
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
catch (err) {
|
|
457
|
+
throw err;
|
|
458
|
+
}
|
|
459
|
+
finally {
|
|
460
|
+
--this._core.registring;
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
route(options) {
|
|
465
|
+
|
|
466
|
+
Hoek.assert(typeof options === 'object', 'Invalid route options');
|
|
467
|
+
|
|
468
|
+
options = [].concat(options);
|
|
469
|
+
for (const config of options) {
|
|
470
|
+
if (Array.isArray(config.method)) {
|
|
471
|
+
for (const method of config.method) {
|
|
472
|
+
const settings = Object.assign({}, config); // Shallow cloned
|
|
473
|
+
settings.method = method;
|
|
474
|
+
this._addRoute(settings, this);
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
else {
|
|
478
|
+
this._addRoute(config, this);
|
|
479
|
+
}
|
|
480
|
+
}
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
_addRoute(config, server) {
|
|
484
|
+
|
|
485
|
+
const route = new Route(config, server); // Do no use config beyond this point, use route members
|
|
486
|
+
const vhosts = [].concat(route.settings.vhost || '*');
|
|
487
|
+
|
|
488
|
+
for (const vhost of vhosts) {
|
|
489
|
+
const record = this._core.router.add({ method: route.method, path: route.path, vhost, analysis: route._analysis, id: route.settings.id }, route);
|
|
490
|
+
route.fingerprint = record.fingerprint;
|
|
491
|
+
route.params = record.params;
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
this.events.emit('route', route.public);
|
|
495
|
+
Cors.options(route.public, server);
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
rules(processor, options = {}) {
|
|
499
|
+
|
|
500
|
+
Hoek.assert(!this.realm._rules, 'Server realm rules already defined');
|
|
501
|
+
|
|
502
|
+
const settings = Config.apply('rules', options);
|
|
503
|
+
if (settings.validate) {
|
|
504
|
+
const schema = settings.validate.schema;
|
|
505
|
+
settings.validate.schema = Joi.compile(schema);
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
this.realm._rules = { processor, settings };
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
state(name, options) {
|
|
512
|
+
|
|
513
|
+
this.states.add(name, options);
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
table(host) {
|
|
517
|
+
|
|
518
|
+
return this._core.router.table(host);
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
start() {
|
|
522
|
+
|
|
523
|
+
return this._core._start();
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
initialize() {
|
|
527
|
+
|
|
528
|
+
return this._core._initialize();
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
stop(options) {
|
|
532
|
+
|
|
533
|
+
return this._core._stop(options);
|
|
534
|
+
}
|
|
535
|
+
};
|
|
536
|
+
|
|
537
|
+
|
|
538
|
+
internals.cache = (plugin) => {
|
|
539
|
+
|
|
540
|
+
const policy = function (options, _segment) {
|
|
541
|
+
|
|
542
|
+
return this._core._cachePolicy(options, _segment, plugin.realm);
|
|
543
|
+
};
|
|
544
|
+
|
|
545
|
+
policy.provision = async (opts) => {
|
|
546
|
+
|
|
547
|
+
const clients = plugin._core._createCache(opts);
|
|
548
|
+
|
|
549
|
+
// Start cache
|
|
550
|
+
|
|
551
|
+
if (['initialized', 'starting', 'started'].indexOf(plugin._core.phase) !== -1) {
|
|
552
|
+
await Promise.all(clients.map((client) => client.start()));
|
|
553
|
+
}
|
|
554
|
+
};
|
|
555
|
+
|
|
556
|
+
return policy;
|
|
557
|
+
};
|
package/lib/streams.js
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const Teamwork = require('teamwork');
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
const internals = {
|
|
7
|
+
team: Symbol('team')
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
exports.drain = function (stream) {
|
|
12
|
+
|
|
13
|
+
const team = new Teamwork();
|
|
14
|
+
stream[internals.team] = team;
|
|
15
|
+
|
|
16
|
+
stream.on('readable', internals.read);
|
|
17
|
+
stream.on('error', internals.end);
|
|
18
|
+
stream.on('end', internals.end);
|
|
19
|
+
|
|
20
|
+
return team.work;
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
internals.read = function () {
|
|
25
|
+
|
|
26
|
+
this.read();
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
internals.end = function () {
|
|
31
|
+
|
|
32
|
+
this.removeListener('readable', internals.read);
|
|
33
|
+
this.removeListener('error', internals.end);
|
|
34
|
+
this.removeListener('end', internals.end);
|
|
35
|
+
|
|
36
|
+
this[internals.team].attend();
|
|
37
|
+
};
|