Comparing version 2.3.4 to 2.3.5
# restify Changelog | ||
## 2.3.5 (not yet released) | ||
## Not Yet Released | ||
## 2.3.5 | ||
- bunyan@0.20.0 | ||
- GH-346 `server.toString()` crashes (Alex Whitman) | ||
- GH-193 support `next('name_of_route')` | ||
## 2.3.4 | ||
@@ -6,0 +12,0 @@ |
@@ -26,2 +26,3 @@ // Copyright 2012 Mark Cavage, Inc. All rights reserved. | ||
var BadRequestError = errors.BadRequestError; | ||
var InternalError = errors.InternalError; | ||
var InvalidArgumentError = errors.InvalidArgumentError; | ||
@@ -262,5 +263,27 @@ var InvalidVersionError = errors.InvalidVersionError; | ||
Router.prototype.get = function get(name, req, cb) { | ||
var params; | ||
var route = false; | ||
var routes = this.routes[req.method] || []; | ||
for (var i = 0; i < routes.length; i++) { | ||
if (routes[i].name === name) { | ||
route = routes[i]; | ||
try { | ||
params = matchURL(route.path, req); | ||
} catch (e) {} | ||
break; | ||
} | ||
} | ||
if (route) { | ||
cb(null, route, params || {}); | ||
} else { | ||
cb(new InternalError()); | ||
} | ||
}; | ||
Router.prototype.find = function find(req, res, callback) { | ||
var candidates = []; | ||
// var candidateKeys = []; | ||
var ct = req.headers['content-type'] || DEF_CT; | ||
@@ -436,3 +459,3 @@ var cacheKey = req.method + req.url + req.version() + ct; | ||
if (preflight(res.methods)) { | ||
callback(null, true); | ||
callback(null, { name: 'preflight' }); | ||
return; | ||
@@ -439,0 +462,0 @@ } |
@@ -125,3 +125,47 @@ // Copyright 2012 Mark Cavage, Inc. All rights reserved. | ||
function ifError(n) { | ||
function _ifError(err) { | ||
if (err) { | ||
err._restify_next = n; | ||
throw err; | ||
} | ||
} | ||
return (_ifError); | ||
} | ||
function emitRouteError(server, req, res, err) { | ||
var name; | ||
if (err.name === 'ResourceNotFoundError') { | ||
name = 'NotFound'; | ||
} else if (err.name === 'InvalidVersionError') { | ||
name = 'VersionNotAllowed'; | ||
} else { | ||
name = err.name.replace(/Error$/, ''); | ||
} | ||
if (server.listeners(name).length > 0) { | ||
server.emit(name, req, res, once(function () { | ||
server.emit('after', req, res, null); | ||
})); | ||
} else { | ||
res.send(err); | ||
server.emit('after', req, res, null); | ||
} | ||
} | ||
function optionsError(err, req, res) { | ||
var code = err.statusCode; | ||
var ok = false; | ||
if (code === 404 && req.method === 'OPTIONS' && req.url === '*') { | ||
res.send(200); | ||
ok = true; | ||
} | ||
return (ok); | ||
} | ||
///--- API | ||
@@ -494,3 +538,3 @@ | ||
str += sprintf(LINE_FMT, 'Router', this.router.toString()); | ||
str += sprintf(LINE_FMT, 'Routes:', ''); | ||
str += sprintf(LINE_FMT, 'Routes', ''); | ||
Object.keys(this.routes).forEach(function (k) { | ||
@@ -502,3 +546,3 @@ var handlers = handlersToString(self.routes[k]); | ||
str += sprintf(LINE_FMT, 'Url', this.url); | ||
str += sprintf(LINE_FMT, 'Version', this.version.join()); | ||
str += sprintf(LINE_FMT, 'Version', this.versions.join()); | ||
@@ -513,114 +557,78 @@ return (str); | ||
Server.prototype._handle = function _handle(req, res) { | ||
var log = this.log; | ||
var self = this; | ||
function _route() { | ||
if (log.trace()) { | ||
log.trace({ | ||
req: req, | ||
req_id: req.getId() | ||
}, 'checking for route'); | ||
} | ||
function routeAndRun() { | ||
self._route(req, res, function (route, context) { | ||
req.context = req.params = context; | ||
req.route = route.spec; | ||
var chain = self.routes[route]; | ||
function emitRouteError(name, err) { | ||
if (self.listeners(name).length > 0) { | ||
self.emit(name, req, res, once(function () { | ||
self.emit('after', req, res, null); | ||
})); | ||
} else { | ||
res.send(err); | ||
self.emit('after', req, res, null); | ||
} | ||
} | ||
self._run(req, res, route, chain, function done(e) { | ||
self.emit('after', req, res, route, e); | ||
}); | ||
}); | ||
} | ||
self.router.find(req, res, function onRoute(err, route, ctx) { | ||
var r = route ? route.name : null; | ||
if (err) { | ||
if (err.statusCode === 404 && | ||
req.method === 'OPTIONS' && | ||
req.url === '*') { | ||
res.send(200); | ||
self.emit('after', req, res, null); | ||
return; | ||
} | ||
log.trace({ | ||
err: err, | ||
req_id: req.getId() | ||
}, 'router errored out'); | ||
switch (err.name) { | ||
case 'ResourceNotFoundError': | ||
emitRouteError('NotFound', err); | ||
break; | ||
case 'MethodNotAllowedError': | ||
emitRouteError('MethodNotAllowed', | ||
err); | ||
break; | ||
case 'InvalidVersionError': | ||
emitRouteError('VersionNotAllowed', | ||
err); | ||
break; | ||
case 'UnsupportedMediaTypeError': | ||
emitRouteError('UnsupportedMediaType', | ||
err); | ||
break; | ||
default: | ||
emitRouteError(' ', err); | ||
break; | ||
} | ||
} else if (r === true) { | ||
// this probably indicates a preflight request | ||
// at any rate semantic means return 200 | ||
res.send(200); | ||
self.emit('after', req, res, null); | ||
} else if (!r || !self.routes[r]) { | ||
log.trace({ | ||
req_id: req.getId() | ||
}, 'no route found (null route)'); | ||
emitRouteError('NotFound', 404); | ||
} else { | ||
if (log.trace()) { | ||
log.trace({ | ||
req_id: req.getId(), | ||
route: r | ||
}, 'route found'); | ||
} | ||
req.context = req.params = ctx; | ||
req.route = route.spec; | ||
var chain = self.routes[r]; | ||
self._run(req, res, r, chain, function done(e) { | ||
self.emit('after', req, res, r, e); | ||
}); | ||
if (this.before.length > 0) { | ||
this._run(req, res, null, this.before, function (err) { | ||
if (!err) { | ||
routeAndRun(); | ||
} | ||
}); | ||
} else { | ||
routeAndRun(); | ||
} | ||
}; | ||
// We need to check if should run the _pre_ chain first. | ||
if (this.before.length > 0) { | ||
if (log.trace()) | ||
log.trace({req: req}, 'running pre chain'); | ||
this._run(req, res, null, this.before, function (err) { | ||
Server.prototype._route = function _route(req, res, name, cb) { | ||
var self = this; | ||
if (typeof (name) === 'function') { | ||
cb = name; | ||
name = null; | ||
} else { | ||
this.router.get(name, req, function (err, route, ctx) { | ||
if (err) { | ||
log.trace({ | ||
err: err | ||
}, 'pre chain errored out. Done.'); | ||
return (false); | ||
emitRouteError(self, req, res, err); | ||
} else { | ||
cb(route, ctx); | ||
} | ||
return (_route()); | ||
}); | ||
return (false); | ||
} | ||
return (_route()); | ||
this.router.find(req, res, function onRoute(err, route, ctx) { | ||
var r = route ? route.name : null; | ||
if (err) { | ||
if (optionsError(err, req, res)) { | ||
self.emit('after', req, res, err); | ||
} else { | ||
emitRouteError(self, req, res, err); | ||
} | ||
} else if (r === 'preflight') { | ||
res.writeHead(200); | ||
res.end(); | ||
self.emit('after', req, res, null); | ||
} else if (!r || !self.routes[r]) { | ||
err = new ResourceNotFoundError(req.path()); | ||
emitRouteError(self, res, res, err); | ||
} else { | ||
cb(r, ctx); | ||
} | ||
}); | ||
}; | ||
Server.prototype._run = function _run(req, res, route, chain, callback) { | ||
// The goofy checks in next() are to make sure we fire the DTrace | ||
// probes after an error might have been sent, as in a handler | ||
// return next(new Error) is basically shorthand for sending an | ||
// error via res.send(), so we do that before firing the dtrace | ||
// probe (namely so the status codes get updated in the | ||
// response). | ||
// | ||
// Callers can stop the chain from proceding if they do | ||
// return next(false); This is useful for non-errors, but where | ||
// a response was sent and you don't want the chain to keep | ||
// going | ||
Server.prototype._run = function _run(req, res, route, chain, cb) { | ||
var d; | ||
@@ -632,37 +640,44 @@ var i = -1; | ||
function ifError(n) { | ||
function _ifError(err) { | ||
if (err) { | ||
err._restify_next = n; | ||
throw err; | ||
function next(arg) { | ||
var done = false; | ||
if (arg) { | ||
if (arg instanceof Error) { | ||
log.trace({err: arg}, 'next(err=%s)', | ||
(arg.name || 'Error')); | ||
res.send(arg); | ||
done = true; | ||
} else if (typeof (arg) === 'string') { | ||
if (req._rstfy_chained_route) { | ||
var _e = new errors.InternalError(); | ||
log.error({ | ||
err: _e | ||
}, 'Multiple next("chain") calls not ' + | ||
'supported'); | ||
res.send(_e); | ||
return (false); | ||
} | ||
self._route(req, res, arg, function (r, ctx) { | ||
req.context = req.params = ctx; | ||
req.route = r.spec; | ||
var _c = chain.slice(0, i + 1); | ||
function _uniq(fn) { | ||
return (_c.indexOf(fn) === -1); | ||
} | ||
var _routes = self.routes[r.name] || []; | ||
var _chain = _routes.filter(_uniq); | ||
req._rstfy_chained_route = true; | ||
self._run(req, res, r, _chain, cb); | ||
}); | ||
} | ||
} | ||
return (_ifError); | ||
} | ||
function next(err) { | ||
// The goofy checks here are to make sure we fire the DTrace | ||
// probes after an error might have been sent, as in a handler | ||
// return next(new Error) is basically shorthand for sending an | ||
// error via res.send(), so we do that before firing the dtrace | ||
// probe (namely so the status codes get updated in the | ||
// response). | ||
var done = false; | ||
if (err) { | ||
if (log.trace()) | ||
log.trace({err: err}, 'next(err=%s)', | ||
err.name || 'Error'); | ||
res.send(err); | ||
if (arg === false) | ||
done = true; | ||
} | ||
// Callers can stop the chain from proceding if they do | ||
// return next(false); This is useful for non-errors, but where | ||
// a response was sent and you don't want the chain to keep | ||
// going | ||
if (err === false) | ||
done = true; | ||
// Fire DTrace done for the previous handler. | ||
if ((i + 1) > 0 && chain[i]) { | ||
if ((i + 1) > 0 && chain[i] && !chain[i]._skip) { | ||
dtrace._rstfy_probes['handler-done'].fire(function () { | ||
@@ -680,2 +695,5 @@ return ([ | ||
if (!done && chain[++i]) { | ||
if (chain[i]._skip) | ||
return (next()); | ||
if (log.trace()) | ||
@@ -714,3 +732,3 @@ log.trace('running %s', chain[i].name || '?'); | ||
return (callback ? callback(err) : true); | ||
return (cb ? cb(arg) : true); | ||
} | ||
@@ -717,0 +735,0 @@ var n1 = once(next); |
@@ -28,3 +28,3 @@ { | ||
"description": "REST framework", | ||
"version": "2.3.4", | ||
"version": "2.3.5", | ||
"repository": { | ||
@@ -47,3 +47,3 @@ "type": "git", | ||
"backoff": "2.0.0", | ||
"bunyan": "0.18.3", | ||
"bunyan": "0.20.0", | ||
"deep-equal": "0.0.0", | ||
@@ -50,0 +50,0 @@ "formidable": "1.0.11", |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
180056
50
4074
5
+ Addedbunyan@0.20.0(transitive)
+ Addedmv@0.0.5(transitive)
- Removedbunyan@0.18.3(transitive)
- Removedmv@0.0.4(transitive)
Updatedbunyan@0.20.0