Plato on Github
Report Home
lib/handler.js
Maintainability
65.80
Lines of code
293
Difficulty
50.24
Estimated Errors
2.20
Function weight
By Complexity
By SLOC
'use strict'; // Load modules const Hoek = require('hoek'); const Items = require('items'); const Methods = require('./methods'); const Response = require('./response'); // Declare internals const internals = {}; exports.execute = function (request, next) { const finalize = (err, result) => { request._setResponse(err || result); return next(); // Must not include an argument }; request._protect.run(finalize, (exit) => { if (request._route._prerequisites) { internals.prerequisites(request, Hoek.once(exit)); } else { internals.handler(request, exit); } }); }; internals.prerequisites = function (request, callback) { const each = (set, nextSet) => { Items.parallel(set, (pre, next) => { pre(request, (err, result) => { if (err) { return next(err); } if (!result._takeover) { return next(); } return callback(null, result); }); }, nextSet); }; Items.serial(request._route._prerequisites, each, (err) => { if (err) { return callback(err); } return internals.handler(request, callback); }); }; internals.handler = function (request, callback) { const timer = new Hoek.Bench(); const finalize = (response, data) => { if (response === null) { // reply.continue() response = Response.wrap(null, request); return response._prepare(null, finalize); } // Check for Error result if (response.isBoom) { request._log(['handler', 'error'], { msec: timer.elapsed(), error: response.message, data: response }); return callback(response); } request._log(['handler'], { msec: timer.elapsed() }); return callback(null, response); }; // Decorate request const reply = request.server._replier.interface(request, request.route.realm, finalize); const bind = request.route.settings.bind; // Execute handler request.route.settings.handler.call(bind, request, reply); }; exports.defaults = function (method, handler, server) { let defaults = null; if (typeof handler === 'object') { const type = Object.keys(handler)[0]; const serverHandler = server._handlers[type]; Hoek.assert(serverHandler, 'Unknown handler:', type); if (serverHandler.defaults) { defaults = (typeof serverHandler.defaults === 'function' ? serverHandler.defaults(method) : serverHandler.defaults); } } return defaults || {}; }; exports.configure = function (handler, route) { if (typeof handler === 'object') { const type = Object.keys(handler)[0]; const serverHandler = route.server._handlers[type]; Hoek.assert(serverHandler, 'Unknown handler:', type); return serverHandler(route.public, handler[type]); } if (typeof handler === 'string') { const parsed = internals.fromString('handler', handler, route.server); return parsed.method; } return handler; }; exports.prerequisitesConfig = function (config, server) { if (!config) { return null; } /* [ [ function (request, reply) { }, { method: function (request, reply) { } assign: key1 }, { method: function (request, reply) { }, assign: key2 } ], 'user(params.id)' ] */ const prerequisites = []; for (let i = 0; i < config.length; ++i) { const pres = [].concat(config[i]); const set = []; for (let j = 0; j < pres.length; ++j) { let pre = pres[j]; if (typeof pre !== 'object') { pre = { method: pre }; } const item = { method: pre.method, assign: pre.assign, failAction: pre.failAction || 'error' }; if (typeof item.method === 'string') { const parsed = internals.fromString('pre', item.method, server); item.method = parsed.method; item.assign = item.assign || parsed.name; } set.push(internals.pre(item)); } prerequisites.push(set); } return prerequisites.length ? prerequisites : null; }; internals.fromString = function (type, notation, server) { // 1:name 2:( 3:arguments const methodParts = notation.match(/^([\w\.]+)(?:\s*)(?:(\()(?:\s*)(\w+(?:\.\w+)*(?:\s*\,\s*\w+(?:\.\w+)*)*)?(?:\s*)\))?$/); Hoek.assert(methodParts, 'Invalid server method string notation:', notation); const name = methodParts[1]; Hoek.assert(name.match(Methods.methodNameRx), 'Invalid server method name:', name); const method = server._methods._normalized[name]; Hoek.assert(method, 'Unknown server method in string notation:', notation); const result = { name: name }; const argsNotation = !!methodParts[2]; const methodArgs = (argsNotation ? (methodParts[3] || '').split(/\s*\,\s*/) : null); result.method = (request, reply) => { if (!argsNotation) { return method(request, reply); // Method is already bound to context } const finalize = (err, value, cached, report) => { if (report) { request._log([type, 'method', name], report); } return reply(err, value); }; const args = []; for (let i = 0; i < methodArgs.length; ++i) { const arg = methodArgs[i]; if (arg) { args.push(Hoek.reach(request, arg)); } } args.push(finalize); method.apply(null, args); }; return result; }; internals.pre = function (pre) { /* { method: function (request, next) { } assign: 'key' failAction: 'error'* | 'log' | 'ignore' } */ return (request, next) => { const timer = new Hoek.Bench(); const finalize = (response, data) => { if (response === null) { // reply.continue() response = Response.wrap(null, request); return response._prepare(null, finalize); } if (response instanceof Error) { if (pre.failAction !== 'ignore') { request._log(['pre', 'error'], { msec: timer.elapsed(), assign: pre.assign, error: response }); } if (pre.failAction === 'error') { return next(response); } } else { request._log(['pre'], { msec: timer.elapsed(), assign: pre.assign }); } if (pre.assign) { request.pre[pre.assign] = response.source; request.preResponses[pre.assign] = response; } return next(null, response); }; // Setup environment const reply = request.server._replier.interface(request, request.route.realm, finalize); const bind = request.route.settings.bind; // Execute handler pre.method.call(bind, request, reply); }; };