/
index.js
108 lines (94 loc) · 2.95 KB
/
index.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
'use strict';
var Promise = require('bluebird');
var assert = require('assert');
var Joi = require('joi');
var Hoek = require('hoek');
var Boom = require('boom');
var internals = {};
var routerSchema = Joi.object().keys({
path: Joi.string().required(),
method: Joi.string().required(),
handler: Joi.func().arity(2).required()
});
var eventSchema = Joi.object().keys({
context: Joi.object().keys({
'resource-path': Joi.string().required(),
'http-method': Joi.string().required(),
}).unknown().required()
}).unknown().required();
module.exports = exports = internals.Router = function(options) {
this.routes = {};
var opts = options || {};
return this;
};
internals.Router.prototype.register = function(route) {
var routes = this.routes;
Hoek.assert(route, 'route is required');
var result = Joi.validate(route, routerSchema);
if (result.error) {
throw (result.error);
}
if (!routes[route.path]) {
routes[route.path] = {};
}
routes[route.path][route.method.toUpperCase()] = route;
};
internals.Router.prototype.route = function(event, context) {
var self = this;
return new Promise((resolve, reject) => {
if (context == null) {
let error = this._processError(Boom.badImplementation('context is required'));
return reject(error);
}
var result = Joi.validate(event, eventSchema);
if (result.error) {
let error = this._processError(result.error);
return reject(error);
}
if (event.context && event.context['resource-path']) {
let route = this._getRoute(event, context);
if (route) {
return route.handler(event, context)
.then((response) => {
return resolve(response);
})
.catch((error) => {
let newError = this._processError(error);
return reject(newError);
});
} else {
let error = this._processError(Boom.notImplemented(event.context['http-method'] + ' handler for path [' + event.context['resource-path'] + '] not registered'));
return reject(error);
}
} else {
let error = this._processError(Boom.badImplementation('Request context, method, and path are required'));
return reject(error);
}
});
};
internals.Router.prototype._processError = function(error) {
var transformed = error;
if (error.isJoi) {
transformed = this._validationError(error);
}
if (transformed.isBoom) {
transformed = transformed.output.payload;
}
return transformed;
}
internals.Router.prototype._validationError = function(error) {
var errorValue;
errorValue = Boom.badRequest('Invalid request input: ' + error.message);
if (error.details) {
errorValue.output.payload.details = error.details;
}
return errorValue;
}
internals.Router.prototype._getRoute = function(event, context) {
var entry = this.routes[event.context['resource-path']];
if (entry) {
return entry[event.context['http-method'].toUpperCase()];
} else {
return null;
}
};