-
Notifications
You must be signed in to change notification settings - Fork 75
/
routes.js
126 lines (101 loc) · 4.76 KB
/
routes.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
'use strict';
const ObjectFiles = require('merge-object-files');
const Validators = require('./validators');
const Hoek = require('@hapi/hoek');
const Utils = require('./utils');
const Path = require('path');
const Props = require('dot-prop');
const create = async function (server, { api, basedir, cors, vhost, handlers, extensions, outputvalidation }) {
const routes = [];
const validator = Validators.create({ api });
if (typeof handlers === 'string') {
handlers = await ObjectFiles.merge(handlers, extensions);
}
//Support x-hapi-handler when no handlers set.
if (!handlers) {
for (const [path, operations] of Object.entries(api.paths)) {
if (operations['x-hapi-handler']) {
const pathnames = path.split('/').slice(1).join('.');
if (!handlers) {
handlers = {};
}
const xhandler = require(Path.resolve(Path.join(basedir, operations['x-hapi-handler'])));
Props.set(handlers, pathnames, xhandler);
}
}
}
for (const [path, operations] of Object.entries(api.paths)) {
const pathnames = Utils.unsuffix(path, '/').split('/').slice(1).join('.');
for (const [method, operation] of Object.entries(operations)) {
const pathsearch = `${pathnames}.${method}`;
const handler = Hoek.reach(handlers, pathsearch);
const xoptions = operation['x-hapi-options'] || {};
if (!handler) {
continue;
}
const customTags = operation.tags || [];
const options = Object.assign({
cors,
id: operation.operationId,
// hapi does not support empty descriptions
description: operation.description !== '' ? operation.description : undefined,
tags: ['api', ...customTags]
}, xoptions);
options.handler = handler;
if (Utils.canCarry(method)) {
options.payload = options.payload ? Hoek.applyToDefaults({ allow: operation.consumes || api.consumes }, options.payload) : { allow: operation.consumes || api.consumes };
}
if (Array.isArray(handler)) {
options.pre = [];
for (let i = 0; i < handler.length - 1; ++i) {
options.pre.push({
assign: handler[i].name || 'p' + (i + 1),
method: handler[i]
});
}
options.handler = handler[handler.length - 1];
}
const skipValidation = options.payload && options.payload.parse === false;
if (operation.parameters && !skipValidation) {
const allowUnknownProperties = xoptions.validate && xoptions.validate.options && xoptions.validate.options.allowUnknown === true;
const v = validator.makeAll(operation.parameters, operation.consumes || api.consumes, allowUnknownProperties);
options.validate = v.validate;
options.ext = {
onPreAuth: { method: v.routeExt }
};
}
if (outputvalidation && operation.responses) {
options.response = {};
options.response.status = validator.makeResponseValidator(operation.responses);
}
if (operation.security === undefined && api.security) {
operation.security = api.security;
}
if (operation.security && operation.security.length) {
for (const secdef of operation.security) {
const securitySchemes = Object.keys(secdef);
for (const securityDefinitionName of securitySchemes) {
const securityDefinition = api.securityDefinitions[securityDefinitionName];
Hoek.assert(securityDefinition, 'Security scheme not defined.');
options.auth = options.auth || { access: {}, mode: 'required' };
options.auth.access.scope = options.auth.access.scope || [];
options.auth.access.scope.push(...secdef[securityDefinitionName]);
options.auth.strategies = options.auth.strategies || [];
options.auth.strategies.push(securityDefinitionName);
}
}
if (options.auth.access.scope.length === 0) {
options.auth.access.scope = false;
}
}
routes.push({
method,
path: api.basePath + path,
options,
vhost
});
}
}
return routes;
};
module.exports = { create };