hyperswitch
Advanced tools
Comparing version 0.2.2 to 0.3.0
@@ -246,36 +246,2 @@ 'use strict'; | ||
HyperSwitch.prototype._wrapInMetrics = function(handlerPromise, match, req) { | ||
var self = this; | ||
// Remove the /{domain}/ prefix, as it's not very useful in stats | ||
var statName = match.value.path.replace(/\/[^\/]+\//, '') | ||
+ '.' + req.method.toUpperCase() + '.'; | ||
// Normalize invalid chars | ||
statName = self.metrics.normalizeName(statName); | ||
// Start timer | ||
var startTime = Date.now(); | ||
return handlerPromise.then(function(res) { | ||
// Record request metrics & log | ||
var statusClass = Math.floor(res.status / 100) + 'xx'; | ||
self.metrics.endTiming([ | ||
statName + res.status, | ||
statName + statusClass, | ||
statName + 'ALL', | ||
], startTime); | ||
return res; | ||
}, | ||
function(err) { | ||
var statusClass = '5xx'; | ||
if (err && err.status) { | ||
statusClass = Math.floor(err.status / 100) + 'xx'; | ||
} | ||
self.metrics.endTiming([ | ||
statName + err.status, | ||
statName + statusClass, | ||
statName + 'ALL', | ||
], startTime); | ||
throw err; | ||
}); | ||
}; | ||
HyperSwitch.prototype._wrapInAccessCheck = function(handlerPromise, match, childReq) { | ||
@@ -357,19 +323,32 @@ var self = this; | ||
// Call the handler with P.try to catch synchronous exceptions. | ||
var reqHandlerPromise; | ||
if (handler.validator) { | ||
reqHandlerPromise = P.try(function() { | ||
return handler.validator.validate(childReq); | ||
}) | ||
.then(function() { | ||
return handler(childHyperSwitch, childReq); | ||
}); | ||
} else { | ||
reqHandlerPromise = P.try(handler, [childHyperSwitch, childReq]); | ||
} | ||
var specInfo = { | ||
path: match.value.path, | ||
spec: handler.spec | ||
}; | ||
var filterIdx = 0; | ||
var reqHandler = function handlerWrapper(req, hyper) { | ||
if (filterIdx < match.filters.length) { | ||
var filter = match.filters[filterIdx]; | ||
filterIdx++; | ||
if (self.metrics) { | ||
reqHandlerPromise = childHyperSwitch._wrapInMetrics(reqHandlerPromise, match, req); | ||
} | ||
if (filter.method | ||
&& filter.method !== req.method | ||
&& !(filter.method === 'get' && req.method === 'head')) { | ||
return handlerWrapper(req, hyper); | ||
} | ||
return filter.filter(req, hyper, handlerWrapper, filter.options, specInfo); | ||
} else { | ||
return P.method(handler)(req, hyper); | ||
} | ||
}; | ||
// This is a hack. Pure P.try get's executed on this tick, but we wanna | ||
// wrap it in metrics and access checks and start execution only afterwards. | ||
// This will go away when filters are completed. | ||
var reqHandlerPromise = P.resolve() | ||
.then(function() { | ||
return reqHandler(childHyperSwitch, childReq); | ||
}); | ||
reqHandlerPromise = reqHandlerPromise | ||
@@ -376,0 +355,0 @@ .then(function(res) { |
@@ -8,3 +8,2 @@ "use strict"; | ||
var swaggerRouter = require('swagger-router'); | ||
var Validator = require('./validator'); | ||
var path = require('path'); | ||
@@ -102,2 +101,46 @@ | ||
Router.prototype._expandOptions = function(def, globals) { | ||
// Expand options in the parent context, so that config options can be | ||
// passed down the chain. | ||
var options = {}; | ||
if (def.options) { | ||
// Protect "templates" property from expansion. | ||
var templates = def.options.templates; | ||
delete def.options.templates; | ||
options = new Template(def.options).expand(globals) || {}; | ||
// Add the original "templates" property back. | ||
options.templates = templates; | ||
} | ||
// Append the log property to module options, if it is not present | ||
if (!options.log) { | ||
options.log = this._options.log || function() {}; | ||
} | ||
return options; | ||
}; | ||
Router.prototype._loadRequestFilter = function(filterDef, globals, method) { | ||
if (filterDef.type === 'default') { | ||
filterDef.path = __dirname + '/filters/' + filterDef.name + '.js'; | ||
} | ||
return { | ||
filter: this._requireModule(filterDef.path), | ||
options: this._expandOptions(filterDef, globals), | ||
method: method | ||
}; | ||
}; | ||
Router.prototype._loadRequestFilters = function(node, spec, scope, method) { | ||
var self = this; | ||
var filtersDef = spec['x-request-filters']; | ||
if (Array.isArray(filtersDef)) { | ||
var filters = filtersDef.map(function(filterDef) { | ||
return self._loadRequestFilter(filterDef, scope.globals, method); | ||
}); | ||
node.value = node.value || {}; | ||
node.value.filters = [].concat(node.value.filters || [], filters); | ||
} | ||
}; | ||
/** | ||
@@ -158,19 +201,4 @@ * Load and initialize a module | ||
// Expand options in the parent context, so that config options can be | ||
// passed down the chain. | ||
var options = {}; | ||
if (modDef.options) { | ||
// Protect "templates" property from expansion. | ||
var templates = modDef.options.templates; | ||
delete modDef.options.templates; | ||
options = new Template(modDef.options).expand(globals) || {}; | ||
// Add the original "templates" property back. | ||
options.templates = templates; | ||
} | ||
var options = this._expandOptions(modDef, globals); | ||
// Append the log property to module options, if it is not present | ||
if (!options.log) { | ||
options.log = this._options.log || function() {}; | ||
} | ||
function constructModule(spec) { | ||
@@ -289,3 +317,3 @@ var mod = { | ||
var backendSetup = method && method['x-setup-handler']; | ||
var backendSetup = method['x-setup-handler']; | ||
if (backendSetup) { | ||
@@ -296,12 +324,11 @@ Array.prototype.push.apply(node.value.resources, | ||
var backendRequest = method && method['x-request-handler']; | ||
var reqHandler; | ||
var backendRequest = method['x-request-handler']; | ||
if (backendRequest) { | ||
node.value.methods[methodName] = handlerTemplate.createHandler(backendRequest, { | ||
reqHandler = handlerTemplate.createHandler(backendRequest, { | ||
globals: node.value.globals, | ||
}); | ||
} else if (method.operationId) { | ||
var handler = scope.operations[method.operationId]; | ||
if (handler) { | ||
node.value.methods[methodName] = handler; | ||
} else { | ||
reqHandler = scope.operations[method.operationId]; | ||
if (!reqHandler) { | ||
throw new Error('No known handler associated with operationId ' | ||
@@ -312,4 +339,5 @@ + method.operationId); | ||
if (method && method.parameters && node.value.methods[methodName]) { | ||
node.value.methods[methodName].validator = new Validator(method.parameters); | ||
if (reqHandler) { | ||
node.value.methods[methodName] = reqHandler; | ||
node.value.methods[methodName].spec = method; | ||
} | ||
@@ -497,2 +525,5 @@ }); | ||
Object.assign(scope.specRoot.securityDefinitions, spec.securityDefinitions || {}); | ||
this._loadRequestFilters(node, spec, scope); | ||
return this._handlePaths(node, spec, scope); | ||
@@ -548,2 +579,8 @@ }; | ||
}); | ||
// First load default request filters | ||
// TODO: Do that in a cleaner way | ||
spec['x-request-filters'] = spec['x-request-filters'] || []; | ||
spec['x-request-filters'].push({ type: 'default', name: 'validator' }); | ||
spec['x-request-filters'].push({ type: 'default', name: 'metrics' }); | ||
return self._handleSwaggerSpec(rootNode, spec, scope) | ||
@@ -550,0 +587,0 @@ .then(function() { |
{ | ||
"name": "hyperswitch", | ||
"version": "0.2.2", | ||
"version": "0.3.0", | ||
"description": "REST API creation framework", | ||
@@ -33,3 +33,3 @@ "main": "index.js", | ||
"preq": "^0.4.8", | ||
"swagger-router": "^0.4.0", | ||
"swagger-router": "^0.4.1", | ||
"swagger-ui": "git+https://github.com/wikimedia/swagger-ui#master", | ||
@@ -36,0 +36,0 @@ "json-stable-stringify": "git+https://github.com/wikimedia/json-stable-stringify#master", |
Manifest confusion
Supply chain riskThis package has inconsistent metadata. This could be malicious or caused by an error when publishing the package.
Found 2 instances in 1 package
166426
46
3889
3
Updatedswagger-router@^0.4.1