Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

restify

Package Overview
Dependencies
Maintainers
1
Versions
184
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

restify - npm Package Compare versions

Comparing version 2.1.1 to 2.2.0

11

CHANGES.md
# restify Changelog
## 2.2.2 (not yet released)
## 2.2.1 (not yet released)
## 2.2.0
- GH-316 drop `clone`, and just shallow copy (Trent Mick)
- GH-284 preflight requests not working without access-control-request-headers
- GH-283 versioned routes should use maximum match, not first (Colin O'Brien)
- dtrace probes for restify clients
- node-dtrace-provider@0.2.8
- backoff@2.0.0 and necessary changes
## 2.1.1

@@ -6,0 +15,0 @@

89

lib/clients/http_client.js

@@ -19,5 +19,5 @@ // Copyright 2012 Mark Cavage, Inc. All rights reserved.

var once = require('once');
var semver = require('semver');
var uuid = require('node-uuid');
var dtrace = require('../dtrace');
var errors = require('../errors');

@@ -36,2 +36,27 @@

function cloneRetryOptions(options, defaults) {
if (options === false) {
return ({
minTimeout: 1,
maxTimeout: 2,
retries: 1
});
}
assert.optionalObject(options, 'options.retry');
var r = options || {};
assert.optionalNumber(r.minTimeout, 'options.retry.minTimeout');
assert.optionalNumber(r.maxTimeout, 'options.retry.maxTimeout');
assert.optionalNumber(r.retries, 'options.retry.retries');
assert.optionalObject(defaults, 'defaults');
defaults = defaults || {};
return ({
minTimeout: r.minTimeout || defaults.minTimeout || 1000,
maxTimeout: r.maxTimeout || defaults.maxTimeout || Infinity,
retries: r.retries || defaults.retries || 4
});
}
function defaultUserAgent() {

@@ -53,2 +78,3 @@ var UA = 'restify/' + VERSION +

this.message = 'connect timeout after ' + ms + 'ms';
this.name = 'ConnectTimeoutError';
}

@@ -65,2 +91,3 @@ util.inherits(ConnectTimeoutError, Error);

var id = dtrace.nextId();
var log = opts.log;

@@ -80,8 +107,24 @@ var proto = opts.protocol === 'https:' ? https : http;

cb(new ConnectTimeoutError(opts.connectTimeout), req);
var err = new ConnectTimeoutError(opts.connectTimeout);
dtrace._rstfy_probes['client-error'].fire(function () {
return ([id, err.toString()]);
});
cb(err, req);
}, opts.connectTimeout);
}
dtrace._rstfy_probes['client-request'].fire(function () {
return ([
opts.method,
opts.path,
opts.headers,
id
]);
});
var req = proto.request(opts, function onResponse(res) {
clearTimeout(timer);
dtrace._rstfy_probes['client-response'].fire(function () {
return ([ id, res.statusCode, res.headers ]);
});
log.trace({client_res: res}, 'Response received');

@@ -102,2 +145,5 @@

req.on('error', function onError(err) {
dtrace._rstfy_probes['client-error'].fire(function () {
return ([id, (err || {}).toString()]);
});
log.trace({err: err}, 'Request failed');

@@ -152,6 +198,3 @@ clearTimeout(timer);

this.name = options.name || 'HttpClient';
this.retry = (options.retry !== false) ?
(options.retry || { retries: 3 }) : false;
this.retry = cloneRetryOptions(options.retry);
this.signRequest = options.signRequest || false;

@@ -295,28 +338,16 @@ this.socketPath = options.socketPath || false;

var self = this;
cb = once(cb);
// Make one request, then kick off the next call; note that
// node-backoff always imposes an initial time delay before
// starting, which we don't want.
rawRequest(opts, function _callback(err, req) {
if (!err || opts.retry === false) {
cb(err, req);
return;
}
var call;
var retry = cloneRetryOptions(opts.retry);
var retry = backoff.call(rawRequest, opts, cb);
retry.setStrategy(new backoff.ExponentialStrategy({
initialDelay: self.retry.minTimeout || 1000,
maxDelay: self.retry.maxTimeout || Infinity
}));
call = backoff.call(rawRequest, opts, cb);
call.setStrategy(new backoff.ExponentialStrategy({
initialDelay: retry.minTimeout,
maxDelay: retry.maxTimeout
}));
call.failAfter(retry.retries);
call.on('backoff', this.emit.bind(this, 'attempt'));
if (typeof (opts.retry.retries) === 'number') {
if (opts.retry.retries !== Infinity)
retry.failAfter(opts.retry.retries);
} else {
retry.failAfter(4);
}
retry.on('backoff', self.emit.bind(self, 'attempt'));
});
call.start();
};

@@ -323,0 +354,0 @@

// Copyright 2012 Mark Cavage, Inc. All rights reserved.
var assert = require('assert-plus');
var dtrace = require('dtrace-provider');

@@ -12,15 +11,26 @@

var ID = 0;
var MAX_INT = Math.pow(2, 32) - 1;
var PROBES = {
// server_name, route_name, fd, method, url, headers (json)
'route-start': ['char *', 'char *', 'int', 'char *', 'char *',
'char *'],
// server_name, route_name, id, method, url, headers (json)
'route-start': ['char *', 'char *', 'int', 'char *', 'char *', 'json'],
// server_name, route_name, handler_name, fd
// server_name, route_name, handler_name, id
'handler-start': ['char *', 'char *', 'char *', 'int'],
// server_name, route_name, handler_name, fd
// server_name, route_name, handler_name, id
'handler-done': ['char *', 'char *', 'char *', 'int'],
// server_name, route_name, fd, statusCode, headers (json)
'route-done': ['char *', 'char *', 'int', 'int', 'char *']
// server_name, route_name, id, statusCode, headers (json)
'route-done': ['char *', 'char *', 'int', 'int', 'json'],
// Client probes
// method, url, headers, id
'client-request': ['char *', 'char *', 'json', 'int'],
// id, statusCode, headers
'client-response': ['int', 'int', 'json'],
// id, Error.toString()
'client-error': ['id', 'char *']
};

@@ -48,2 +58,9 @@ var PROVIDER;

PROVIDER.enable();
PROVIDER.nextId = function nextId() {
if (++ID >= MAX_INT)
ID = 1;
return (ID);
};
}

@@ -50,0 +67,0 @@

@@ -10,2 +10,5 @@ // Copyright 2012 Mark Cavage, Inc. All rights reserved.

var shallowCopy = require('./utils').shallowCopy;
function createClient(options) {

@@ -15,3 +18,2 @@ var assert = require('assert-plus');

var clients = require('./clients');
var clone = require('clone');

@@ -21,7 +23,7 @@ assert.object(options, 'options');

var client;
var opts = clone(options);
var opts = shallowCopy(options);
opts.agent = options.agent;
opts.name = opts.name || 'restify';
opts.type = opts.type || 'application/octet-stream';
opts.log = options.log || bunyan.createLogger(opts.name);
opts.log = opts.log || bunyan.createLogger(opts.name);

@@ -48,4 +50,3 @@ switch (opts.type) {

function createJsonClient(options) {
var clone = require('clone');
options = options ? clone(options) : {};
options = options ? shallowCopy(options) : {};
options.type = 'json';

@@ -57,4 +58,3 @@ return (createClient(options));

function createStringClient(options) {
var clone = require('clone');
options = options ? clone(options) : {};
options = options ? shallowCopy(options) : {};
options.type = 'string';

@@ -66,4 +66,3 @@ return (createClient(options));

function createHttpClient(options) {
var clone = require('clone');
options = options ? clone(options) : {};
options = options ? shallowCopy(options) : {};
options.type = 'http';

@@ -76,3 +75,2 @@ return (createClient(options));

var bunyan = require('./bunyan_helper');
var clone = require('clone');
var InternalError = require('./errors').InternalError;

@@ -82,11 +80,8 @@ var Router = require('./router');

var opts = clone(options || {});
var opts = shallowCopy(options || {});
var server;
opts.name = opts.name || 'restify';
// clone can't clone something with prototypes so we need to
// manually set opts.log and opts.router to the right objects:
opts.log =
opts.log ? options.log : bunyan.createLogger(opts.name);
opts.router = opts.router ? options.router : new Router(opts);
opts.log = opts.log || bunyan.createLogger(opts.name);
opts.router = opts.router || new Router(opts);

@@ -93,0 +88,0 @@ server = new Server(opts);

// Copyright 2012 Mark Cavage, Inc. All rights reserved.
var assert = require('assert-plus');
var clone = require('clone');
var shallowCopy = require('../utils').shallowCopy;
///--- API

@@ -16,3 +17,3 @@

if (options.properties) {
props = clone(options.properties);
props = shallowCopy(options.properties);
} else {

@@ -19,0 +20,0 @@ props = {};

@@ -8,6 +8,6 @@ // Copyright 2012 Mark Cavage, Inc. All rights reserved.

var assert = require('assert-plus');
var clone = require('clone');
var LRU = require('lru-cache');
var semver = require('semver');
var shallowCopy = require('./utils').shallowCopy;
var errors = require('./errors');

@@ -42,2 +42,11 @@

function createCachedRoute(o, path, version, route) {
if (!o.hasOwnProperty(path))
o[path] = {};
if (!o[path].hasOwnProperty(version))
o[path][version] = route;
}
function matchContentType(type1, type2) {

@@ -183,8 +192,8 @@ var matches = true;

this.version = options.version || [];
if (!Array.isArray(this.version))
this.version = [this.version];
assert.arrayOfString(this.version, 'options.version');
this.versions = options.versions || options.version || [];
if (!Array.isArray(this.versions))
this.versions = [this.versions];
assert.arrayOfString(this.versions, 'options.versions');
this.version.forEach(function (v) {
this.versions.forEach(function (v) {
if (semver.valid(v))

@@ -195,3 +204,3 @@ return (true);

});
this.version.sort();
this.versions.sort();

@@ -214,3 +223,3 @@ }

var type = options.contentType || self.contentType;
var version = options.version || self.version;
var versions = options.versions || options.version || self.versions;

@@ -221,5 +230,5 @@ if (!Array.isArray(type))

if (!Array.isArray(version))
version = [version];
version.sort();
if (!Array.isArray(versions))
versions = [versions];
versions.sort();

@@ -241,3 +250,3 @@ exists = routes.some(function (r) {

type: type,
version: version
versions: versions
};

@@ -258,3 +267,3 @@ routes.push(route);

route.type,
route.version);
route.versions);

@@ -292,2 +301,4 @@ return (route.name);

Router.prototype.find = function find(req, res, callback) {
var candidates = {};
var candidateKeys = [];
var ct = req.headers['content-type'] || DEF_CT;

@@ -303,3 +314,3 @@ var cacheKey = req.method + req.url + req.version() + ct;

if ((cacheVal = this.cache.get(cacheKey))) {
callback(null, cacheVal.name, clone(cacheVal.params));
callback(null, cacheVal.name, shallowCopy(cacheVal.params));
return;

@@ -323,2 +334,3 @@ }

switch (req.method) {
case 'PATCH':
case 'POST':

@@ -341,12 +353,36 @@ case 'PUT':

if (routes[i].version.length === 0 ||
req.version() === '*' ||
(ver = maxSatisfying(routes[i].version,
req.version()) || false)) {
// GH-283: we want to find the latest version for a given route,
// not the first one. However, if neither the client nor
// server specified any version, we're done, because neither
// cared
if (routes[i].versions.length === 0 && req.version() === '*') {
r = routes[i];
break;
}
if (routes[i].versions.length > 0) {
candidates[routes[i].versions] = routes[i];
candidateKeys.push(routes[i].versions);
}
}
//
if (!r) {
candidateKeys.forEach(function (k) {
var v = semver.maxSatisfying(k, req.version());
if (v && (!ver || semver.gt(v, ver.version))) {
ver = {
version: v,
key: k
};
}
});
if (ver && ver.key) {
r = candidates[ver.key.toString()];
} else {
if (candidateKeys.length > 0)
ver = false;
}
}
// In order, we check if the route exists, in which case, we're good.

@@ -359,4 +395,2 @@ // Otherwise we look to see if ver was set to false; that would tell us

// to handle this having been a preflight request.
//
if (params && r) {

@@ -368,3 +402,3 @@ cacheVal = {

this.cache.set(cacheKey, cacheVal);
callback(null, r.name, clone(params));
callback(null, r.name, shallowCopy(params));
return;

@@ -378,3 +412,6 @@ }

if (ver === false) {
callback(new InvalidVersionError(req.getVersion()));
callback(new InvalidVersionError('%s is not supported by %s %s',
req.version() || '?',
req.method,
req.path()));
return;

@@ -403,2 +440,5 @@ }

(headers || '').split(/\s*,\s*/).forEach(function (h) {
if (!h)
return;
h = h.toLowerCase();

@@ -405,0 +445,0 @@ ok = ALLOW_HEADERS.indexOf(h) !== -1 && ok;

@@ -11,3 +11,2 @@ // Copyright 2012 Mark Cavage, Inc. All rights reserved.

var assert = require('assert-plus');
var clone = require('clone');
var mime = require('mime');

@@ -20,2 +19,3 @@ var once = require('once');

var formatters = require('./formatters');
var shallowCopy = require('./utils').shallowCopy;

@@ -143,3 +143,3 @@ // Ensure these are loaded

this.secure = false;
this.version = options.version || null;
this.versions = options.versions || options.version || [];

@@ -297,3 +297,3 @@ var fmt = mergeFormatters(options.formatters);

} else if (typeof (opts) === 'object') {
opts = clone(opts);
opts = shallowCopy(opts);
} else {

@@ -321,10 +321,10 @@ throw new TypeError('path (string) required');

opts.method = method.toUpperCase();
opts.version = opts.version || self.version;
if (!Array.isArray(opts.version))
opts.version = [opts.version];
opts.versions = opts.versions || opts.version || self.versions;
if (!Array.isArray(opts.versions))
opts.versions = [opts.versions];
if (!opts.name) {
opts.name = method + '-' + (opts.path || opts.url);
if (opts.version) {
opts.name += '-' + opts.version.join('--');
if (opts.versions.length > 0) {
opts.name += '-' + opts.versions.join('--');
}

@@ -576,2 +576,3 @@ }

var i = -1;
var id = dtrace.nextId();
var log = this.log;

@@ -620,3 +621,3 @@ var self = this;

chain[i].name || ('handler-' + i),
req.connection.fd
id
]);

@@ -636,3 +637,3 @@ });

chain[i].name || ('handler-' + i),
req.connection.fd
id
]);

@@ -650,5 +651,5 @@ });

route !== null ? route : 'pre',
req.connection.fd,
id,
res.statusCode || 200,
JSON.stringify(res.headers())
res.headers()
]);

@@ -672,6 +673,6 @@ });

route !== null ? route : 'pre',
req.connection.fd,
id,
req.method,
req.href(),
JSON.stringify(req.headers)
req.headers
]);

@@ -703,5 +704,5 @@ });

res.serverName = this.name;
res.version = this.router.version[this.router.version.length - 1];
res.version = this.router.versions[this.router.versions.length - 1];
// HTTP METHODS set for the current route:
res.methods = this.router.reverse[Object.keys(this.router.reverse)[0]];
};

@@ -57,3 +57,18 @@ // Copyright 2012 Mark Cavage, Inc. All rights reserved.

/**
* Return a shallow copy of the given object;
*/
function shallowCopy(obj) {
if (!obj) {
return (obj);
}
var copy = {};
Object.keys(obj).forEach(function (k) {
copy[k] = obj[k];
});
return (copy);
}
///--- Exports

@@ -63,3 +78,4 @@

parseQuality: parseQuality,
sanitizePath: sanitizePath
};
sanitizePath: sanitizePath,
shallowCopy: shallowCopy
};

@@ -14,2 +14,3 @@ {

"Trent Mick",
"Colin O'Brien",
"Falco Nogatz",

@@ -27,3 +28,3 @@ "Pedro Palazón",

"description": "REST framework",
"version": "2.1.1",
"version": "2.2.0",
"repository": {

@@ -45,6 +46,5 @@ "type": "git",

"assert-plus": "0.1.2",
"backoff": "1.2.0",
"backoff": "2.0.0",
"bunyan": "0.18.2",
"clone": "0.1.5",
"dtrace-provider": "0.2.7",
"dtrace-provider": "0.2.8",
"formidable": "1.0.11",

@@ -51,0 +51,0 @@ "http-signature": "0.9.10",

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc