Comparing version 8.1.1 to 8.2.0
@@ -0,5 +1,23 @@ | ||
<a name="8.2.0"></a> | ||
## 8.2.0 (2019-03-18) | ||
#### Bug Fixes | ||
* properly handle non-errors thrown in domains (#1757) ([cb2e7177](git://github.com/restify/node-restify.git/commit/cb2e7177)) | ||
* **cpuUsageThrottle:** support breaking change in pidusage module ([7460064f](git://github.com/restify/node-restify.git/commit/7460064f)) | ||
#### Features | ||
* **first:** Handlers that execute ASAP in the req/res lifecycle (#1756) ([8178098d](git://github.com/restify/node-restify.git/commit/8178098d)) | ||
<a name="8.1.1"></a> | ||
### 8.1.1 (2019-03-14) | ||
#### Bug Fixes | ||
* Published NPM package had a bad dependency on `npm` causing new irrelevant packages to get installed | ||
<a name="8.1.0"></a> | ||
@@ -6,0 +24,0 @@ ## 8.1.0 (2019-03-06) |
@@ -58,4 +58,9 @@ # Contributing to Restify | ||
$ git pull origin master # ensure you have the latest changes | ||
$ npx unleash [-p for patch, -m for minor, -M for major] -d # do a dry run to verify | ||
$ npx unleash [-p for patch, -m for minor, -M for major] | ||
$ npx unleash [-p for patch, -m for minor, -M for major] --no-publish -d # do a dry run to verify | ||
$ npx unleash [-p for patch, -m for minor, -M for major] --no-publish | ||
# Unleash doesnt support 2FA, hence we use --no-publish flag here. | ||
# This ensures we have the package.json updated, changelog generated, tag created | ||
# and all the changes into origin | ||
# Next, publish to npm manually and do not forget to provide the 2FA code. | ||
$ npm publish | ||
``` |
@@ -133,3 +133,3 @@ 'use strict'; | ||
// This allows us to monitor lag caused by both the event loop | ||
// and pidusage.stat | ||
// and pidusage | ||
plugin._timeoutDelta = 0; | ||
@@ -141,3 +141,3 @@ plugin._timeoutStart = Date.now(); | ||
function updateReject() { | ||
pidusage.stat(process.pid, function pidusageStat(e, stat) { | ||
pidusage(process.pid, function pidusageStat(e, stat) { | ||
// Requeue an updateReject irrespective of whether or not pidusage | ||
@@ -169,3 +169,3 @@ // encountered an error | ||
// updated the _reject value and how long it actually took. This | ||
// metric accounts for the misbehaviour of pidusage.stat | ||
// metric accounts for the misbehaviour of pidusage | ||
var now = Date.now(); | ||
@@ -172,0 +172,0 @@ plugin._timeoutDelta = |
@@ -120,2 +120,3 @@ // Copyright 2012 Mark Cavage, Inc. All rights reserved. | ||
this.strictNext = !!options.strictNext; | ||
this.firstChain = []; | ||
this.preChain = new Chain({ | ||
@@ -495,2 +496,69 @@ onceNext: this.onceNext, | ||
/** | ||
* Gives you hooks that run before restify touches a request. These hooks | ||
* allow you to do processing early in the request/response life cycle without | ||
* the overhead of the restify framework. You can not yield the event loop in | ||
* this handler. | ||
* | ||
* The function handler accepts two parameters: req, res. If you want restify | ||
* to ignore this request, return false from your handler. Return true or | ||
* undefined to let restify continue handling the request. | ||
* | ||
* When false is returned, restify immediately stops handling the request. This | ||
* means that no further middleware will be executed for any chain and routing | ||
* will not occure. All request/response handling for an incoming request must | ||
* be done inside the first handler if you intend to return false. This | ||
* includes things like closing the response and returning a status code. | ||
* | ||
* The only work restify does for a first handler is to increment the number of | ||
* inflightRequests prior to calling the chain, and decrement that value if the | ||
* handler returns false. Returning anything other than true, false, undefined, | ||
* or null will cause an exception to be thrown. | ||
* | ||
* Since server.first is designed to bypass the restify framework, there are | ||
* naturally trade-offs you make when using this API: | ||
* * Standard restify lifecycle events such as 'after' are not triggered for | ||
* any request that you return false from a handler for | ||
* * Invoking any of the restify req/res APIs from within a first handler is | ||
* unspecified behavior, as the restify framework hasn't built up state for | ||
* the request yet. | ||
* * There are no request timers available at the time that the first chain | ||
* runs. | ||
* * And more! Beware doing anything with restify in these handlers. They are | ||
* designed to give you similar access to the req/res as you would have if | ||
* you were directly using node.js' http module, they are outside of the | ||
* restify framework! | ||
* | ||
* @public | ||
* @memberof Server | ||
* @instance | ||
* @function first | ||
* @param {...Function} handler - Allows you to add handlers that | ||
* run for all requests, *before* restify touches the request. | ||
* This gives you a hook to change request headers and the like if you need to. | ||
* Note that `req.params` will be undefined, as that's filled in *after* | ||
* routing. | ||
* Takes one or more functions. | ||
* @returns {Object} returns self | ||
* @example | ||
* server.first(function(req, res) { | ||
* if(server.inflightRequests() > 100) { | ||
* res.statusCode = 503; | ||
* res.end(); | ||
* return false | ||
* } | ||
* return true; | ||
* }) | ||
*/ | ||
Server.prototype.first = function first() { | ||
var args = Array.prototype.slice.call(arguments); | ||
for (var i = 0; i < args.length; i++) { | ||
assert.func(args[i]); | ||
this.firstChain.push(args[i]); | ||
} | ||
return this; | ||
}; | ||
// eslint-disable-next-line jsdoc/check-param-names | ||
/** | ||
* Allows you to add in handlers that run for all routes. Note that handlers | ||
@@ -812,2 +880,42 @@ * added | ||
// Increment the number of inflight requests prior to calling the firstChain | ||
// handlers. This accomplishes two things. First, it gives earliest an | ||
// accurate count of how many inflight requests there would be including | ||
// this new request. Second, it intentionally winds up the inflight request | ||
// accounting with the implementation of firstChain. Note how we increment | ||
// here, but decrement down inside the for loop below. It's easy to end up | ||
// with race conditions betwen inflight request accounting and inflight | ||
// request load shedding, causing load shedding to reject/allow too many | ||
// requests. The current implementation of firstChain is designed to | ||
// remove those race conditions. By winding these implementations up with | ||
// one another, it makes it clear that moving around the inflight request | ||
// accounting will change the behavior of earliest. | ||
self._inflightRequests++; | ||
// Give the first chain the earliest possible opportunity to process | ||
// this request before we do any work on it. | ||
var firstChain = self.firstChain; | ||
for (var i = 0; i < firstChain.length; i++) { | ||
var handle = firstChain[i](req, res); | ||
// Limit the range of values we will accept as return results of | ||
// first handlers. This helps us maintain forward compatibility by | ||
// ensuring users don't rely on undocumented/unspecified behavior. | ||
assert.ok( | ||
handle === true || | ||
handle === false || | ||
handle === undefined || | ||
handle === null, | ||
'Return value of first[' + | ||
i + | ||
'] must be: ' + | ||
'boolean, undefined, or null' | ||
); | ||
// If the first handler returns false, stop handling the request | ||
// immediately. | ||
if (handle === false) { | ||
self._inflightRequests--; | ||
return; | ||
} | ||
} | ||
this.emit('request', req, res); | ||
@@ -817,2 +925,3 @@ | ||
if (this.socketio && /^\/socket\.io.*/.test(req.url)) { | ||
self._inflightRequests--; | ||
return; | ||
@@ -824,5 +933,2 @@ } | ||
// increment number of requests | ||
self._inflightRequests++; | ||
// Run in domain to catch async errors | ||
@@ -1311,3 +1417,3 @@ // It has significant negative performance impact | ||
self._emitErrorEvents(req, res, null, err, function emitError(emitErr) { | ||
self._emitErrorEvents(req, res, null, err, function emitError() { | ||
// Prevent double handling | ||
@@ -1318,4 +1424,4 @@ if (res._sent) { | ||
// Expose only knonw errors | ||
if (_.isNumber(err.statusCode)) { | ||
// only automatically send errors that are known (e.g., restify-errors) | ||
if (err instanceof Error && _.isNumber(err.statusCode)) { | ||
res.send(err); | ||
@@ -1325,3 +1431,8 @@ return; | ||
res.send(new errors.InternalError(emitErr || err)); | ||
// if the thrown exception is not really an Error object, e.g., | ||
// "throw 'foo';" | ||
// try to do best effort here to pass on that value by casting it to a | ||
// string. This should work even for falsy values like 0, false, null, | ||
// or undefined. | ||
res.send(new errors.InternalError(String(err))); | ||
}); | ||
@@ -1396,6 +1507,5 @@ }; | ||
// eslint-disable-next-line handle-callback-err | ||
function onResult(nullErr, results) { | ||
// vasync will never return error here. callback with the original | ||
// error to pass it on. | ||
return cb(err); | ||
function onResult(__, results) { | ||
// vasync will never return error here since we throw them away. | ||
return cb(); | ||
} | ||
@@ -1402,0 +1512,0 @@ ); |
@@ -69,3 +69,3 @@ { | ||
"name": "restify", | ||
"homepage": "http://restifyjs.com", | ||
"homepage": "http://restify.com", | ||
"description": "REST framework", | ||
@@ -78,3 +78,3 @@ "keywords": [ | ||
], | ||
"version": "8.1.1", | ||
"version": "8.2.0", | ||
"repository": { | ||
@@ -126,3 +126,3 @@ "type": "git", | ||
"autocannon": "^2.2.0", | ||
"autocannon-compare": "^0.3.0", | ||
"autocannon-compare": "^0.4.0", | ||
"chai": "^4.1.2", | ||
@@ -129,0 +129,0 @@ "cover": "^0.2.9", |
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
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
No website
QualityPackage does not have a website.
Found 1 instance in 1 package
354893
8744
0
78