diff --git a/bin/report-latency b/bin/report-latency
index 896834f4d..21dbc9255 100755
--- a/bin/report-latency
+++ b/bin/report-latency
@@ -10,214 +10,210 @@ var sprintf = require('util').format;
var nopt = require('nopt');
-
-
///--- Globals
var BUCKETS = {};
var REQUEST_IDS = {};
var OPTS = {
- 'average': Boolean,
- 'help': Boolean,
- 'end': Date,
- 'max-latency': Number,
- 'max-requests': Number,
- 'output': String,
- 'percentile': [Number, Array],
- 'period': Number,
- 'requests': Boolean,
- 'start': Date
+ 'average': Boolean,
+ 'help': Boolean,
+ 'end': Date,
+ 'max-latency': Number,
+ 'max-requests': Number,
+ 'output': String,
+ 'percentile': [Number, Array],
+ 'period': Number,
+ 'requests': Boolean,
+ 'start': Date
};
var SHORT_OPTS = {
- 'a': ['--average'],
- 'h': ['--help'],
- 'i': ['--period'],
- 'e': ['--end'],
- 'l': ['--max-latency'],
- 'n': ['--max-requests'],
- 'o': ['--output'],
- 'p': ['--percentile'],
- 'r': ['--requests'],
- 's': ['--start']
+ 'a': ['--average'],
+ 'h': ['--help'],
+ 'i': ['--period'],
+ 'e': ['--end'],
+ 'l': ['--max-latency'],
+ 'n': ['--max-requests'],
+ 'o': ['--output'],
+ 'p': ['--percentile'],
+ 'r': ['--requests'],
+ 's': ['--start']
};
-
-
///--- Functions
function percentile(p, vals) {
- p = parseInt(p, 10);
- return vals[(Math.round(((p/100) * vals.length) + 1/2) - 1)].latency;
+ p = parseInt(p, 10);
+ return vals[(Math.round(((p / 100) * vals.length) + 1 / 2) - 1)].latency;
}
function report(buckets, output) {
- Object.keys(buckets).sort(function (a, b) {
- return parseInt(a, 10) - parseInt(b, 10);
- }).forEach(function (k) {
- var avg = 0;
- var perc = [];
- var req = buckets[k].length;
- var sum = 0;
- var t = Math.round(buckets[k]._time);
-
- buckets[k] = buckets[k].sort(function (a, b) {
- return a.latency - b.latency;
+ Object.keys(buckets).sort(function (a, b) {
+ return parseInt(a, 10) - parseInt(b, 10);
+ }).forEach(function (k) {
+ var avg = 0;
+ var perc = [];
+ var req = buckets[k].length;
+ var sum = 0;
+ var t = Math.round(buckets[k]._time);
+
+ buckets[k] = buckets[k].sort(function (a, b) {
+ return a.latency - b.latency;
+ });
+
+ buckets[k].forEach(function (v) {
+ sum += v.latency;
+ });
+
+ if (sum > 0 && req > 0) {
+ if (output.average)
+ output.average.push([t, Math.round(sum / req)]);
+ if (output.requests)
+ output.requests.push([t, buckets[k].length]);
+ Object.keys(output.percentile).forEach(function (p) {
+ var _p = percentile(p, buckets[k]);
+ output.percentile[p].push([t, _p]);
});
-
- buckets[k].forEach(function (v) {
- sum += v.latency;
- });
-
- if (sum > 0 && req > 0) {
- if (output.average)
- output.average.push([t, Math.round(sum/req)]);
- if (output.requests)
- output.requests.push([t, buckets[k].length]);
- Object.keys(output.percentile).forEach(function (p) {
- var _p = percentile(p, buckets[k]);
- output.percentile[p].push([t, _p]);
- });
- }
+ }
});
- return output;
+ return output;
}
function usage(code, message) {
- var str = '';
- Object.keys(SHORT_OPTS).forEach(function(k) {
- if (!Array.isArray(SHORT_OPTS[k]))
- return;
-
- var opt = SHORT_OPTS[k][0].replace('--', '');
- var type = OPTS[opt].name || 'string';
- if (type && type === 'boolean')
- type = '';
- type = type.toLowerCase();
-
- str += ' [--' + opt + ' ' + type + ']';
- });
- str += ' [file ...]';
-
- if (message)
- console.error(message);
-
- console.error('usage: ' + path.basename(process.argv[1]) + str);
- process.exit(code);
+ var str = '';
+ Object.keys(SHORT_OPTS).forEach(function (k) {
+ if (!Array.isArray(SHORT_OPTS[k]))
+ return;
+
+ var opt = SHORT_OPTS[k][0].replace('--', '');
+ var type = OPTS[opt].name || 'string';
+ if (type && type === 'boolean')
+ type = '';
+ type = type.toLowerCase();
+
+ str += ' [--' + opt + ' ' + type + ']';
+ });
+ str += ' [file ...]';
+
+ if (message)
+ console.error(message);
+
+ console.error('usage: ' + path.basename(process.argv[1]) + str);
+ process.exit(code);
}
-
///--- Mainline
var parsed;
try {
- parsed = nopt(OPTS, SHORT_OPTS, process.argv, 2);
+ parsed = nopt(OPTS, SHORT_OPTS, process.argv, 2);
} catch (e) {
- usage(1, e.toString());
+ usage(1, e.toString());
}
if (parsed.help)
- usage(0);
+ usage(0);
if (!parsed.average && !parsed.percentile)
- usage(1, '--average or --percentile required');
+ usage(1, '--average or --percentile required');
if (parsed.argv.remain.length < 1)
- usage(1, 'log file required');
+ usage(1, 'log file required');
var config = {
- average: parsed.average || false,
- maxLatency: parsed['max-latency'] || 1000,
- maxRequests: parsed['max-requests'] || 10000,
- percentile: parsed.percentile || [],
- period: parsed.period || 60,
- requests: parsed.requests || false,
- start: parsed.start ? (parsed.start.getTime() / 1000) : 0,
- end: parsed.end ? (parsed.end.getTime() / 1000) : Number.MAX_VALUE
+ average: parsed.average || false,
+ maxLatency: parsed['max-latency'] || 1000,
+ maxRequests: parsed['max-requests'] || 10000,
+ percentile: parsed.percentile || [],
+ period: parsed.period || 60,
+ requests: parsed.requests || false,
+ start: parsed.start ? (parsed.start.getTime() / 1000) : 0,
+ end: parsed.end ? (parsed.end.getTime() / 1000) : Number.MAX_VALUE
};
var buckets = {};
var done = 0;
parsed.argv.remain.forEach(function (f) {
- var stream = readline.createInterface({
- input: fs.createReadStream(f),
- output: null
- })
- stream.on('line', function (l) {
- var record;
- var t = -1;
-
- try {
- record = JSON.parse(l);
- } catch (e) {}
-
- if (!record)
- return;
-
- var t = -1;
- if (record.time)
- t = (new Date(record.time).getTime() / 1000);
-
- if (record._audit !== true ||
- REQUEST_IDS[record.req_id] ||
- t < config.start ||
- t > config.end) {
-
- console.error('Skipping %s', l);
- }
-
- REQUEST_IDS[record.req_id] = true;
- record.time = t;
-
- var b = Math.round(record.time / config.period) + '';
- if (!buckets[b])
- buckets[b] = [];
-
- buckets[b].push(record);
- buckets[b]._time = record.time // good enough
- });
+ var stream = readline.createInterface({
+ input: fs.createReadStream(f),
+ output: null
+ })
+ stream.on('line', function (l) {
+ var record;
+ var t = -1;
+
+ try {
+ record = JSON.parse(l);
+ } catch (e) {
+ }
+
+ if (!record)
+ return;
+
+ var t = -1;
+ if (record.time)
+ t = (new Date(record.time).getTime() / 1000);
+
+ if (record._audit !== true ||
+ REQUEST_IDS[record.req_id] ||
+ t < config.start ||
+ t > config.end) {
+
+ console.error('Skipping %s', l);
+ }
+
+ REQUEST_IDS[record.req_id] = true;
+ record.time = t;
+
+ var b = Math.round(record.time / config.period) + '';
+ if (!buckets[b])
+ buckets[b] = [];
+
+ buckets[b].push(record);
+ buckets[b]._time = record.time // good enough
+ });
+
+ stream.on('end', function () {
+ if (++done === parsed.argv.remain.length) {
+ console.error('Generating report...');
+
+ var output = {
+ average: config.average ? [] : false,
+ requests: config.requests ? [] : false,
+ percentile: {}
+ };
+ config.percentile.forEach(function (p) {
+ output.percentile[p] = [];
+ });
+
+ output = report(buckets, output);
+ var finalOutput = [];
+ if (output.average) {
+ finalOutput.push({
+ name: 'avg',
+ values: output.average
+ });
+ }
+ if (output.requests) {
+ finalOutput.push({
+ name: 'n',
+ values: output.requests
+ });
+ }
+ Object.keys(output.percentile).forEach(function (k) {
+ finalOutput.push({
+ name: 'p' + k,
+ values: output.percentile[k]
+ });
+ });
- stream.on('end', function () {
- if (++done === parsed.argv.remain.length) {
- console.error('Generating report...');
-
- var output = {
- average: config.average ? [] : false,
- requests: config.requests ? [] : false,
- percentile: {}
- };
- config.percentile.forEach(function (p) {
- output.percentile[p] = [];
- });
-
- output = report(buckets, output);
- var finalOutput = [];
- if (output.average) {
- finalOutput.push({
- name: 'avg',
- values: output.average
- });
- }
- if (output.requests) {
- finalOutput.push({
- name: 'n',
- values: output.requests
- });
- }
- Object.keys(output.percentile).forEach(function (k) {
- finalOutput.push({
- name: 'p' + k,
- values: output.percentile[k]
- });
- });
-
- console.log(JSON.stringify(finalOutput));
- }
- });
+ console.log(JSON.stringify(finalOutput));
+ }
+ });
});
diff --git a/examples/CORS/cors.js b/examples/CORS/cors.js
index c88b2ac7e..bc2264513 100644
--- a/examples/CORS/cors.js
+++ b/examples/CORS/cors.js
@@ -4,8 +4,8 @@ var srv = restify.createServer();
srv.use(restify.CORS());
function foo(req, res, next) {
- res.send(204);
- next();
+ res.send(204);
+ next();
}
srv.put('/foo', foo);
diff --git a/examples/bench/bench.js b/examples/bench/bench.js
index b0af25f0c..dc0e28968 100644
--- a/examples/bench/bench.js
+++ b/examples/bench/bench.js
@@ -2,10 +2,10 @@ var server = require('../../lib').createServer();
//var server = require('express')();
server.get('/echo/:name', function (req, res, next) {
- res.setHeader('content-type', 'text/plain');
- res.send(200, req.params.name);
+ res.setHeader('content-type', 'text/plain');
+ res.send(200, req.params.name);
});
server.listen(8080, function () {
- console.log('ready');
+ console.log('ready');
});
\ No newline at end of file
diff --git a/examples/dtrace/demo.js b/examples/dtrace/demo.js
index 09dea0b44..efb58e5a8 100644
--- a/examples/dtrace/demo.js
+++ b/examples/dtrace/demo.js
@@ -71,53 +71,51 @@ var restify = require('../../lib');
var Logger = require('bunyan');
-
///--- Globals
var NAME = 'exampleapp';
-
///--- Mainline
var log = new Logger({
- name: NAME,
- level: 'trace',
- service: NAME,
- serializers: restify.bunyan.serializers
+ name: NAME,
+ level: 'trace',
+ service: NAME,
+ serializers: restify.bunyan.serializers
});
var server = restify.createServer({
- name: NAME,
- Logger: log,
- formatters: {
- 'application/foo': function(req, res, body) {
- if (body instanceof Error) {
- body = body.stack;
- } else if (Buffer.isBuffer(body)) {
- body = body.toString('base64');
- } else {
- switch (typeof(body)) {
- case 'boolean':
- case 'number':
- case 'string':
- body = body.toString();
- break;
-
- case 'undefined':
- body = '';
- break;
-
- default:
- body = body === null ? '' :
- JSON.stringify(body);
- break;
- }
-
- }
- return body;
+ name: NAME,
+ Logger: log,
+ formatters: {
+ 'application/foo': function (req, res, body) {
+ if (body instanceof Error) {
+ body = body.stack;
+ } else if (Buffer.isBuffer(body)) {
+ body = body.toString('base64');
+ } else {
+ switch (typeof(body)) {
+ case 'boolean':
+ case 'number':
+ case 'string':
+ body = body.toString();
+ break;
+
+ case 'undefined':
+ body = '';
+ break;
+
+ default:
+ body = body === null ? '' :
+ JSON.stringify(body);
+ break;
}
+
+ }
+ return body;
}
+ }
});
server.use(restify.acceptParser(server.acceptable));
@@ -127,50 +125,52 @@ server.use(restify.queryParser());
server.use(restify.urlEncodedBodyParser());
server.use(function slowHandler(req, res, next) {
- setTimeout(function() { next(); }, 250);
+ setTimeout(function () {
+ next();
+ }, 250);
});
server.get({url: '/foo/:id', name: 'GetFoo'}, function (req, res, next) {
- next();
+ next();
}, function sendResult(req, res, next) {
- res.send({
- hello: req.params.id
- });
- next();
+ res.send({
+ hello: req.params.id
+ });
+ next();
});
server.head('/foo/:id', function (req, res, next) {
- res.send({
- hello: req.params.id
- });
- next();
+ res.send({
+ hello: req.params.id
+ });
+ next();
});
server.put('/foo/:id', function (req, res, next) {
- res.send({
- hello: req.params.id
- });
- next();
+ res.send({
+ hello: req.params.id
+ });
+ next();
});
server.post('/foo/:id', function (req, res, next) {
- res.json(201, req.params);
- next();
+ res.json(201, req.params);
+ next();
});
server.del('/foo/:id', function (req, res, next) {
- res.send(204);
- next();
+ res.send(204);
+ next();
});
-server.on('after', function(req, res, name) {
- req.log.info('%s just finished: %d.', name, res.code);
+server.on('after', function (req, res, name) {
+ req.log.info('%s just finished: %d.', name, res.code);
});
-server.on('NotFound', function(req, res) {
- res.send(404, req.url + ' was not found');
+server.on('NotFound', function (req, res) {
+ res.send(404, req.url + ' was not found');
});
-server.listen(9080, function() {
- log.info('listening: %s', server.url);
+server.listen(9080, function () {
+ log.info('listening: %s', server.url);
});
diff --git a/examples/dtrace/hello.js b/examples/dtrace/hello.js
index 7773d59bb..c6ead0ef9 100644
--- a/examples/dtrace/hello.js
+++ b/examples/dtrace/hello.js
@@ -1,7 +1,7 @@
var restify = require('../lib');
var server = restify.createServer({
- name: 'helloworld'
+ name: 'helloworld'
});
server.use(restify.acceptParser(server.acceptable));
@@ -11,21 +11,21 @@ server.use(restify.queryParser());
server.use(restify.urlEncodedBodyParser());
server.use(function slowHandler(req, res, next) {
- setTimeout(function() {
- next();
- }, 250);
+ setTimeout(function () {
+ next();
+ }, 250);
});
server.get({
- path: '/hello/:name',
- name: 'GetFoo'
+ path: '/hello/:name',
+ name: 'GetFoo'
}, function respond(req, res, next) {
- res.send({
- hello: req.params.name
- });
- next();
+ res.send({
+ hello: req.params.name
+ });
+ next();
});
-server.listen(8080, function() {
- console.log('listening: %s', server.url);
+server.listen(8080, function () {
+ console.log('listening: %s', server.url);
});
\ No newline at end of file
diff --git a/examples/jsonp/jsonp.js b/examples/jsonp/jsonp.js
index 2ffb748e9..547b68344 100644
--- a/examples/jsonp/jsonp.js
+++ b/examples/jsonp/jsonp.js
@@ -4,10 +4,10 @@ var srv = restify.createServer();
srv.use(restify.queryParser());
srv.use(restify.jsonp());
srv.get('/', function (req, res, next) {
- res.send({hello: 'world'});
- next();
+ res.send({hello: 'world'});
+ next();
});
srv.listen(8080, function () {
- console.log('ready on %s', srv.url);
+ console.log('ready on %s', srv.url);
});
\ No newline at end of file
diff --git a/examples/sockio/sockio.js b/examples/sockio/sockio.js
index d637c22ef..21f67c46e 100644
--- a/examples/sockio/sockio.js
+++ b/examples/sockio/sockio.js
@@ -6,28 +6,26 @@ var socketio = require('socket.io');
var restify = require('../lib');
-
///--- Globals
var IP = (function () {
- var nics = os.networkInterfaces();
- var keys = Object.keys(nics).filter(function (k) {
- return (nics[k].some(function (n) {
- return (!n.internal);
- }));
- });
- return (nics[keys.pop()].pop().address);
+ var nics = os.networkInterfaces();
+ var keys = Object.keys(nics).filter(function (k) {
+ return (nics[k].some(function (n) {
+ return (!n.internal);
+ }));
+ });
+ return (nics[keys.pop()].pop().address);
})();
var HTML = '\n' +
- '';
-
+ '';
///--- Mainline
@@ -36,22 +34,22 @@ var server = restify.createServer();
var io = socketio.listen(server);
server.get('/', function indexHTML(req, res, next) {
- res.setHeader('Content-Type', 'text/html');
- res.setHeader('Content-Length', Buffer.byteLength(HTML));
- res.writeHead(200);
- res.write(HTML);
- res.end();
- next();
+ res.setHeader('Content-Type', 'text/html');
+ res.setHeader('Content-Length', Buffer.byteLength(HTML));
+ res.writeHead(200);
+ res.write(HTML);
+ res.end();
+ next();
});
io.sockets.on('connection', function (socket) {
- socket.emit('news', { hello: 'world' });
- socket.on('my other event', function (data) {
- console.log(data);
- });
+ socket.emit('news', { hello: 'world' });
+ socket.on('my other event', function (data) {
+ console.log(data);
+ });
});
server.listen(8080, IP, function () {
- console.log('socket.io server listening at %s', server.url);
+ console.log('socket.io server listening at %s', server.url);
});
diff --git a/examples/spdy/spdy.js b/examples/spdy/spdy.js
index c56b3361e..47c8cad5c 100644
--- a/examples/spdy/spdy.js
+++ b/examples/spdy/spdy.js
@@ -3,26 +3,26 @@ var bunyan = require('bunyan');
var restify = require('../../lib');
var srv = restify.createServer({
- spdy: {
- cert: fs.readFileSync('./keys/spdy-cert.pem'),
- key: fs.readFileSync('./keys/spdy-key.pem'),
- ca: fs.readFileSync('keys/spdy-csr.pem')
- }
+ spdy: {
+ cert: fs.readFileSync('./keys/spdy-cert.pem'),
+ key: fs.readFileSync('./keys/spdy-key.pem'),
+ ca: fs.readFileSync('keys/spdy-csr.pem')
+ }
});
srv.get('/', function (req, res, next) {
- res.send({hello: 'world'});
- next();
+ res.send({hello: 'world'});
+ next();
});
srv.on('after', restify.auditLogger({
- body: true,
- log: bunyan.createLogger({
- name: 'audit',
- stream: process.stdout
- })
+ body: true,
+ log: bunyan.createLogger({
+ name: 'audit',
+ stream: process.stdout
+ })
}));
srv.listen(8080, function () {
- console.log('ready on %s', srv.url);
+ console.log('ready on %s', srv.url);
});
diff --git a/examples/todoapp/lib/client.js b/examples/todoapp/lib/client.js
index 0fef9b304..7d7956360 100644
--- a/examples/todoapp/lib/client.js
+++ b/examples/todoapp/lib/client.js
@@ -8,130 +8,127 @@ var getopt = require('posix-getopt');
var restify = require('restify');
-
///--- Globals
var sprintf = util.format;
-
///--- API
function TodoClient(options) {
- assert.object(options, 'options');
- assert.object(options.log, 'options.log');
- assert.optionalString(options.socketPath, 'options.socketPath');
- assert.optionalString(options.url, 'options.url');
- assert.optionalString(options.version, 'options.version');
-
- var self = this;
- var ver = options.version || '~1.0';
-
- this.client = restify.createClient({
- log: options.log,
- name: 'TodoClient',
- socketPath: options.socketPath,
- type: 'json',
- url: options.url,
- version: ver
- });
- this.log = options.log.child({component: 'TodoClient'}, true);
- this.url = options.url;
- this.version = ver;
-
- if (options.username && options.password) {
- this.username = options.username;
- this.client.basicAuth(options.username, options.password);
- }
+ assert.object(options, 'options');
+ assert.object(options.log, 'options.log');
+ assert.optionalString(options.socketPath, 'options.socketPath');
+ assert.optionalString(options.url, 'options.url');
+ assert.optionalString(options.version, 'options.version');
+
+ var self = this;
+ var ver = options.version || '~1.0';
+
+ this.client = restify.createClient({
+ log: options.log,
+ name: 'TodoClient',
+ socketPath: options.socketPath,
+ type: 'json',
+ url: options.url,
+ version: ver
+ });
+ this.log = options.log.child({component: 'TodoClient'}, true);
+ this.url = options.url;
+ this.version = ver;
+
+ if (options.username && options.password) {
+ this.username = options.username;
+ this.client.basicAuth(options.username, options.password);
+ }
}
TodoClient.prototype.create = function create(task, cb) {
- assert.string(task, 'task');
- assert.func(cb, 'callback');
-
- this.client.post('/todo', {task: task}, function (err, req, res, obj) {
- if (err) {
- cb(err);
- } else {
- cb(null, obj);
- }
- });
+ assert.string(task, 'task');
+ assert.func(cb, 'callback');
+
+ this.client.post('/todo', {task: task}, function (err, req, res, obj) {
+ if (err) {
+ cb(err);
+ } else {
+ cb(null, obj);
+ }
+ });
};
TodoClient.prototype.list = function list(cb) {
- assert.func(cb, 'callback');
-
- this.client.get('/todo', function (err, req, res, obj) {
- if (err) {
- cb(err);
- } else {
- cb(null, obj);
- }
- });
+ assert.func(cb, 'callback');
+
+ this.client.get('/todo', function (err, req, res, obj) {
+ if (err) {
+ cb(err);
+ } else {
+ cb(null, obj);
+ }
+ });
};
TodoClient.prototype.get = function get(name, cb) {
- assert.string(name, 'name');
- assert.func(cb, 'callback');
-
- this.client.get('/todo/' + name, function (err, req, res, obj) {
- if (err) {
- cb(err);
- } else {
- cb(null, obj);
- }
- });
+ assert.string(name, 'name');
+ assert.func(cb, 'callback');
+
+ this.client.get('/todo/' + name, function (err, req, res, obj) {
+ if (err) {
+ cb(err);
+ } else {
+ cb(null, obj);
+ }
+ });
};
TodoClient.prototype.update = function update(todo, cb) {
- assert.object(todo, 'todo');
- assert.func(cb, 'callback');
-
- this.client.put('/todo/' + todo.name, todo, function (err) {
- if (err) {
- cb(err);
- } else {
- cb(null);
- }
- });
+ assert.object(todo, 'todo');
+ assert.func(cb, 'callback');
+
+ this.client.put('/todo/' + todo.name, todo, function (err) {
+ if (err) {
+ cb(err);
+ } else {
+ cb(null);
+ }
+ });
};
TodoClient.prototype.del = function del(name, cb) {
- if (typeof (name) === 'function') {
- cb = name;
- name = '';
+ if (typeof (name) === 'function') {
+ cb = name;
+ name = '';
+ }
+ assert.string(name, 'name');
+ assert.func(cb, 'callback');
+
+ var p = '/todo' + (name.length > 0 ? '/' + name : '');
+ this.client.del(p, function (err) {
+ if (err) {
+ cb(err);
+ } else {
+ cb(null);
}
- assert.string(name, 'name');
- assert.func(cb, 'callback');
-
- var p = '/todo' + (name.length > 0 ? '/' + name : '');
- this.client.del(p, function (err) {
- if (err) {
- cb(err);
- } else {
- cb(null);
- }
- });
+ });
};
TodoClient.prototype.toString = function toString() {
- var str = sprintf('[object TodoClient this little hackery
- // just ensures that we're never < TRACE
- LOG.level(Math.max(bunyan.TRACE, (LOG.level() - 10)));
- if (LOG.level() <= bunyan.DEBUG)
- LOG = LOG.child({src: true});
- break;
-
- case 'z':
- opts.password = option.optarg;
- break;
-
- default:
- usage('invalid option: ' + option.option);
- break;
- }
+ var option;
+ var opts = {}
+ var parser = new getopt.BasicParser('hvd:p:u:z:', process.argv);
+
+ while ((option = parser.getopt()) !== undefined) {
+ switch (option.option) {
+ case 'd':
+ opts.directory = path.normalize(option.optarg);
+ break;
+
+ case 'h':
+ usage();
+ break;
+
+ case 'p':
+ opts.port = parseInt(option.optarg, 10);
+ break;
+
+ case 'u':
+ opts.user = option.optarg;
+ break;
+
+ case 'v':
+ // Allows us to set -vvv -> this little hackery
+ // just ensures that we're never < TRACE
+ LOG.level(Math.max(bunyan.TRACE, (LOG.level() - 10)));
+ if (LOG.level() <= bunyan.DEBUG)
+ LOG = LOG.child({src: true});
+ break;
+
+ case 'z':
+ opts.password = option.optarg;
+ break;
+
+ default:
+ usage('invalid option: ' + option.option);
+ break;
}
+ }
- return (opts);
+ return (opts);
}
function usage(msg) {
- if (msg)
- console.error(msg);
-
- var str = 'usage: ' +
- NAME +
- ' [-v] [-d dir] [-p port] [-u user] [-z password]';
- console.error(str);
- process.exit(msg ? 1 : 0);
+ if (msg)
+ console.error(msg);
+
+ var str = 'usage: ' +
+ NAME +
+ ' [-v] [-d dir] [-p port] [-u user] [-z password]';
+ console.error(str);
+ process.exit(msg ? 1 : 0);
}
-
///--- Mainline
(function main() {
- var options = parseOptions();
-
- LOG.debug(options, 'command line arguments parsed');
-
- // First setup our 'database'
- var dir = path.normalize((options.directory || '/tmp') + '/todos');
- try {
- fs.mkdirSync(dir);
- } catch (e) {
- if (e.code !== 'EEXIST') {
- LOG.fatal(e, 'unable to create "database" %s', dir);
- process.exit(1);
- }
+ var options = parseOptions();
+
+ LOG.debug(options, 'command line arguments parsed');
+
+ // First setup our 'database'
+ var dir = path.normalize((options.directory || '/tmp') + '/todos');
+ try {
+ fs.mkdirSync(dir);
+ } catch (e) {
+ if (e.code !== 'EEXIST') {
+ LOG.fatal(e, 'unable to create "database" %s', dir);
+ process.exit(1);
}
+ }
- var server = todo.createServer({
- directory: dir,
- log: LOG
- });
+ var server = todo.createServer({
+ directory: dir,
+ log: LOG
+ });
- // At last, let's rock and roll
- server.listen((options.port || 8080), function onListening() {
- LOG.info('listening at %s', server.url);
- });
+ // At last, let's rock and roll
+ server.listen((options.port || 8080), function onListening() {
+ LOG.info('listening at %s', server.url);
+ });
})();
diff --git a/examples/todoapp/test/todo.test.js b/examples/todoapp/test/todo.test.js
index b67738cbc..13ddd5e23 100644
--- a/examples/todoapp/test/todo.test.js
+++ b/examples/todoapp/test/todo.test.js
@@ -9,7 +9,6 @@ var restify = require('restify');
var todo = require('../lib');
-
///--- Globals
var CLIENT;
@@ -18,121 +17,120 @@ var SERVER;
var SOCK = '/tmp/.todo_sock';
-
///--- Tests
exports.setup = function (t) {
- var log = bunyan.createLogger({
- name: 'todo_unit_test',
- level: process.env.LOG_LEVEL || 'info',
- serializers: restify.bunyan.serializers,
- stream: process.stdout
+ var log = bunyan.createLogger({
+ name: 'todo_unit_test',
+ level: process.env.LOG_LEVEL || 'info',
+ serializers: restify.bunyan.serializers,
+ stream: process.stdout
+ });
+
+
+ fs.mkdir(DIR, function (err) {
+ if (err && err.code !== 'EEXIST') {
+ console.error('unable to mkdir: ' + err.stack);
+ process.exit(1);
+ }
+
+ SERVER = todo.createServer({
+ directory: DIR,
+ log: log.child({component: 'server'}, true),
+ noAudit: true
});
-
- fs.mkdir(DIR, function (err) {
- if (err && err.code !== 'EEXIST') {
- console.error('unable to mkdir: ' + err.stack);
- process.exit(1);
- }
-
- SERVER = todo.createServer({
- directory: DIR,
- log: log.child({component: 'server'}, true),
- noAudit: true
- });
-
- t.ok(SERVER);
- SERVER.listen(SOCK, function () {
- CLIENT = todo.createClient({
- log: log.child({component: 'client'}, true),
- socketPath: SOCK
- });
- t.ok(CLIENT);
- t.done();
- });
+ t.ok(SERVER);
+ SERVER.listen(SOCK, function () {
+ CLIENT = todo.createClient({
+ log: log.child({component: 'client'}, true),
+ socketPath: SOCK
+ });
+ t.ok(CLIENT);
+ t.done();
});
+ });
};
exports.listEmpty = function (t) {
- CLIENT.list(function (err, todos) {
- t.ifError(err);
- t.ok(todos);
- t.ok(Array.isArray(todos));
- if (todos)
- t.equal(todos.length, 0);
- t.done();
- });
+ CLIENT.list(function (err, todos) {
+ t.ifError(err);
+ t.ok(todos);
+ t.ok(Array.isArray(todos));
+ if (todos)
+ t.equal(todos.length, 0);
+ t.done();
+ });
};
exports.create = function (t) {
- var task = 'check that unit test works';
- CLIENT.create(task, function (err, todo) {
- t.ifError(err);
- t.ok(todo);
- if (todo) {
- t.ok(todo.name);
- t.equal(todo.task, task);
- }
- t.done();
- });
+ var task = 'check that unit test works';
+ CLIENT.create(task, function (err, todo) {
+ t.ifError(err);
+ t.ok(todo);
+ if (todo) {
+ t.ok(todo.name);
+ t.equal(todo.task, task);
+ }
+ t.done();
+ });
};
exports.listAndGet = function (t) {
- CLIENT.list(function (err, todos) {
- t.ifError(err);
- t.ok(todos);
- t.ok(Array.isArray(todos));
- if (todos) {
- t.equal(todos.length, 1);
- CLIENT.get(todos[0], function (err2, todo) {
- t.ifError(err2);
- t.ok(todo);
- t.done();
- });
- } else {
- t.done();
- }
- });
+ CLIENT.list(function (err, todos) {
+ t.ifError(err);
+ t.ok(todos);
+ t.ok(Array.isArray(todos));
+ if (todos) {
+ t.equal(todos.length, 1);
+ CLIENT.get(todos[0], function (err2, todo) {
+ t.ifError(err2);
+ t.ok(todo);
+ t.done();
+ });
+ } else {
+ t.done();
+ }
+ });
};
exports.update = function (t) {
- CLIENT.list(function (err, todos) {
- t.ifError(err);
- t.ok(todos);
- t.ok(Array.isArray(todos));
- if (todos) {
- t.equal(todos.length, 1);
-
- var todo = {
- name: todos[0],
- task: 'something else'
- };
- CLIENT.update(todo, function (err2) {
- t.ifError(err2);
- t.done();
- });
- } else {
- t.done();
- }
- });
+ CLIENT.list(function (err, todos) {
+ t.ifError(err);
+ t.ok(todos);
+ t.ok(Array.isArray(todos));
+ if (todos) {
+ t.equal(todos.length, 1);
+
+ var todo = {
+ name: todos[0],
+ task: 'something else'
+ };
+ CLIENT.update(todo, function (err2) {
+ t.ifError(err2);
+ t.done();
+ });
+ } else {
+ t.done();
+ }
+ });
};
exports.teardown = function teardown(t) {
- CLIENT.del(function (err) {
- t.ifError(err);
+ CLIENT.del(function (err) {
+ t.ifError(err);
- SERVER.once('close', function () {
- fs.rmdir(DIR, function (err) {
- t.ifError(err);
- t.done();
- });
- });
- SERVER.close();
+ SERVER.once('close', function () {
+ fs.rmdir(DIR, function (err) {
+ t.ifError(err);
+ t.done();
+ });
});
+ SERVER.close();
+ });
};
diff --git a/lib/bunyan_helper.js b/lib/bunyan_helper.js
index c421d83c6..7c6616e06 100644
--- a/lib/bunyan_helper.js
+++ b/lib/bunyan_helper.js
@@ -9,7 +9,6 @@ var LRU = require('lru-cache');
var uuid = require('node-uuid');
-
///--- Globals
var sprintf = util.format;
@@ -17,23 +16,22 @@ var DEFAULT_REQ_ID = uuid.v4();
var STR_FMT = '[object %s]';
-
///--- Helpers
function appendStream(streams, s) {
- assert.arrayOfObject(streams, 'streams');
- assert.object(s, 'stream');
+ assert.arrayOfObject(streams, 'streams');
+ assert.object(s, 'stream');
- if (s instanceof Stream) {
- streams.push({
- raw: false,
- stream: s
- });
- } else {
- assert.optionalBool(s.raw, 'stream.raw');
- assert.object(s.stream, 'stream.stream');
- streams.push(s);
- }
+ if (s instanceof Stream) {
+ streams.push({
+ raw: false,
+ stream: s
+ });
+ } else {
+ assert.optionalBool(s.raw, 'stream.raw');
+ assert.object(s.stream, 'stream.stream');
+ streams.push(s);
+ }
}
@@ -58,176 +56,178 @@ function appendStream(streams, s) {
* a "req_id" field. Default false.
*/
function RequestCaptureStream(opts) {
- assert.object(opts, 'options');
- assert.optionalObject(opts.stream, 'options.stream');
- assert.optionalArrayOfObject(opts.streams, 'options.streams');
- assert.optionalNumber(opts.level, 'options.level');
- assert.optionalNumber(opts.maxRecords, 'options.maxRecords');
- assert.optionalNumber(opts.maxRequestIds, 'options.maxRequestIds');
- assert.optionalBool(opts.dumpDefault, 'options.dumpDefault');
-
- var self = this;
- Stream.call(this);
-
- this.level = opts.level ? bunyan.resolveLevel(opts.level) : bunyan.WARN;
- this.limit = opts.maxRecords || 100;
- this.maxRequestIds = opts.maxRequestIds || 1000;
- this.requestMap = LRU({
- max: self.maxRequestIds
- });
- this.dumpDefault = opts.dumpDefault;
-
- this._offset = -1;
- this._rings = [];
-
- this.streams = [];
-
- if (opts.stream)
- appendStream(this.streams, opts.stream);
-
- if (opts.streams)
- opts.streams.forEach(appendStream.bind(null, this.streams));
-
- this.haveNonRawStreams = false;
- for (var i = 0; i < this.streams.length; i++) {
- if (!this.streams[i].raw) {
- this.haveNonRawStreams = true;
- break;
- }
+ assert.object(opts, 'options');
+ assert.optionalObject(opts.stream, 'options.stream');
+ assert.optionalArrayOfObject(opts.streams, 'options.streams');
+ assert.optionalNumber(opts.level, 'options.level');
+ assert.optionalNumber(opts.maxRecords, 'options.maxRecords');
+ assert.optionalNumber(opts.maxRequestIds, 'options.maxRequestIds');
+ assert.optionalBool(opts.dumpDefault, 'options.dumpDefault');
+
+ var self = this;
+ Stream.call(this);
+
+ this.level = opts.level ? bunyan.resolveLevel(opts.level) : bunyan.WARN;
+ this.limit = opts.maxRecords || 100;
+ this.maxRequestIds = opts.maxRequestIds || 1000;
+ this.requestMap = LRU({
+ max: self.maxRequestIds
+ });
+ this.dumpDefault = opts.dumpDefault;
+
+ this._offset = -1;
+ this._rings = [];
+
+ this.streams = [];
+
+ if (opts.stream)
+ appendStream(this.streams, opts.stream);
+
+ if (opts.streams)
+ opts.streams.forEach(appendStream.bind(null, this.streams));
+
+ this.haveNonRawStreams = false;
+ for (var i = 0; i < this.streams.length; i++) {
+ if (!this.streams[i].raw) {
+ this.haveNonRawStreams = true;
+ break;
}
+ }
}
util.inherits(RequestCaptureStream, Stream);
RequestCaptureStream.prototype.write = function write(record) {
- var req_id = record.req_id || DEFAULT_REQ_ID;
- var ring;
- var self = this;
-
- if (!(ring = this.requestMap.get(req_id))) {
- if (++this._offset > this.maxRequestIds)
- this._offset = 0;
-
- if (this._rings.length <= this._offset) {
- this._rings.push(new bunyan.RingBuffer({
- limit: self.limit
- }));
- }
-
- ring = this._rings[this._offset];
- ring.records.length = 0;
- this.requestMap.set(req_id, ring);
+ var req_id = record.req_id || DEFAULT_REQ_ID;
+ var ring;
+ var self = this;
+
+ if (!(ring = this.requestMap.get(req_id))) {
+ if (++this._offset > this.maxRequestIds)
+ this._offset = 0;
+
+ if (this._rings.length <= this._offset) {
+ this._rings.push(new bunyan.RingBuffer({
+ limit: self.limit
+ }));
}
- assert.ok(ring, 'no ring found');
-
- if (record.level >= this.level) {
- var i, r, ser;
- for (i = 0; i < ring.records.length; i++) {
- r = ring.records[i];
- if (this.haveNonRawStreams) {
- ser = JSON.stringify(r,
- bunyan.safeCycles()) + '\n';
- }
- self.streams.forEach(function (s) {
- s.stream.write(s.raw ? r : ser);
- });
- }
- ring.records.length = 0;
- if (this.dumpDefault) {
- var defaultRing = self.requestMap.get(DEFAULT_REQ_ID);
- for (i = 0; i < defaultRing.records.length; i++) {
- r = defaultRing.records[i];
- if (this.haveNonRawStreams) {
- ser = JSON.stringify(r,
- bunyan.safeCycles()) + '\n';
- }
- self.streams.forEach(function (s) {
- s.stream.write(s.raw ? r : ser);
- });
- }
- defaultRing.records.length = 0;
+ ring = this._rings[this._offset];
+ ring.records.length = 0;
+ this.requestMap.set(req_id, ring);
+ }
+
+ assert.ok(ring, 'no ring found');
+
+ if (record.level >= this.level) {
+ var i, r, ser;
+ for (i = 0; i < ring.records.length; i++) {
+ r = ring.records[i];
+ if (this.haveNonRawStreams) {
+ ser = JSON.stringify(r,
+ bunyan.safeCycles()) + '\n';
+ }
+ self.streams.forEach(function (s) {
+ s.stream.write(s.raw ? r : ser);
+ });
+ }
+ ring.records.length = 0;
+ if (this.dumpDefault) {
+ var defaultRing = self.requestMap.get(DEFAULT_REQ_ID);
+ for (i = 0; i < defaultRing.records.length; i++) {
+ r = defaultRing.records[i];
+ if (this.haveNonRawStreams) {
+ ser = JSON.stringify(r,
+ bunyan.safeCycles()) + '\n';
}
- } else {
- ring.write(record);
+ self.streams.forEach(function (s) {
+ s.stream.write(s.raw ? r : ser);
+ });
+ }
+ defaultRing.records.length = 0;
}
+ } else {
+ ring.write(record);
+ }
};
RequestCaptureStream.prototype.toString = function toString() {
- return (sprintf(STR_FMT,
- this.constructor.name,
- this.level,
- this.limit,
- this.maxRequestIds));
+ return (sprintf(STR_FMT,
+ this.constructor.name,
+ this.level,
+ this.limit,
+ this.maxRequestIds));
};
-
///--- Serializers
function clientReq(req) {
- if (!req)
- return (req);
-
- var host;
-
- try {
- host = req.host.split(':')[0];
- } catch (e) {
- host = false;
- }
-
- return ({
- method: req ? req.method : false,
- url: req ? req.path : false,
- address: host,
- port: req ? req.port : false,
- headers: req ? req.headers : false
- });
+ if (!req)
+ return (req);
+
+ var host;
+
+ try {
+ host = req.host.split(':')[0];
+ } catch (e) {
+ host = false;
+ }
+
+ return ({
+ method: req ? req.method : false,
+ url: req ? req.path : false,
+ address: host,
+ port: req ? req.port : false,
+ headers: req ? req.headers : false
+ });
}
function clientRes(res) {
- if (!res || !res.statusCode)
- return (res);
+ if (!res || !res.statusCode)
+ return (res);
- return ({
- statusCode: res.statusCode,
- headers: res.headers
- });
+ return ({
+ statusCode: res.statusCode,
+ headers: res.headers
+ });
}
var SERIALIZERS = {
- err: bunyan.stdSerializers.err,
- req: bunyan.stdSerializers.req,
- res: bunyan.stdSerializers.res,
- client_req: clientReq,
- client_res: clientRes
+ err: bunyan.stdSerializers.err,
+ req: bunyan.stdSerializers.req,
+ res: bunyan.stdSerializers.res,
+ client_req: clientReq,
+ client_res: clientRes
};
///--- Exports
module.exports = {
- RequestCaptureStream: RequestCaptureStream,
- serializers: SERIALIZERS,
-
- createLogger: function createLogger(name) {
- return (bunyan.createLogger({
- name: name,
- serializers: SERIALIZERS,
- streams: [ {
- level: 'warn',
- stream: process.stderr
- }, {
- level: 'debug',
- type: 'raw',
- stream: new RequestCaptureStream({
- stream: process.stderr
- })
- } ]
- }));
- }
+ RequestCaptureStream: RequestCaptureStream,
+ serializers: SERIALIZERS,
+
+ createLogger: function createLogger(name) {
+ return (bunyan.createLogger({
+ name: name,
+ serializers: SERIALIZERS,
+ streams: [
+ {
+ level: 'warn',
+ stream: process.stderr
+ },
+ {
+ level: 'debug',
+ type: 'raw',
+ stream: new RequestCaptureStream({
+ stream: process.stderr
+ })
+ }
+ ]
+ }));
+ }
};
diff --git a/lib/clients/http_client.js b/lib/clients/http_client.js
index 5c1460117..8973a9b49 100644
--- a/lib/clients/http_client.js
+++ b/lib/clients/http_client.js
@@ -31,16 +31,16 @@ var KeepAliveAgentSecure;
var httpMaxSockets = http.globalAgent.maxSockets;
var httpsMaxSockets = https.globalAgent.maxSockets;
if (!nativeKeepAlive) {
- KeepAliveAgent = require('keep-alive-agent');
- KeepAliveAgentSecure = KeepAliveAgent.Secure;
+ KeepAliveAgent = require('keep-alive-agent');
+ KeepAliveAgentSecure = KeepAliveAgent.Secure;
} else {
- KeepAliveAgent = http.Agent;
- KeepAliveAgentSecure = https.Agent;
- // maxSockets defaults to Infinity, but that doesn't
- // lend itself well to KeepAlive, since sockets will
- // never be reused.
- httpMaxSockets = Math.min(httpMaxSockets, 1024);
- httpsMaxSockets = Math.min(httpsMaxSockets, 1024);
+ KeepAliveAgent = http.Agent;
+ KeepAliveAgentSecure = https.Agent;
+ // maxSockets defaults to Infinity, but that doesn't
+ // lend itself well to KeepAlive, since sockets will
+ // never be reused.
+ httpMaxSockets = Math.min(httpMaxSockets, 1024);
+ httpsMaxSockets = Math.min(httpsMaxSockets, 1024);
}
///--- Globals
@@ -49,492 +49,489 @@ if (!nativeKeepAlive) {
var VERSION = JSON.parse(fs.readFileSync(require('path').normalize(__dirname + '/../../package.json'), 'utf8')).version;
-
///--- Helpers
function cloneRetryOptions(options, defaults) {
- if (options === false) {
- return (false);
- }
-
- 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
- });
+ if (options === false) {
+ return (false);
+ }
+
+ 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() {
- var UA = 'restify/' + VERSION +
- ' (' + os.arch() + '-' + os.platform() + '; ' +
- 'v8/' + process.versions.v8 + '; ' +
- 'OpenSSL/' + process.versions.openssl + ') ' +
- 'node/' + process.versions.node;
+ var UA = 'restify/' + VERSION +
+ ' (' + os.arch() + '-' + os.platform() + '; ' +
+ 'v8/' + process.versions.v8 + '; ' +
+ 'OpenSSL/' + process.versions.openssl + ') ' +
+ 'node/' + process.versions.node;
- return (UA);
+ return (UA);
}
function ConnectTimeoutError(ms) {
- if (Error.captureStackTrace)
- Error.captureStackTrace(this, ConnectTimeoutError);
+ if (Error.captureStackTrace)
+ Error.captureStackTrace(this, ConnectTimeoutError);
- this.message = 'connect timeout after ' + ms + 'ms';
- this.name = 'ConnectTimeoutError';
+ this.message = 'connect timeout after ' + ms + 'ms';
+ this.name = 'ConnectTimeoutError';
}
util.inherits(ConnectTimeoutError, Error);
function rawRequest(opts, cb) {
- assert.object(opts, 'options');
- assert.object(opts.log, 'options.log');
- assert.func(cb, 'callback');
-
- cb = once(cb);
-
- var id = dtrace.nextId();
- var log = opts.log;
- var proto = opts.protocol === 'https:' ? https : http;
- var timer;
-
- if (opts.cert && opts.key)
- opts.agent = false;
-
- if (opts.connectTimeout) {
- timer = setTimeout(function connectTimeout() {
- timer = null;
- if (req) {
- req.abort();
- }
-
- 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
- ]);
+ assert.object(opts, 'options');
+ assert.object(opts.log, 'options.log');
+ assert.func(cb, 'callback');
+
+ cb = once(cb);
+
+ var id = dtrace.nextId();
+ var log = opts.log;
+ var proto = opts.protocol === 'https:' ? https : http;
+ var timer;
+
+ if (opts.cert && opts.key)
+ opts.agent = false;
+
+ if (opts.connectTimeout) {
+ timer = setTimeout(function connectTimeout() {
+ timer = null;
+ if (req) {
+ req.abort();
+ }
+
+ 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');
- 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');
+ res.log = log;
- res.log = log;
+ var err;
+ if (res.statusCode >= 400)
+ err = errors.codeToHttpError(res.statusCode);
- var err;
- if (res.statusCode >= 400)
- err = errors.codeToHttpError(res.statusCode);
+ req.removeAllListeners('error');
+ req.removeAllListeners('socket');
+ req.emit('result', (err || null), res);
+ });
+ req.log = log;
- req.removeAllListeners('error');
- req.removeAllListeners('socket');
- req.emit('result', (err || null), res);
- });
- req.log = log;
-
- req.on('error', function onError(err) {
- dtrace._rstfy_probes['client-error'].fire(function () {
- return ([id, (err || {}).toString()]);
- });
- log.trace({err: err}, 'Request failed');
- clearTimeout(timer);
-
- cb(err, req);
- if (req) {
- process.nextTick(function () {
- req.emit('result', err, null);
- });
- }
+ req.on('error', function onError(err) {
+ dtrace._rstfy_probes['client-error'].fire(function () {
+ return ([id, (err || {}).toString()]);
});
+ log.trace({err: err}, 'Request failed');
+ clearTimeout(timer);
+
+ cb(err, req);
+ if (req) {
+ process.nextTick(function () {
+ req.emit('result', err, null);
+ });
+ }
+ });
- req.once('upgrade', function onUpgrade(res, socket, _head) {
- clearTimeout(timer);
- dtrace._rstfy_probes['client-response'].fire(function () {
- return ([ id, res.statusCode, res.headers ]);
- });
- log.trace({client_res: res}, 'upgrade response received');
+ req.once('upgrade', function onUpgrade(res, socket, _head) {
+ clearTimeout(timer);
+ dtrace._rstfy_probes['client-response'].fire(function () {
+ return ([ id, res.statusCode, res.headers ]);
+ });
+ log.trace({client_res: res}, 'upgrade response received');
- res.log = log;
+ res.log = log;
- var err;
- if (res.statusCode >= 400)
- err = errors.codeToHttpError(res.statusCode);
+ var err;
+ if (res.statusCode >= 400)
+ err = errors.codeToHttpError(res.statusCode);
- req.removeAllListeners('error');
- req.removeAllListeners('socket');
- req.emit('upgradeResult', (err || null), res, socket, _head);
- });
+ req.removeAllListeners('error');
+ req.removeAllListeners('socket');
+ req.emit('upgradeResult', (err || null), res, socket, _head);
+ });
- req.once('socket', function onSocket(socket) {
- var _socket = socket;
- if (opts.protocol === 'https:' && socket.socket) {
- _socket = socket.socket;
- }
+ req.once('socket', function onSocket(socket) {
+ var _socket = socket;
+ if (opts.protocol === 'https:' && socket.socket) {
+ _socket = socket.socket;
+ }
- if (_socket.writable && !_socket._connecting) {
- clearTimeout(timer);
- cb(null, req);
- return;
- }
+ if (_socket.writable && !_socket._connecting) {
+ clearTimeout(timer);
+ cb(null, req);
+ return;
+ }
- _socket.once('connect', function onConnect() {
- clearTimeout(timer);
- if (opts._keep_alive) {
- _socket.setKeepAlive(true);
- socket.setKeepAlive(true);
- }
+ _socket.once('connect', function onConnect() {
+ clearTimeout(timer);
+ if (opts._keep_alive) {
+ _socket.setKeepAlive(true);
+ socket.setKeepAlive(true);
+ }
- cb(null, req);
- });
+ cb(null, req);
});
+ });
- if (opts.signRequest)
- opts.signRequest(req);
+ if (opts.signRequest)
+ opts.signRequest(req);
- if (log.trace())
- log.trace({client_req: opts}, 'request sent');
+ if (log.trace())
+ log.trace({client_req: opts}, 'request sent');
} // end `rawRequest`
-
///--- API
function HttpClient(options) {
- assert.object(options, 'options');
- assert.optionalObject(options.headers, 'options.headers');
- assert.object(options.log, 'options.log');
- assert.optionalFunc(options.signRequest, 'options.signRequest');
- assert.optionalString(options.socketPath, 'options.socketPath');
- assert.optionalString(options.url, 'options.url');
-
- EventEmitter.call(this);
-
- var self = this;
-
- this.agent = options.agent;
- this.ca = options.ca;
- this.cert = options.cert;
- this.ciphers = options.ciphers;
- this.connectTimeout = options.connectTimeout || false;
- this.headers = options.headers || {};
- this.log = options.log;
- if (!this.log.serializers)
- {
- // Ensure logger has a reasonable serializer for `client_res`
- // and `client_req` logged in this module.
- this.log = this.log.child({serializers: bunyan.serializers});
- }
- this.key = options.key;
- this.name = options.name || 'HttpClient';
- this.passphrase = options.passphrase;
- this.pfx = options.pfx;
- if (options.rejectUnauthorized !== undefined) {
- this.rejectUnauthorized = options.rejectUnauthorized;
- } else {
- this.rejectUnauthorized = true;
- }
-
- if (process.env.https_proxy) {
- this.proxy = url.parse(process.env.https_proxy);
- } else if (process.env.http_proxy) {
- this.proxy = url.parse(process.env.http_proxy);
- } else if (options.proxy) {
- this.proxy = options.proxy;
- } else {
- this.proxy = false;
- }
-
- this.retry = cloneRetryOptions(options.retry);
- this.signRequest = options.signRequest || false;
- this.socketPath = options.socketPath || false;
- this.url = options.url ? url.parse(options.url) : {};
-
- if (options.accept) {
- if (options.accept.indexOf('/') === -1)
- options.accept = mime.lookup(options.accept);
-
- this.headers.accept = options.accept;
- }
-
- if (options.contentType) {
- if (options.contentType.indexOf('/') === -1)
- options.type = mime.lookup(options.contentType);
-
- this.headers['content-type'] = options.contentType;
- }
-
- if (options.userAgent !== false) {
- this.headers['user-agent'] = options.userAgent ||
- defaultUserAgent();
- }
-
- if (options.version)
- this.headers['accept-version'] = options.version;
-
- if (this.agent === undefined) {
- var Agent;
- var maxSockets;
-
- if (this.proxy) {
- if (this.url.protocol == 'https:') {
- if (this.proxy.protocol === 'https:') {
- Agent = tunnelAgent.httpsOverHttps;
- } else {
- Agent = tunnelAgent.httpsOverHttp;
- }
- } else {
- if (this.proxy.protocol === 'https:') {
- Agent = tunnelAgent.httpOverHttps;
- } else {
- Agent = tunnelAgent.httpOverHttp;
- }
- }
- } else if (this.url.protocol === 'https:') {
- Agent = KeepAliveAgentSecure;
- maxSockets = httpsMaxSockets;
+ assert.object(options, 'options');
+ assert.optionalObject(options.headers, 'options.headers');
+ assert.object(options.log, 'options.log');
+ assert.optionalFunc(options.signRequest, 'options.signRequest');
+ assert.optionalString(options.socketPath, 'options.socketPath');
+ assert.optionalString(options.url, 'options.url');
+
+ EventEmitter.call(this);
+
+ var self = this;
+
+ this.agent = options.agent;
+ this.ca = options.ca;
+ this.cert = options.cert;
+ this.ciphers = options.ciphers;
+ this.connectTimeout = options.connectTimeout || false;
+ this.headers = options.headers || {};
+ this.log = options.log;
+ if (!this.log.serializers) {
+ // Ensure logger has a reasonable serializer for `client_res`
+ // and `client_req` logged in this module.
+ this.log = this.log.child({serializers: bunyan.serializers});
+ }
+ this.key = options.key;
+ this.name = options.name || 'HttpClient';
+ this.passphrase = options.passphrase;
+ this.pfx = options.pfx;
+ if (options.rejectUnauthorized !== undefined) {
+ this.rejectUnauthorized = options.rejectUnauthorized;
+ } else {
+ this.rejectUnauthorized = true;
+ }
+
+ if (process.env.https_proxy) {
+ this.proxy = url.parse(process.env.https_proxy);
+ } else if (process.env.http_proxy) {
+ this.proxy = url.parse(process.env.http_proxy);
+ } else if (options.proxy) {
+ this.proxy = options.proxy;
+ } else {
+ this.proxy = false;
+ }
+
+ this.retry = cloneRetryOptions(options.retry);
+ this.signRequest = options.signRequest || false;
+ this.socketPath = options.socketPath || false;
+ this.url = options.url ? url.parse(options.url) : {};
+
+ if (options.accept) {
+ if (options.accept.indexOf('/') === -1)
+ options.accept = mime.lookup(options.accept);
+
+ this.headers.accept = options.accept;
+ }
+
+ if (options.contentType) {
+ if (options.contentType.indexOf('/') === -1)
+ options.type = mime.lookup(options.contentType);
+
+ this.headers['content-type'] = options.contentType;
+ }
+
+ if (options.userAgent !== false) {
+ this.headers['user-agent'] = options.userAgent ||
+ defaultUserAgent();
+ }
+
+ if (options.version)
+ this.headers['accept-version'] = options.version;
+
+ if (this.agent === undefined) {
+ var Agent;
+ var maxSockets;
+
+ if (this.proxy) {
+ if (this.url.protocol == 'https:') {
+ if (this.proxy.protocol === 'https:') {
+ Agent = tunnelAgent.httpsOverHttps;
} else {
- Agent = KeepAliveAgent;
- maxSockets = httpMaxSockets;
+ Agent = tunnelAgent.httpsOverHttp;
}
-
- if (this.proxy) {
- this.agent = new Agent({
- proxy: self.proxy,
- rejectUnauthorized: self.rejectUnauthorized,
- ca: self.ca
- });
+ } else {
+ if (this.proxy.protocol === 'https:') {
+ Agent = tunnelAgent.httpOverHttps;
} else {
- this.agent = new Agent({
- cert: self.cert,
- ca: self.ca,
- ciphers: self.ciphers,
- key: self.key,
- maxSockets: maxSockets,
-
- // require('keep-alive-agent')
- maxKeepAliveRequests: 0,
- maxKeepAliveTime: 0,
-
- // native keepalive
- keepAliveMsecs: 1000,
- keepAlive: true,
-
- passphrase: self.passphrase,
- pfx: self.pfx,
- rejectUnauthorized: self.rejectUnauthorized
- });
- this._keep_alive = true;
+ Agent = tunnelAgent.httpOverHttp;
}
+ }
+ } else if (this.url.protocol === 'https:') {
+ Agent = KeepAliveAgentSecure;
+ maxSockets = httpsMaxSockets;
+ } else {
+ Agent = KeepAliveAgent;
+ maxSockets = httpMaxSockets;
+ }
+
+ if (this.proxy) {
+ this.agent = new Agent({
+ proxy: self.proxy,
+ rejectUnauthorized: self.rejectUnauthorized,
+ ca: self.ca
+ });
+ } else {
+ this.agent = new Agent({
+ cert: self.cert,
+ ca: self.ca,
+ ciphers: self.ciphers,
+ key: self.key,
+ maxSockets: maxSockets,
+
+ // require('keep-alive-agent')
+ maxKeepAliveRequests: 0,
+ maxKeepAliveTime: 0,
+
+ // native keepalive
+ keepAliveMsecs: 1000,
+ keepAlive: true,
+
+ passphrase: self.passphrase,
+ pfx: self.pfx,
+ rejectUnauthorized: self.rejectUnauthorized
+ });
+ this._keep_alive = true;
}
+ }
}
util.inherits(HttpClient, EventEmitter);
module.exports = HttpClient;
HttpClient.prototype.close = function close() {
- var sockets = this.agent.sockets;
- Object.keys((sockets || {})).forEach(function (k) {
- if (Array.isArray(sockets[k])) {
- sockets[k].forEach(function (s) {
- s.end();
- });
- }
- });
+ var sockets = this.agent.sockets;
+ Object.keys((sockets || {})).forEach(function (k) {
+ if (Array.isArray(sockets[k])) {
+ sockets[k].forEach(function (s) {
+ s.end();
+ });
+ }
+ });
- sockets = this.agent.idleSockets || this.agent.freeSockets;
- Object.keys((sockets || {})).forEach(function (k) {
- sockets[k].forEach(function (s) {
- s.end();
- });
+ sockets = this.agent.idleSockets || this.agent.freeSockets;
+ Object.keys((sockets || {})).forEach(function (k) {
+ sockets[k].forEach(function (s) {
+ s.end();
});
+ });
};
HttpClient.prototype.del = function del(options, callback) {
- var opts = this._options('DELETE', options);
+ var opts = this._options('DELETE', options);
- return (this.read(opts, callback));
+ return (this.read(opts, callback));
};
HttpClient.prototype.get = function get(options, callback) {
- var opts = this._options('GET', options);
+ var opts = this._options('GET', options);
- return (this.read(opts, callback));
+ return (this.read(opts, callback));
};
HttpClient.prototype.head = function head(options, callback) {
- var opts = this._options('HEAD', options);
+ var opts = this._options('HEAD', options);
- return (this.read(opts, callback));
+ return (this.read(opts, callback));
};
HttpClient.prototype.opts = function http_options(options, callback) {
- var _opts = this._options('OPTIONS', options);
+ var _opts = this._options('OPTIONS', options);
- return (this.read(_opts, callback));
+ return (this.read(_opts, callback));
};
HttpClient.prototype.post = function post(options, callback) {
- var opts = this._options('POST', options);
+ var opts = this._options('POST', options);
- return (this.request(opts, callback));
+ return (this.request(opts, callback));
};
HttpClient.prototype.put = function put(options, callback) {
- var opts = this._options('PUT', options);
+ var opts = this._options('PUT', options);
- return (this.request(opts, callback));
+ return (this.request(opts, callback));
};
HttpClient.prototype.patch = function patch(options, callback) {
- var opts = this._options('PATCH', options);
+ var opts = this._options('PATCH', options);
- return (this.request(opts, callback));
+ return (this.request(opts, callback));
};
HttpClient.prototype.read = function read(options, callback) {
- var r = this.request(options, function readRequestCallback(err, req) {
- if (!err)
- req.end();
+ var r = this.request(options, function readRequestCallback(err, req) {
+ if (!err)
+ req.end();
- return (callback(err, req));
- });
- return (r);
+ return (callback(err, req));
+ });
+ return (r);
};
HttpClient.prototype.basicAuth = function basicAuth(username, password) {
- if (username === false) {
- delete this.headers.authorization;
- } else {
- assert.string(username, 'username');
- assert.string(password, 'password');
-
- var buffer = new Buffer(username + ':' + password, 'utf8');
- this.headers.authorization = 'Basic ' +
- buffer.toString('base64');
- }
-
- return (this);
+ if (username === false) {
+ delete this.headers.authorization;
+ } else {
+ assert.string(username, 'username');
+ assert.string(password, 'password');
+
+ var buffer = new Buffer(username + ':' + password, 'utf8');
+ this.headers.authorization = 'Basic ' +
+ buffer.toString('base64');
+ }
+
+ return (this);
};
HttpClient.prototype.request = function request(opts, cb) {
- assert.object(opts, 'options');
- assert.func(cb, 'callback');
+ assert.object(opts, 'options');
+ assert.func(cb, 'callback');
- cb = once(cb);
+ cb = once(cb);
- if (opts.retry === false) {
- rawRequest(opts, cb);
- return;
- }
+ if (opts.retry === false) {
+ rawRequest(opts, cb);
+ return;
+ }
- var call;
- var retry = cloneRetryOptions(opts.retry);
+ var call;
+ var retry = cloneRetryOptions(opts.retry);
- opts._keep_alive = this._keep_alive;
- 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'));
+ opts._keep_alive = this._keep_alive;
+ 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'));
- call.start();
+ call.start();
};
HttpClient.prototype._options = function (method, options) {
- if (typeof (options) !== 'object')
- options = { path: options };
-
- var self = this;
- var opts = {
- agent: options.agent || self.agent,
- ca: options.ca || self.ca,
- cert: options.cert || self.cert,
- ciphers: options.ciphers || self.ciphers,
- connectTimeout: options.connectTimeout || self.connectTimeout,
- headers: options.headers || {},
- key: options.key || self.key,
- log: options.log || self.log,
- method: method,
- passphrase: options.passphrase || self.passphrase,
- path: options.path || self.path,
- pfx: options.pfx || self.pfx,
- rejectUnauthorized: options.rejectUnauthorized ||
- self.rejectUnauthorized,
- retry: options.retry !== false ? options.retry : false,
- signRequest: options.signRequest || self.signRequest
- };
-
- if (!opts.retry && opts.retry !== false)
- opts.retry = self.retry;
-
-
- // Backwards compatibility with restify < 1.0
- if (options.query &&
- Object.keys(options.query).length &&
- opts.path.indexOf('?') === -1) {
- opts.path += '?' + querystring.stringify(options.query);
- }
-
- if (this.socketPath)
- opts.socketPath = this.socketPath;
-
- Object.keys(this.url).forEach(function (k) {
- if (!opts[k])
- opts[k] = self.url[k];
- });
-
- Object.keys(self.headers).forEach(function (k) {
- if (!opts.headers[k])
- opts.headers[k] = self.headers[k];
- });
-
- if (!opts.headers.date)
- opts.headers.date = new Date().toUTCString();
-
- if (method === 'GET' || method === 'HEAD' || method === 'DELETE') {
- if (opts.headers['content-type'])
- delete opts.headers['content-type'];
- if (opts.headers['content-md5'])
- delete opts.headers['content-md5'];
- if (opts.headers['content-length'] && method !== 'DELETE')
- delete opts.headers['content-length'];
- if (opts.headers['transfer-encoding'])
- delete opts.headers['transfer-encoding'];
- }
-
- return (opts);
+ if (typeof (options) !== 'object')
+ options = { path: options };
+
+ var self = this;
+ var opts = {
+ agent: options.agent || self.agent,
+ ca: options.ca || self.ca,
+ cert: options.cert || self.cert,
+ ciphers: options.ciphers || self.ciphers,
+ connectTimeout: options.connectTimeout || self.connectTimeout,
+ headers: options.headers || {},
+ key: options.key || self.key,
+ log: options.log || self.log,
+ method: method,
+ passphrase: options.passphrase || self.passphrase,
+ path: options.path || self.path,
+ pfx: options.pfx || self.pfx,
+ rejectUnauthorized: options.rejectUnauthorized ||
+ self.rejectUnauthorized,
+ retry: options.retry !== false ? options.retry : false,
+ signRequest: options.signRequest || self.signRequest
+ };
+
+ if (!opts.retry && opts.retry !== false)
+ opts.retry = self.retry;
+
+
+ // Backwards compatibility with restify < 1.0
+ if (options.query &&
+ Object.keys(options.query).length &&
+ opts.path.indexOf('?') === -1) {
+ opts.path += '?' + querystring.stringify(options.query);
+ }
+
+ if (this.socketPath)
+ opts.socketPath = this.socketPath;
+
+ Object.keys(this.url).forEach(function (k) {
+ if (!opts[k])
+ opts[k] = self.url[k];
+ });
+
+ Object.keys(self.headers).forEach(function (k) {
+ if (!opts.headers[k])
+ opts.headers[k] = self.headers[k];
+ });
+
+ if (!opts.headers.date)
+ opts.headers.date = new Date().toUTCString();
+
+ if (method === 'GET' || method === 'HEAD' || method === 'DELETE') {
+ if (opts.headers['content-type'])
+ delete opts.headers['content-type'];
+ if (opts.headers['content-md5'])
+ delete opts.headers['content-md5'];
+ if (opts.headers['content-length'] && method !== 'DELETE')
+ delete opts.headers['content-length'];
+ if (opts.headers['transfer-encoding'])
+ delete opts.headers['transfer-encoding'];
+ }
+
+ return (opts);
};
// vim: set ts=8 sts=8 sw=8 et:
diff --git a/lib/clients/index.js b/lib/clients/index.js
index 153eb20ab..2c195a91e 100644
--- a/lib/clients/index.js
+++ b/lib/clients/index.js
@@ -8,7 +8,7 @@ var StringClient = require('./string_client');
///--- Exports
module.exports = {
- HttpClient: HttpClient,
- JsonClient: JsonClient,
- StringClient: StringClient
+ HttpClient: HttpClient,
+ JsonClient: JsonClient,
+ StringClient: StringClient
};
diff --git a/lib/clients/json_client.js b/lib/clients/json_client.js
index fef346c5b..7505159d9 100644
--- a/lib/clients/json_client.js
+++ b/lib/clients/json_client.js
@@ -10,79 +10,79 @@ var RestError = require('../errors').RestError;
var StringClient = require('./string_client');
-
///--- API
function JsonClient(options) {
- assert.object(options, 'options');
+ assert.object(options, 'options');
- options.accept = 'application/json';
- options.name = options.name || 'JsonClient';
- options.contentType = 'application/json';
+ options.accept = 'application/json';
+ options.name = options.name || 'JsonClient';
+ options.contentType = 'application/json';
- StringClient.call(this, options);
+ StringClient.call(this, options);
- this._super = StringClient.prototype;
+ this._super = StringClient.prototype;
}
util.inherits(JsonClient, StringClient);
module.exports = JsonClient;
JsonClient.prototype.write = function write(options, body, callback) {
- assert.ok(body !== undefined, 'body');
- assert.object(body, 'body');
+ assert.ok(body !== undefined, 'body');
+ assert.object(body, 'body');
- body = JSON.stringify(body !== null ? body : {});
- return (this._super.write.call(this, options, body, callback));
+ body = JSON.stringify(body !== null ? body : {});
+ return (this._super.write.call(this, options, body, callback));
};
JsonClient.prototype.parse = function parse(req, callback) {
- var log = this.log;
- function parseResponse(err, req2, res, data) {
- var obj;
- try {
- if (data && !/^\s*$/.test(data))
- obj = JSON.parse(data);
- } catch (e) {
- // Not really sure what else we can do here, besides
- // make the client just keep going.
- log.trace(e, 'Invalid JSON in response');
- }
- obj = obj || {};
-
- if (res && res.statusCode >= 400) {
- // Upcast error to a RestError (if we can)
- // Be nice and handle errors like
- // { error: { code: '', message: '' } }
- // in addition to { code: '', message: '' }.
- if (obj.code || (obj.error && obj.error.code)) {
- var _c = obj.code ||
- (obj.error ? obj.error.code : '') ||
- '';
- var _m = obj.message ||
- (obj.error ? obj.error.message : '') ||
- '';
-
- err = new RestError({
- message: _m,
- restCode: _c,
- statusCode: res.statusCode
- });
- err.name = err.restCode;
- if (!/Error$/.test(err.name))
- err.name += 'Error';
- } else if (!err) {
- err = codeToHttpError(res.statusCode,
- obj.message || '', data);
- }
- }
-
- if (err)
- err.body = obj;
-
- callback((err || null), req2, res, obj);
+ var log = this.log;
+
+ function parseResponse(err, req2, res, data) {
+ var obj;
+ try {
+ if (data && !/^\s*$/.test(data))
+ obj = JSON.parse(data);
+ } catch (e) {
+ // Not really sure what else we can do here, besides
+ // make the client just keep going.
+ log.trace(e, 'Invalid JSON in response');
+ }
+ obj = obj || {};
+
+ if (res && res.statusCode >= 400) {
+ // Upcast error to a RestError (if we can)
+ // Be nice and handle errors like
+ // { error: { code: '', message: '' } }
+ // in addition to { code: '', message: '' }.
+ if (obj.code || (obj.error && obj.error.code)) {
+ var _c = obj.code ||
+ (obj.error ? obj.error.code : '') ||
+ '';
+ var _m = obj.message ||
+ (obj.error ? obj.error.message : '') ||
+ '';
+
+ err = new RestError({
+ message: _m,
+ restCode: _c,
+ statusCode: res.statusCode
+ });
+ err.name = err.restCode;
+ if (!/Error$/.test(err.name))
+ err.name += 'Error';
+ } else if (!err) {
+ err = codeToHttpError(res.statusCode,
+ obj.message || '', data);
+ }
}
- return (this._super.parse.call(this, req, parseResponse));
+ if (err)
+ err.body = obj;
+
+ callback((err || null), req2, res, obj);
+ }
+
+ return (this._super.parse.call(this, req, parseResponse));
};
diff --git a/lib/clients/string_client.js b/lib/clients/string_client.js
index 4f99a0ba0..6ccdf62b1 100644
--- a/lib/clients/string_client.js
+++ b/lib/clients/string_client.js
@@ -10,182 +10,181 @@ var util = require('util');
var HttpClient = require('./http_client');
-
///--- Helpers
///--- API
function StringClient(options) {
- assert.object(options, 'options');
- assert.optionalObject(options.gzip, 'options.gzip');
+ assert.object(options, 'options');
+ assert.optionalObject(options.gzip, 'options.gzip');
- options.accept = options.accept || 'text/plain';
- options.name = options.name || 'StringClient';
- options.contentType =
- options.contentType || 'application/x-www-form-urlencoded';
+ options.accept = options.accept || 'text/plain';
+ options.name = options.name || 'StringClient';
+ options.contentType =
+ options.contentType || 'application/x-www-form-urlencoded';
- HttpClient.call(this, options);
- this.gzip = options.gzip;
+ HttpClient.call(this, options);
+ this.gzip = options.gzip;
}
util.inherits(StringClient, HttpClient);
module.exports = StringClient;
StringClient.prototype.post = function post(options, body, callback) {
- var opts = this._options('POST', options);
- if (typeof (body) === 'function') {
- callback = body;
- body = null;
- }
+ var opts = this._options('POST', options);
+ if (typeof (body) === 'function') {
+ callback = body;
+ body = null;
+ }
- return (this.write(opts, body, callback));
+ return (this.write(opts, body, callback));
};
StringClient.prototype.put = function put(options, body, callback) {
- var opts = this._options('PUT', options);
- if (typeof (body) === 'function') {
- callback = body;
- body = null;
- }
+ var opts = this._options('PUT', options);
+ if (typeof (body) === 'function') {
+ callback = body;
+ body = null;
+ }
- return (this.write(opts, body, callback));
+ return (this.write(opts, body, callback));
};
StringClient.prototype.patch = function patch(options, body, callback) {
- var opts = this._options('PATCH', options);
- if (typeof (body) === 'function') {
- callback = body;
- body = null;
- }
+ var opts = this._options('PATCH', options);
+ if (typeof (body) === 'function') {
+ callback = body;
+ body = null;
+ }
- return (this.write(opts, body, callback));
+ return (this.write(opts, body, callback));
};
StringClient.prototype.read = function read(options, callback) {
- var self = this;
- this.request(options, function _parse(err, req) {
- if (err)
- return (callback(err, req));
-
- req.once('result', self.parse(req, callback));
- return (req.end());
- });
- return (this);
+ var self = this;
+ this.request(options, function _parse(err, req) {
+ if (err)
+ return (callback(err, req));
+
+ req.once('result', self.parse(req, callback));
+ return (req.end());
+ });
+ return (this);
};
StringClient.prototype.write = function write(options, body, callback) {
- if (body !== null && typeof (body) !== 'string')
- body = qs.stringify(body);
+ if (body !== null && typeof (body) !== 'string')
+ body = qs.stringify(body);
- var self = this;
+ var self = this;
- function _write(data) {
- if (data) {
- var hash = crypto.createHash('md5');
- hash.update(data, 'utf8');
- options.headers['content-md5'] = hash.digest('base64');
- }
-
- self.request(options, function (err, req) {
- if (err) {
- callback(err, req);
- return;
- }
-
- req.once('result', self.parse(req, callback));
- req.end(data);
- });
+ function _write(data) {
+ if (data) {
+ var hash = crypto.createHash('md5');
+ hash.update(data, 'utf8');
+ options.headers['content-md5'] = hash.digest('base64');
}
- options.headers = options.headers || {};
+ self.request(options, function (err, req) {
+ if (err) {
+ callback(err, req);
+ return;
+ }
+
+ req.once('result', self.parse(req, callback));
+ req.end(data);
+ });
+ }
- if (this.gzip)
- options.headers['accept-encoding'] = 'gzip';
+ options.headers = options.headers || {};
- if (body) {
- if (this.gzip) {
- options.headers['content-encoding'] = 'gzip';
- zlib.gzip(body, function (err, data) {
- if (err) {
- callback(err, null);
- return;
- }
+ if (this.gzip)
+ options.headers['accept-encoding'] = 'gzip';
- options.headers['content-length'] = data.length;
- _write(data);
- });
- } else {
- options.headers['content-length'] =
- Buffer.byteLength(body);
- _write(body);
+ if (body) {
+ if (this.gzip) {
+ options.headers['content-encoding'] = 'gzip';
+ zlib.gzip(body, function (err, data) {
+ if (err) {
+ callback(err, null);
+ return;
}
+
+ options.headers['content-length'] = data.length;
+ _write(data);
+ });
} else {
- _write();
+ options.headers['content-length'] =
+ Buffer.byteLength(body);
+ _write(body);
}
+ } else {
+ _write();
+ }
- return (this);
+ return (this);
};
StringClient.prototype.parse = function parse(req, callback) {
- function parseResponse(err, res) {
- if (res) {
- function done() {
- res.log.trace('body received:\n%s', body);
- res.body = body;
- if (hash && md5 !== hash.digest('base64')) {
- err = new Error('BadDigest');
- callback(err, req, res);
- return;
- }
-
- if (err) {
- err.body = body;
- err.message = body;
- }
-
- callback(err, req, res, body);
- }
-
- var body = '';
- var gz;
- var hash;
- var md5 = res.headers['content-md5'];
- if (md5 && req.method !== 'HEAD')
- hash = crypto.createHash('md5');
-
- if (res.headers['content-encoding'] === 'gzip') {
- gz = zlib.createGunzip();
- gz.on('data', function (chunk) {
- body += chunk.toString('utf8');
- });
- gz.once('end', done);
- res.once('end', gz.end.bind(gz));
- } else {
- res.setEncoding('utf8');
- res.once('end', done);
- }
-
- res.on('data', function onData(chunk) {
- if (hash)
- hash.update(chunk);
-
- if (gz) {
- gz.write(chunk);
- } else {
- body += chunk;
- }
- });
+ function parseResponse(err, res) {
+ if (res) {
+ function done() {
+ res.log.trace('body received:\n%s', body);
+ res.body = body;
+ if (hash && md5 !== hash.digest('base64')) {
+ err = new Error('BadDigest');
+ callback(err, req, res);
+ return;
+ }
+
+ if (err) {
+ err.body = body;
+ err.message = body;
+ }
+ callback(err, req, res, body);
+ }
+
+ var body = '';
+ var gz;
+ var hash;
+ var md5 = res.headers['content-md5'];
+ if (md5 && req.method !== 'HEAD')
+ hash = crypto.createHash('md5');
+
+ if (res.headers['content-encoding'] === 'gzip') {
+ gz = zlib.createGunzip();
+ gz.on('data', function (chunk) {
+ body += chunk.toString('utf8');
+ });
+ gz.once('end', done);
+ res.once('end', gz.end.bind(gz));
+ } else {
+ res.setEncoding('utf8');
+ res.once('end', done);
+ }
+
+ res.on('data', function onData(chunk) {
+ if (hash)
+ hash.update(chunk);
+
+ if (gz) {
+ gz.write(chunk);
} else {
- callback(err, req, null, null);
+ body += chunk;
}
+ });
+
+ } else {
+ callback(err, req, null, null);
}
+ }
- return (parseResponse);
+ return (parseResponse);
};
diff --git a/lib/dtrace.js b/lib/dtrace.js
index 9f41d1dee..411eb620b 100644
--- a/lib/dtrace.js
+++ b/lib/dtrace.js
@@ -1,79 +1,82 @@
// Copyright 2012 Mark Cavage, Inc. All rights reserved.
-
///--- Globals
var ID = 0;
var MAX_INT = Math.pow(2, 32) - 1;
var PROBES = {
- // server_name, route_name, id, method, url, headers (json)
- 'route-start': ['char *', 'char *', 'int', 'char *', 'char *', 'json'],
+ // server_name, route_name, id, method, url, headers (json)
+ 'route-start': ['char *', 'char *', 'int', 'char *', 'char *', 'json'],
- // server_name, route_name, handler_name, id
- 'handler-start': ['char *', 'char *', 'char *', 'int'],
+ // server_name, route_name, handler_name, id
+ 'handler-start': ['char *', 'char *', 'char *', 'int'],
- // server_name, route_name, handler_name, id
- 'handler-done': ['char *', 'char *', 'char *', 'int'],
+ // server_name, route_name, handler_name, id
+ 'handler-done': ['char *', 'char *', 'char *', 'int'],
- // server_name, route_name, id, statusCode, headers (json)
- 'route-done': ['char *', 'char *', 'int', 'int', 'json'],
+ // 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 *']
+ // 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 *']
};
var PROVIDER;
-
///--- API
module.exports = function exportStaticProvider() {
- if (!PROVIDER) {
- try {
- var dtrace = require('dtrace-provider');
- PROVIDER = dtrace.createDTraceProvider('restify');
- } catch (e) {
- PROVIDER = {
- fire: function () {},
- enable: function () {},
- addProbe: function () {
- var p = {
- fire: function () {}
- };
- return (p);
- },
- removeProbe: function () {},
- disable: function () {}
- };
+ if (!PROVIDER) {
+ try {
+ var dtrace = require('dtrace-provider');
+ PROVIDER = dtrace.createDTraceProvider('restify');
+ } catch (e) {
+ PROVIDER = {
+ fire: function () {
+ },
+ enable: function () {
+ },
+ addProbe: function () {
+ var p = {
+ fire: function () {
+ }
+ };
+ return (p);
+ },
+ removeProbe: function () {
+ },
+ disable: function () {
}
+ };
+ }
- PROVIDER._rstfy_probes = {};
+ PROVIDER._rstfy_probes = {};
- Object.keys(PROBES).forEach(function (p) {
- var args = PROBES[p].splice(0);
- args.unshift(p);
+ Object.keys(PROBES).forEach(function (p) {
+ var args = PROBES[p].splice(0);
+ args.unshift(p);
- var probe = PROVIDER.addProbe.apply(PROVIDER, args);
- PROVIDER._rstfy_probes[p] = probe;
- });
+ var probe = PROVIDER.addProbe.apply(PROVIDER, args);
+ PROVIDER._rstfy_probes[p] = probe;
+ });
- PROVIDER.enable();
+ PROVIDER.enable();
- PROVIDER.nextId = function nextId() {
- if (++ID >= MAX_INT)
- ID = 1;
+ PROVIDER.nextId = function nextId() {
+ if (++ID >= MAX_INT)
+ ID = 1;
- return (ID);
- };
- }
+ return (ID);
+ };
+ }
- return (PROVIDER);
+ return (PROVIDER);
}();
diff --git a/lib/errors/http_error.js b/lib/errors/http_error.js
index 514bff7df..0cd1c0f05 100644
--- a/lib/errors/http_error.js
+++ b/lib/errors/http_error.js
@@ -7,127 +7,122 @@ var assert = require('assert-plus');
var WError = require('verror').WError;
-
///--- Globals
var slice = Function.prototype.call.bind(Array.prototype.slice);
-
///--- Helpers
function codeToErrorName(code) {
- code = parseInt(code, 10);
- var status = http.STATUS_CODES[code];
- if (!status)
- return (false);
+ code = parseInt(code, 10);
+ var status = http.STATUS_CODES[code];
+ if (!status)
+ return (false);
- var pieces = status.split(/\s+/);
- var str = '';
- pieces.forEach(function (s) {
- str += s.charAt(0).toUpperCase() + s.slice(1).toLowerCase();
- });
+ var pieces = status.split(/\s+/);
+ var str = '';
+ pieces.forEach(function (s) {
+ str += s.charAt(0).toUpperCase() + s.slice(1).toLowerCase();
+ });
- str = str.replace(/\W+/g, '');
- if (!/\w+Error$/.test(str))
- str += 'Error';
+ str = str.replace(/\W+/g, '');
+ if (!/\w+Error$/.test(str))
+ str += 'Error';
- return (str);
+ return (str);
}
-
///--- Error Base class
function HttpError(options) {
- assert.object(options, 'options');
-
- options.constructorOpt = options.constructorOpt || HttpError;
- WError.apply(this, arguments);
-
- var self = this;
- var code = parseInt((options.statusCode || 500), 10);
- this.statusCode = code;
- this.body = options.body || {
- code: codeToErrorName(code),
- message: options.message || self.message
- };
- this.message = options.message || self.message;
+ assert.object(options, 'options');
+
+ options.constructorOpt = options.constructorOpt || HttpError;
+ WError.apply(this, arguments);
+
+ var self = this;
+ var code = parseInt((options.statusCode || 500), 10);
+ this.statusCode = code;
+ this.body = options.body || {
+ code: codeToErrorName(code),
+ message: options.message || self.message
+ };
+ this.message = options.message || self.message;
}
util.inherits(HttpError, WError);
-
///--- Exports
module.exports = {
- HttpError: HttpError,
-
- codeToHttpError: function codeToHttpError(code, message, body) {
- var err;
- var name = codeToErrorName(code);
-
- if (!name) {
- err = new HttpError({
- statusCode: code,
- message: message,
- body: body
- });
- err.name = 'Http' + code + 'Error';
- } else {
- err = new module.exports[name]({
- body: body,
- message: message,
- constructorOpt: codeToHttpError,
- statusCode: code
- });
- }
-
- return (err);
+ HttpError: HttpError,
+
+ codeToHttpError: function codeToHttpError(code, message, body) {
+ var err;
+ var name = codeToErrorName(code);
+
+ if (!name) {
+ err = new HttpError({
+ statusCode: code,
+ message: message,
+ body: body
+ });
+ err.name = 'Http' + code + 'Error';
+ } else {
+ err = new module.exports[name]({
+ body: body,
+ message: message,
+ constructorOpt: codeToHttpError,
+ statusCode: code
+ });
}
-};
+ return (err);
+ }
+};
// Export all the 4xx and 5xx HTTP Status codes as Errors
var codes = Object.keys(http.STATUS_CODES);
codes.forEach(function (code) {
- if (code < 400)
- return;
+ if (code < 400)
+ return;
- var name = codeToErrorName(code);
+ var name = codeToErrorName(code);
- module.exports[name] = function (cause, message) {
- var index = 1;
- var opts = {
- statusCode: code
- };
-
- if (cause && cause instanceof Error) {
- opts.cause = cause;
- opts.constructorOpt = arguments.callee;
- } else if (typeof (cause) === 'object') {
- opts.body = cause.body;
- opts.cause = cause.cause;
- opts.constructorOpt = cause.constructorOpt;
- opts.message = cause.message;
- opts.statusCode = cause.statusCode || code;
- } else {
- opts.constructorOpt = arguments.callee;
- index = 0;
- }
-
- var args = slice(arguments, index);
- args.unshift(opts);
- HttpError.apply(this, args);
+ module.exports[name] = function (cause, message) {
+ var index = 1;
+ var opts = {
+ statusCode: code
};
- util.inherits(module.exports[name], HttpError);
- module.exports[name].displayName =
- module.exports[name].prototype.name =
- name;
+ if (cause && cause instanceof Error) {
+ opts.cause = cause;
+ opts.constructorOpt = arguments.callee;
+ } else if (typeof (cause) === 'object') {
+ opts.body = cause.body;
+ opts.cause = cause.cause;
+ opts.constructorOpt = cause.constructorOpt;
+ opts.message = cause.message;
+ opts.statusCode = cause.statusCode || code;
+ } else {
+ opts.constructorOpt = arguments.callee;
+ index = 0;
+ }
+
+ var args = slice(arguments, index);
+ args.unshift(opts);
+ HttpError.apply(this, args);
+ };
+ util.inherits(module.exports[name], HttpError);
+
+ module.exports[name].displayName =
+ module.exports[name].prototype.name =
+ name;
});
diff --git a/lib/errors/index.js b/lib/errors/index.js
index a3fc36307..74561ccd0 100644
--- a/lib/errors/index.js
+++ b/lib/errors/index.js
@@ -7,10 +7,10 @@ var restErrors = require('./rest_error');
module.exports = {};
Object.keys(httpErrors).forEach(function (k) {
- module.exports[k] = httpErrors[k];
+ module.exports[k] = httpErrors[k];
});
// Note some of the RestErrors overwrite plain HTTP errors.
Object.keys(restErrors).forEach(function (k) {
- module.exports[k] = restErrors[k];
+ module.exports[k] = restErrors[k];
});
diff --git a/lib/errors/rest_error.js b/lib/errors/rest_error.js
index 5f45058ac..1bda98720 100644
--- a/lib/errors/rest_error.js
+++ b/lib/errors/rest_error.js
@@ -7,7 +7,6 @@ var assert = require('assert-plus');
var httpErrors = require('./http_error');
-
///--- Globals
var slice = Function.prototype.call.bind(Array.prototype.slice);
@@ -15,81 +14,79 @@ var slice = Function.prototype.call.bind(Array.prototype.slice);
var HttpError = httpErrors.HttpError;
var CODES = {
- BadDigest: 400,
- BadMethod: 405,
- Internal: 500, // Don't have InternalErrorError
- InvalidArgument: 409,
- InvalidContent: 400,
- InvalidCredentials: 401,
- InvalidHeader: 400,
- InvalidVersion: 400,
- MissingParameter: 409,
- NotAuthorized: 403,
- PreconditionFailed: 412,
- RequestExpired: 400,
- RequestThrottled: 429,
- ResourceNotFound: 404,
- WrongAccept: 406
+ BadDigest: 400,
+ BadMethod: 405,
+ Internal: 500, // Don't have InternalErrorError
+ InvalidArgument: 409,
+ InvalidContent: 400,
+ InvalidCredentials: 401,
+ InvalidHeader: 400,
+ InvalidVersion: 400,
+ MissingParameter: 409,
+ NotAuthorized: 403,
+ PreconditionFailed: 412,
+ RequestExpired: 400,
+ RequestThrottled: 429,
+ ResourceNotFound: 404,
+ WrongAccept: 406
};
-
///--- API
function RestError(options) {
- assert.object(options, 'options');
+ assert.object(options, 'options');
- options.constructorOpt = options.constructorOpt || RestError;
- HttpError.apply(this, arguments);
+ options.constructorOpt = options.constructorOpt || RestError;
+ HttpError.apply(this, arguments);
- var self = this;
- this.restCode = options.restCode || 'Error';
- this.body = options.body || {
- code: self.restCode,
- message: options.message || self.message
- };
+ var self = this;
+ this.restCode = options.restCode || 'Error';
+ this.body = options.body || {
+ code: self.restCode,
+ message: options.message || self.message
+ };
}
util.inherits(RestError, HttpError);
-
///--- Exports
module.exports = {
- RestError: RestError
+ RestError: RestError
};
Object.keys(CODES).forEach(function (k) {
- var name = k;
- if (!/\w+Error$/.test(name))
- name += 'Error';
-
- module.exports[name] = function (cause, message) {
- var index = 1;
- var opts = {
- restCode: (k === 'Internal' ? 'InternalError' : k),
- statusCode: CODES[k]
- };
-
- opts.constructorOpt = arguments.callee;
-
- if (cause && cause instanceof Error) {
- opts.cause = cause;
- } else if (typeof (cause) === 'object') {
- opts.body = cause.body;
- opts.cause = cause.cause;
- opts.message = cause.message;
- opts.statusCode = cause.statusCode || CODES[k];
- } else {
- index = 0;
- }
-
- var args = slice(arguments, index);
- args.unshift(opts);
- RestError.apply(this, args);
+ var name = k;
+ if (!/\w+Error$/.test(name))
+ name += 'Error';
+
+ module.exports[name] = function (cause, message) {
+ var index = 1;
+ var opts = {
+ restCode: (k === 'Internal' ? 'InternalError' : k),
+ statusCode: CODES[k]
};
- util.inherits(module.exports[name], RestError);
- module.exports[name].displayName =
- module.exports[name].prototype.name =
- name;
+
+ opts.constructorOpt = arguments.callee;
+
+ if (cause && cause instanceof Error) {
+ opts.cause = cause;
+ } else if (typeof (cause) === 'object') {
+ opts.body = cause.body;
+ opts.cause = cause.cause;
+ opts.message = cause.message;
+ opts.statusCode = cause.statusCode || CODES[k];
+ } else {
+ index = 0;
+ }
+
+ var args = slice(arguments, index);
+ args.unshift(opts);
+ RestError.apply(this, args);
+ };
+ util.inherits(module.exports[name], RestError);
+ module.exports[name].displayName =
+ module.exports[name].prototype.name =
+ name;
});
diff --git a/lib/formatters/binary.js b/lib/formatters/binary.js
index 5cd81e67f..d8b4d12e7 100644
--- a/lib/formatters/binary.js
+++ b/lib/formatters/binary.js
@@ -1,18 +1,17 @@
// Copyright 2012 Mark Cavage, Inc. All rights reserved.
-
///--- Exports
function formatBinary(req, res, body) {
- if (body instanceof Error)
- res.statusCode = body.statusCode || 500;
+ if (body instanceof Error)
+ res.statusCode = body.statusCode || 500;
- if (!Buffer.isBuffer(body))
- body = new Buffer(body.toString());
+ if (!Buffer.isBuffer(body))
+ body = new Buffer(body.toString());
- res.setHeader('Content-Length', body.length);
- return (body);
+ res.setHeader('Content-Length', body.length);
+ return (body);
}
module.exports = formatBinary;
\ No newline at end of file
diff --git a/lib/formatters/index.js b/lib/formatters/index.js
index 4fa9b9a42..290e30ae1 100644
--- a/lib/formatters/index.js
+++ b/lib/formatters/index.js
@@ -1,12 +1,11 @@
// Copyright 2012 Mark Cavage, Inc. All rights reserved.
-
///--- Exports
module.exports = {
- 'application/javascript; q=0.1': require('./jsonp'),
- 'application/json; q=0.4': require('./json'),
- 'text/plain; q=0.3': require('./text'),
- 'application/octet-stream; q=0.2': require('./binary')
+ 'application/javascript; q=0.1': require('./jsonp'),
+ 'application/json; q=0.4': require('./json'),
+ 'text/plain; q=0.3': require('./text'),
+ 'application/octet-stream; q=0.2': require('./binary')
};
diff --git a/lib/formatters/json.js b/lib/formatters/json.js
index 7508e981b..cf4ca6d6e 100644
--- a/lib/formatters/json.js
+++ b/lib/formatters/json.js
@@ -1,30 +1,29 @@
// Copyright 2012 Mark Cavage, Inc. All rights reserved.
-
///--- Exports
function formatJSON(req, res, body) {
- if (body instanceof Error) {
- // snoop for RestError or HttpError, but don't rely on
- // instanceof
- res.statusCode = body.statusCode || 500;
-
- if (body.body) {
- body = body.body;
- } else {
- body = {
- message: body.message
- };
- }
- } else if (Buffer.isBuffer(body)) {
- body = body.toString('base64');
+ if (body instanceof Error) {
+ // snoop for RestError or HttpError, but don't rely on
+ // instanceof
+ res.statusCode = body.statusCode || 500;
+
+ if (body.body) {
+ body = body.body;
+ } else {
+ body = {
+ message: body.message
+ };
}
+ } else if (Buffer.isBuffer(body)) {
+ body = body.toString('base64');
+ }
- var data = JSON.stringify(body);
- res.setHeader('Content-Length', Buffer.byteLength(data));
+ var data = JSON.stringify(body);
+ res.setHeader('Content-Length', Buffer.byteLength(data));
- return (data);
+ return (data);
}
module.exports = formatJSON;
diff --git a/lib/formatters/jsonp.js b/lib/formatters/jsonp.js
index 96b71216c..cb8729bb0 100644
--- a/lib/formatters/jsonp.js
+++ b/lib/formatters/jsonp.js
@@ -1,38 +1,37 @@
// Copyright 2012 Mark Cavage, Inc. All rights reserved.
-
///--- Exports
function formatJSONP(req, res, body) {
- if (!body) {
- res.setHeader('Content-Length', 0);
- return (null);
- }
-
- if (body instanceof Error) {
- if ((body.restCode || body.httpCode) && body.body) {
- body = body.body;
- } else {
- body = {
- message: body.message
- };
- }
+ if (!body) {
+ res.setHeader('Content-Length', 0);
+ return (null);
+ }
+
+ if (body instanceof Error) {
+ if ((body.restCode || body.httpCode) && body.body) {
+ body = body.body;
+ } else {
+ body = {
+ message: body.message
+ };
}
+ }
- if (Buffer.isBuffer(body))
- body = body.toString('base64');
+ if (Buffer.isBuffer(body))
+ body = body.toString('base64');
- var cb = req.query.callback || req.query.jsonp;
- var data;
- if (cb) {
- data = cb + '(' + JSON.stringify(body) + ');';
- } else {
- data = JSON.stringify(body);
- }
+ var cb = req.query.callback || req.query.jsonp;
+ var data;
+ if (cb) {
+ data = cb + '(' + JSON.stringify(body) + ');';
+ } else {
+ data = JSON.stringify(body);
+ }
- res.setHeader('Content-Length', Buffer.byteLength(data));
- return (data);
+ res.setHeader('Content-Length', Buffer.byteLength(data));
+ return (data);
}
module.exports = formatJSONP;
diff --git a/lib/formatters/text.js b/lib/formatters/text.js
index d59817fcc..4a8564153 100644
--- a/lib/formatters/text.js
+++ b/lib/formatters/text.js
@@ -1,21 +1,20 @@
// Copyright 2012 Mark Cavage, Inc. All rights reserved.
-
///--- Exports
function formatText(req, res, body) {
- if (body instanceof Error) {
- res.statusCode = body.statusCode || 500;
- body = body.message;
- } else if (typeof (body) === 'object') {
- body = JSON.stringify(body);
- } else {
- body = body.toString();
- }
+ if (body instanceof Error) {
+ res.statusCode = body.statusCode || 500;
+ body = body.message;
+ } else if (typeof (body) === 'object') {
+ body = JSON.stringify(body);
+ } else {
+ body = body.toString();
+ }
- res.setHeader('Content-Length', Buffer.byteLength(body));
- return (body);
+ res.setHeader('Content-Length', Buffer.byteLength(body));
+ return (body);
}
module.exports = formatText;
diff --git a/lib/http_date.js b/lib/http_date.js
index 18ab3fbfa..c74398e45 100644
--- a/lib/http_date.js
+++ b/lib/http_date.js
@@ -1,8 +1,8 @@
// Copyright 2012 Mark Cavage, Inc. All rights reserved.
module.exports = function httpDate(now) {
- if (!now)
- now = new Date();
+ if (!now)
+ now = new Date();
- return (now.toUTCString());
+ return (now.toUTCString());
};
diff --git a/lib/index.js b/lib/index.js
index bb16f3a19..0ced3d8e5 100644
--- a/lib/index.js
+++ b/lib/index.js
@@ -11,84 +11,84 @@ var shallowCopy = require('./utils').shallowCopy;
function createClient(options) {
- var assert = require('assert-plus');
- var bunyan = require('./bunyan_helper');
- var clients = require('./clients');
+ var assert = require('assert-plus');
+ var bunyan = require('./bunyan_helper');
+ var clients = require('./clients');
- assert.object(options, 'options');
+ assert.object(options, 'options');
- var client;
- var opts = shallowCopy(options);
- opts.agent = options.agent;
- opts.name = opts.name || 'restify';
- opts.type = opts.type || 'application/octet-stream';
- opts.log = opts.log || bunyan.createLogger(opts.name);
+ var client;
+ var opts = shallowCopy(options);
+ opts.agent = options.agent;
+ opts.name = opts.name || 'restify';
+ opts.type = opts.type || 'application/octet-stream';
+ opts.log = opts.log || bunyan.createLogger(opts.name);
- switch (opts.type) {
+ switch (opts.type) {
case 'json':
- client = new clients.JsonClient(opts);
- break;
+ client = new clients.JsonClient(opts);
+ break;
case 'string':
- client = new clients.StringClient(opts);
- break;
+ client = new clients.StringClient(opts);
+ break;
case 'http':
default:
- client = new clients.HttpClient(opts);
- break;
- }
+ client = new clients.HttpClient(opts);
+ break;
+ }
- return (client);
+ return (client);
}
function createJsonClient(options) {
- options = options ? shallowCopy(options) : {};
- options.type = 'json';
- return (createClient(options));
+ options = options ? shallowCopy(options) : {};
+ options.type = 'json';
+ return (createClient(options));
}
function createStringClient(options) {
- options = options ? shallowCopy(options) : {};
- options.type = 'string';
- return (createClient(options));
+ options = options ? shallowCopy(options) : {};
+ options.type = 'string';
+ return (createClient(options));
}
function createHttpClient(options) {
- options = options ? shallowCopy(options) : {};
- options.type = 'http';
- return (createClient(options));
+ options = options ? shallowCopy(options) : {};
+ options.type = 'http';
+ return (createClient(options));
}
function createServer(options) {
- var bunyan = require('./bunyan_helper');
- var InternalError = require('./errors').InternalError;
- var Router = require('./router');
- var Server = require('./server');
-
- var opts = shallowCopy(options || {});
- var server;
-
- opts.name = opts.name || 'restify';
- opts.log = opts.log || bunyan.createLogger(opts.name);
- opts.router = opts.router || new Router(opts);
-
- server = new Server(opts);
- server.on('uncaughtException', function (req, res, route, e) {
- if (this.listeners('uncaughtException').length > 1 ||
- res._headerSent) {
- return (false);
- }
-
- res.send(new InternalError(e, e.message || 'unexpected error'));
- return (true);
- });
-
- return (server);
+ var bunyan = require('./bunyan_helper');
+ var InternalError = require('./errors').InternalError;
+ var Router = require('./router');
+ var Server = require('./server');
+
+ var opts = shallowCopy(options || {});
+ var server;
+
+ opts.name = opts.name || 'restify';
+ opts.log = opts.log || bunyan.createLogger(opts.name);
+ opts.router = opts.router || new Router(opts);
+
+ server = new Server(opts);
+ server.on('uncaughtException', function (req, res, route, e) {
+ if (this.listeners('uncaughtException').length > 1 ||
+ res._headerSent) {
+ return (false);
+ }
+
+ res.send(new InternalError(e, e.message || 'unexpected error'));
+ return (true);
+ });
+
+ return (server);
}
@@ -101,60 +101,59 @@ function createServer(options) {
* @param {Object} a hash of parameter names to values for substitution.
*/
function realizeUrl(pattern, params) {
- var p = pattern.replace(/\/:([^/]+)/g, function (match, k) {
- return (params.hasOwnProperty(k) ? '/' + params[k] : match);
- });
+ var p = pattern.replace(/\/:([^/]+)/g, function (match, k) {
+ return (params.hasOwnProperty(k) ? '/' + params[k] : match);
+ });
- return (require('./utils').sanitizePath(p));
+ return (require('./utils').sanitizePath(p));
}
-
///--- Exports
module.exports = {
- // Client API
- createClient: createClient,
- createJsonClient: createJsonClient,
- createJSONClient: createJsonClient,
- createStringClient: createStringClient,
- createHttpClient: createHttpClient,
- get HttpClient() {
- return (require('./clients').HttpClient);
- },
- get JsonClient() {
- return (require('./clients').JsonClient);
- },
- get StringClient() {
- return (require('./clients').StringClient);
- },
-
- // Miscellaneous API
- get bunyan() {
- return (require('./bunyan_helper'));
- },
-
- errors: {}
+ // Client API
+ createClient: createClient,
+ createJsonClient: createJsonClient,
+ createJSONClient: createJsonClient,
+ createStringClient: createStringClient,
+ createHttpClient: createHttpClient,
+ get HttpClient() {
+ return (require('./clients').HttpClient);
+ },
+ get JsonClient() {
+ return (require('./clients').JsonClient);
+ },
+ get StringClient() {
+ return (require('./clients').StringClient);
+ },
+
+ // Miscellaneous API
+ get bunyan() {
+ return (require('./bunyan_helper'));
+ },
+
+ errors: {}
};
var errors = require('./errors');
Object.keys(errors).forEach(function (k) {
- module.exports.errors[k] = errors[k];
- module.exports[k] = errors[k];
+ module.exports.errors[k] = errors[k];
+ module.exports[k] = errors[k];
});
if (!process.env.RESTIFY_CLIENT_ONLY) {
- module.exports.createServer = createServer;
- module.exports.httpDate = require('./http_date');
- module.exports.realizeUrl = realizeUrl;
- module.exports.formatters = require('./formatters');
- module.exports.plugins = {};
- var plugins = require('./plugins');
- Object.keys(plugins).forEach(function (k) {
- module.exports.plugins[k] = plugins[k];
- module.exports[k] = plugins[k];
- });
+ module.exports.createServer = createServer;
+ module.exports.httpDate = require('./http_date');
+ module.exports.realizeUrl = realizeUrl;
+ module.exports.formatters = require('./formatters');
+ module.exports.plugins = {};
+ var plugins = require('./plugins');
+ Object.keys(plugins).forEach(function (k) {
+ module.exports.plugins[k] = plugins[k];
+ module.exports[k] = plugins[k];
+ });
}
diff --git a/lib/plugins/accept.js b/lib/plugins/accept.js
index 0ac16d6ce..e75b176b9 100644
--- a/lib/plugins/accept.js
+++ b/lib/plugins/accept.js
@@ -18,31 +18,31 @@ var NotAcceptableError = require('../errors').NotAcceptableError;
* @throws {TypeError} on bad input
*/
function acceptParser(acceptable) {
- if (!Array.isArray(acceptable))
- acceptable = [acceptable];
- assert.arrayOfString(acceptable, 'acceptable');
-
- acceptable = acceptable.filter(function (a) {
- return (a);
- }).map(function (a) {
- return ((a.indexOf('/') === -1) ? mime.lookup(a) : a);
+ if (!Array.isArray(acceptable))
+ acceptable = [acceptable];
+ assert.arrayOfString(acceptable, 'acceptable');
+
+ acceptable = acceptable.filter(function (a) {
+ return (a);
+ }).map(function (a) {
+ return ((a.indexOf('/') === -1) ? mime.lookup(a) : a);
}).filter(function (a) {
- return (a);
+ return (a);
});
- var e = new NotAcceptableError('Server accepts: ' + acceptable.join());
+ var e = new NotAcceptableError('Server accepts: ' + acceptable.join());
- function parseAccept(req, res, next) {
- if (req.accepts(acceptable)) {
- next();
- return;
- }
-
- res.json(e);
- next(false);
+ function parseAccept(req, res, next) {
+ if (req.accepts(acceptable)) {
+ next();
+ return;
}
- return (parseAccept);
+ res.json(e);
+ next(false);
+ }
+
+ return (parseAccept);
}
module.exports = acceptParser;
diff --git a/lib/plugins/audit.js b/lib/plugins/audit.js
index eae888e86..fef658300 100644
--- a/lib/plugins/audit.js
+++ b/lib/plugins/audit.js
@@ -20,87 +20,86 @@ var HttpError = require('../errors').HttpError;
* @return {Function} to be used in server.after.
*/
function auditLogger(options) {
- assert.object(options, 'options');
- assert.object(options.log, 'options.log');
-
- var log = options.log.child({
- audit: true,
- serializers: {
- err: bunyan.stdSerializers.err,
- req: function auditRequestSerializer(req) {
- if (!req)
- return (false);
-
- var timers = {};
- (req.timers || []).forEach(function (time) {
- var t = time.time;
- var _t = Math.floor((1000000 * t[0]) +
- (t[1] / 1000));
- timers[time.name] = _t;
- });
- return ({
- method: req.method,
- url: req.url,
- headers: req.headers,
- httpVersion: req.httpVersion,
- trailers: req.trailers,
- version: req.version,
- body: options.body === true ?
- req.body : undefined,
- timers: timers
- });
- },
- res: function auditResponseSerializer(res) {
- if (!res)
- return (false);
-
-
- var body;
- if (options.body === true) {
- if (res._body instanceof HttpError) {
- body = res._body.body;
- } else {
- body = res._body;
- }
- }
-
- return ({
- statusCode: res.statusCode,
- headers: res._headers,
- trailer: res._trailer || false,
- body: body
- });
- }
+ assert.object(options, 'options');
+ assert.object(options.log, 'options.log');
+
+ var log = options.log.child({
+ audit: true,
+ serializers: {
+ err: bunyan.stdSerializers.err,
+ req: function auditRequestSerializer(req) {
+ if (!req)
+ return (false);
+
+ var timers = {};
+ (req.timers || []).forEach(function (time) {
+ var t = time.time;
+ var _t = Math.floor((1000000 * t[0]) +
+ (t[1] / 1000));
+ timers[time.name] = _t;
+ });
+ return ({
+ method: req.method,
+ url: req.url,
+ headers: req.headers,
+ httpVersion: req.httpVersion,
+ trailers: req.trailers,
+ version: req.version,
+ body: options.body === true ?
+ req.body : undefined,
+ timers: timers
+ });
+ },
+ res: function auditResponseSerializer(res) {
+ if (!res)
+ return (false);
+
+
+ var body;
+ if (options.body === true) {
+ if (res._body instanceof HttpError) {
+ body = res._body.body;
+ } else {
+ body = res._body;
+ }
}
- });
-
- function audit(req, res, route, err) {
- var latency = res.get('Response-Time');
- if (typeof (latency) !== 'number')
- latency = Date.now() - req._time;
-
- var obj = {
- remoteAddress: req.connection.remoteAddress,
- remotePort: req.connection.remotePort,
- req_id: req.getId(),
- req: req,
- res: res,
- err: err,
- latency: latency,
- secure: req.secure,
- _audit: true
- };
-
- log.info(obj, 'handled: %d', res.statusCode);
-
- return (true);
- }
- return (audit);
+ return ({
+ statusCode: res.statusCode,
+ headers: res._headers,
+ trailer: res._trailer || false,
+ body: body
+ });
+ }
+ }
+ });
+
+ function audit(req, res, route, err) {
+ var latency = res.get('Response-Time');
+ if (typeof (latency) !== 'number')
+ latency = Date.now() - req._time;
+
+ var obj = {
+ remoteAddress: req.connection.remoteAddress,
+ remotePort: req.connection.remotePort,
+ req_id: req.getId(),
+ req: req,
+ res: res,
+ err: err,
+ latency: latency,
+ secure: req.secure,
+ _audit: true
+ };
+
+ log.info(obj, 'handled: %d', res.statusCode);
+
+ return (true);
+ }
+
+ return (audit);
}
-
///-- Exports
module.exports = auditLogger;
diff --git a/lib/plugins/authorization.js b/lib/plugins/authorization.js
index 000f73313..3b225fc99 100644
--- a/lib/plugins/authorization.js
+++ b/lib/plugins/authorization.js
@@ -5,74 +5,71 @@ var httpSignature = require('http-signature');
var errors = require('../errors');
-
///--- Globals
var InvalidHeaderError = errors.InvalidHeaderError;
var OPTIONS = {
- algorithms: [
- 'rsa-sha1',
- 'rsa-sha256',
- 'rsa-sha512',
- 'dsa-sha1',
- 'hmac-sha1',
- 'hmac-sha256',
- 'hmac-sha512'
- ]
+ algorithms: [
+ 'rsa-sha1',
+ 'rsa-sha256',
+ 'rsa-sha512',
+ 'dsa-sha1',
+ 'hmac-sha1',
+ 'hmac-sha256',
+ 'hmac-sha512'
+ ]
};
-
///--- Helpers
function parseBasic(string) {
- var decoded;
- var index;
- var pieces;
-
- decoded = (new Buffer(string, 'base64')).toString('utf8');
- if (!decoded)
- throw new InvalidHeaderError('Authorization header invalid');
-
- index = decoded.indexOf(':');
- if (index === -1) {
- pieces = [decoded];
- } else {
- pieces = [decoded.slice(0, index), decoded.slice(index + 1)];
- }
-
- if (!pieces || typeof (pieces[0]) !== 'string')
- throw new InvalidHeaderError('Authorization header invalid');
-
- // Allows for usernameless authentication
- if (!pieces[0])
- pieces[0] = null;
-
- // Allows for passwordless authentication
- if (!pieces[1])
- pieces[1] = null;
-
- return ({
- username: pieces[0],
- password: pieces[1]
- });
+ var decoded;
+ var index;
+ var pieces;
+
+ decoded = (new Buffer(string, 'base64')).toString('utf8');
+ if (!decoded)
+ throw new InvalidHeaderError('Authorization header invalid');
+
+ index = decoded.indexOf(':');
+ if (index === -1) {
+ pieces = [decoded];
+ } else {
+ pieces = [decoded.slice(0, index), decoded.slice(index + 1)];
+ }
+
+ if (!pieces || typeof (pieces[0]) !== 'string')
+ throw new InvalidHeaderError('Authorization header invalid');
+
+ // Allows for usernameless authentication
+ if (!pieces[0])
+ pieces[0] = null;
+
+ // Allows for passwordless authentication
+ if (!pieces[1])
+ pieces[1] = null;
+
+ return ({
+ username: pieces[0],
+ password: pieces[1]
+ });
}
function parseSignature(request) {
- try {
- return (httpSignature.parseRequest(request, {
- algorithms: OPTIONS.algorithms
- }));
- } catch (e) {
- throw new InvalidHeaderError('Authorization header invalid: ' +
- e.message);
- }
+ try {
+ return (httpSignature.parseRequest(request, {
+ algorithms: OPTIONS.algorithms
+ }));
+ } catch (e) {
+ throw new InvalidHeaderError('Authorization header invalid: ' +
+ e.message);
+ }
}
-
/**
* Returns a plugin that will parse the client's Authorization header.
*
@@ -94,48 +91,48 @@ function parseSignature(request) {
*/
function authorizationParser() {
- function parseAuthorization(req, res, next) {
- req.authorization = {};
- req.username = 'anonymous';
-
- if (!req.headers.authorization)
- return (next());
-
- var pieces = req.headers.authorization.split(' ', 2);
- if (!pieces || pieces.length !== 2) {
- var e = new InvalidHeaderError('BasicAuth content ' +
- 'is invalid.');
- return (next(e));
- }
-
- req.authorization.scheme = pieces[0];
- req.authorization.credentials = pieces[1];
-
- try {
- switch (pieces[0].toLowerCase()) {
- case 'basic':
- req.authorization.basic = parseBasic(pieces[1]);
- req.username = req.authorization.basic.username;
- break;
-
- case 'signature':
- req.authorization.signature =
- parseSignature(req);
- req.username =
- req.authorization.signature.keyId;
- break;
-
- default:
- break;
- }
- } catch (e2) {
- return (next(e2));
- }
-
- return (next());
+ function parseAuthorization(req, res, next) {
+ req.authorization = {};
+ req.username = 'anonymous';
+
+ if (!req.headers.authorization)
+ return (next());
+
+ var pieces = req.headers.authorization.split(' ', 2);
+ if (!pieces || pieces.length !== 2) {
+ var e = new InvalidHeaderError('BasicAuth content ' +
+ 'is invalid.');
+ return (next(e));
+ }
+
+ req.authorization.scheme = pieces[0];
+ req.authorization.credentials = pieces[1];
+
+ try {
+ switch (pieces[0].toLowerCase()) {
+ case 'basic':
+ req.authorization.basic = parseBasic(pieces[1]);
+ req.username = req.authorization.basic.username;
+ break;
+
+ case 'signature':
+ req.authorization.signature =
+ parseSignature(req);
+ req.username =
+ req.authorization.signature.keyId;
+ break;
+
+ default:
+ break;
+ }
+ } catch (e2) {
+ return (next(e2));
}
- return (parseAuthorization);
+ return (next());
+ }
+
+ return (parseAuthorization);
}
module.exports = authorizationParser;
diff --git a/lib/plugins/body_parser.js b/lib/plugins/body_parser.js
index f3bc8c6fa..851921f36 100644
--- a/lib/plugins/body_parser.js
+++ b/lib/plugins/body_parser.js
@@ -11,81 +11,79 @@ var multipartParser = require('./multipart_parser');
var fieldedTextParser = require('./fielded_text_body_parser.js');
-
///--- Globals
var UnsupportedMediaTypeError = errors.UnsupportedMediaTypeError;
-
///--- API
function bodyParser(options) {
- assert.optionalObject(options, 'options');
- options = options || {};
- options.bodyReader = true;
-
- var read = bodyReader(options);
- var parseForm = formParser(options);
- var parseJson = jsonParser(options);
- var parseMultipart = multipartParser(options);
- var parseFieldedText = fieldedTextParser(options);
-
- function parseBody(req, res, next) {
- // Allow use of 'requestBodyOnGet' flag to allow for merging of
- // the request body of a GET request into req.params
- if (req.method === 'HEAD') {
- next();
- return;
- }
- if (req.method === 'GET') {
- if (!options.requestBodyOnGet) {
- next();
- return;
- }
- }
-
- if (req.contentLength() === 0 && !req.isChunked()) {
- next();
- return;
- }
-
- var parser;
- var type = req.contentType();
- switch (type) {
- case 'application/json':
- parser = parseJson[0];
- break;
- case 'application/x-www-form-urlencoded':
- parser = parseForm[0];
- break;
- case 'multipart/form-data':
- parser = parseMultipart;
- break;
- case 'text/tsv':
- parser = parseFieldedText;
- break;
- case 'text/tab-separated-values':
- parser = parseFieldedText;
- break;
- case 'text/csv':
- parser = parseFieldedText;
- break;
-
- default:
- break;
- }
-
- if (parser) {
- parser(req, res, next);
- } else if (options && options.rejectUnknown) {
- next(new UnsupportedMediaTypeError(type));
- } else {
- next();
- }
+ assert.optionalObject(options, 'options');
+ options = options || {};
+ options.bodyReader = true;
+
+ var read = bodyReader(options);
+ var parseForm = formParser(options);
+ var parseJson = jsonParser(options);
+ var parseMultipart = multipartParser(options);
+ var parseFieldedText = fieldedTextParser(options);
+
+ function parseBody(req, res, next) {
+ // Allow use of 'requestBodyOnGet' flag to allow for merging of
+ // the request body of a GET request into req.params
+ if (req.method === 'HEAD') {
+ next();
+ return;
+ }
+ if (req.method === 'GET') {
+ if (!options.requestBodyOnGet) {
+ next();
+ return;
+ }
+ }
+
+ if (req.contentLength() === 0 && !req.isChunked()) {
+ next();
+ return;
+ }
+
+ var parser;
+ var type = req.contentType();
+ switch (type) {
+ case 'application/json':
+ parser = parseJson[0];
+ break;
+ case 'application/x-www-form-urlencoded':
+ parser = parseForm[0];
+ break;
+ case 'multipart/form-data':
+ parser = parseMultipart;
+ break;
+ case 'text/tsv':
+ parser = parseFieldedText;
+ break;
+ case 'text/tab-separated-values':
+ parser = parseFieldedText;
+ break;
+ case 'text/csv':
+ parser = parseFieldedText;
+ break;
+
+ default:
+ break;
+ }
+
+ if (parser) {
+ parser(req, res, next);
+ } else if (options && options.rejectUnknown) {
+ next(new UnsupportedMediaTypeError(type));
+ } else {
+ next();
}
+ }
- return ([read, parseBody]);
+ return ([read, parseBody]);
}
module.exports = bodyParser;
diff --git a/lib/plugins/body_reader.js b/lib/plugins/body_reader.js
index 1950fb64d..3b02812e0 100644
--- a/lib/plugins/body_reader.js
+++ b/lib/plugins/body_reader.js
@@ -8,7 +8,6 @@ var assert = require('assert-plus');
var errors = require('../errors');
-
///--- Globals
var BadDigestError = errors.BadDigestError;
@@ -18,110 +17,108 @@ var RequestEntityTooLargeError = errors.RequestEntityTooLargeError;
var MD5_MSG = 'Content-MD5 \'%s\' didn\'t match \'%s\'';
-
///--- Helpers
function createBodyWriter(req) {
- var contentType = req.contentType();
- if (!contentType ||
- contentType === 'application/json' ||
- contentType === 'application/x-www-form-urlencoded' ||
- contentType === 'multipart/form-data' ||
- contentType.substr(0, 5) === 'text/') {
-
- req.body = '';
- return (function (chunk) {
- req.body += chunk.toString('utf8');
- });
- }
-
- req.body = new Buffer(0);
+ var contentType = req.contentType();
+ if (!contentType ||
+ contentType === 'application/json' ||
+ contentType === 'application/x-www-form-urlencoded' ||
+ contentType === 'multipart/form-data' ||
+ contentType.substr(0, 5) === 'text/') {
+
+ req.body = '';
return (function (chunk) {
- req.body = Buffer.concat([req.body, chunk]);
+ req.body += chunk.toString('utf8');
});
-}
+ }
+ req.body = new Buffer(0);
+ return (function (chunk) {
+ req.body = Buffer.concat([req.body, chunk]);
+ });
+}
///--- API
function bodyReader(options) {
- options = options || {};
- assert.object(options, 'options');
-
- var maxBodySize = options.maxBodySize || 0;
-
- function readBody(req, res, next) {
- if ((req.getContentLength() === 0 && !req.isChunked()) ||
- req.contentType() === 'multipart/form-data' ||
- req.contentType() === 'application/octet-stream') {
- next();
- return;
- }
- var bodyWriter = createBodyWriter(req);
-
- function done() {
- if (maxBodySize && bytesReceived > maxBodySize) {
- var msg = 'Request body size exceeds ' +
- maxBodySize;
- next(new RequestEntityTooLargeError(msg));
- return;
- }
-
- if (!req.body.length) {
- next();
- return;
- }
-
- if (hash && md5 !== (digest = hash.digest('base64'))) {
- next(new BadDigestError(MD5_MSG, md5, digest));
- return;
- }
-
- next();
- }
-
- var bytesReceived = 0;
- var digest;
- var gz;
- var hash;
- var md5;
- if ((md5 = req.headers['content-md5']))
- hash = crypto.createHash('md5');
-
- if (req.headers['content-encoding'] === 'gzip') {
- gz = zlib.createGunzip();
- gz.on('data', function onData(chunk) {
- bodyWriter(chunk);
- });
- gz.once('end', done);
- req.once('end', gz.end.bind(gz));
- } else {
- req.once('end', done);
- }
-
- req.on('data', function onRequestData(chunk) {
- if (maxBodySize) {
- bytesReceived += chunk.length;
- if (bytesReceived > maxBodySize)
- return;
- }
-
- if (hash)
- hash.update(chunk, 'binary');
-
- if (gz) {
- gz.write(chunk);
- } else {
- bodyWriter(chunk);
- }
- });
-
- req.once('error', next);
- req.resume();
+ options = options || {};
+ assert.object(options, 'options');
+
+ var maxBodySize = options.maxBodySize || 0;
+
+ function readBody(req, res, next) {
+ if ((req.getContentLength() === 0 && !req.isChunked()) ||
+ req.contentType() === 'multipart/form-data' ||
+ req.contentType() === 'application/octet-stream') {
+ next();
+ return;
+ }
+ var bodyWriter = createBodyWriter(req);
+
+ function done() {
+ if (maxBodySize && bytesReceived > maxBodySize) {
+ var msg = 'Request body size exceeds ' +
+ maxBodySize;
+ next(new RequestEntityTooLargeError(msg));
+ return;
+ }
+
+ if (!req.body.length) {
+ next();
+ return;
+ }
+
+ if (hash && md5 !== (digest = hash.digest('base64'))) {
+ next(new BadDigestError(MD5_MSG, md5, digest));
+ return;
+ }
+
+ next();
+ }
+
+ var bytesReceived = 0;
+ var digest;
+ var gz;
+ var hash;
+ var md5;
+ if ((md5 = req.headers['content-md5']))
+ hash = crypto.createHash('md5');
+
+ if (req.headers['content-encoding'] === 'gzip') {
+ gz = zlib.createGunzip();
+ gz.on('data', function onData(chunk) {
+ bodyWriter(chunk);
+ });
+ gz.once('end', done);
+ req.once('end', gz.end.bind(gz));
+ } else {
+ req.once('end', done);
}
- return (readBody);
+ req.on('data', function onRequestData(chunk) {
+ if (maxBodySize) {
+ bytesReceived += chunk.length;
+ if (bytesReceived > maxBodySize)
+ return;
+ }
+
+ if (hash)
+ hash.update(chunk, 'binary');
+
+ if (gz) {
+ gz.write(chunk);
+ } else {
+ bodyWriter(chunk);
+ }
+ });
+
+ req.once('error', next);
+ req.resume();
+ }
+
+ return (readBody);
}
module.exports = bodyReader;
diff --git a/lib/plugins/bunyan.js b/lib/plugins/bunyan.js
index 6f4198639..4bc16a7db 100644
--- a/lib/plugins/bunyan.js
+++ b/lib/plugins/bunyan.js
@@ -5,43 +5,41 @@ var assert = require('assert-plus');
var shallowCopy = require('../utils').shallowCopy;
-
///--- API
function requestLogger(options) {
- assert.optionalObject(options);
- options = options || {};
-
- var props;
- if (options.properties) {
- props = shallowCopy(options.properties);
- } else {
- props = {};
+ assert.optionalObject(options);
+ options = options || {};
+
+ var props;
+ if (options.properties) {
+ props = shallowCopy(options.properties);
+ } else {
+ props = {};
+ }
+ if (options.serializers)
+ props.serializers = options.serializers;
+
+ function bunyan(req, res, next) {
+ if (!req.log && !options.log) {
+ next();
+ return;
}
- if (options.serializers)
- props.serializers = options.serializers;
-
- function bunyan(req, res, next) {
- if (!req.log && !options.log) {
- next();
- return;
- }
- var log = req.log || options.log;
+ var log = req.log || options.log;
- props.req_id = req.getId();
- req.log = log.child(props, props.serializers ? false : true);
- if (props.req_id)
- delete props.req_id;
+ props.req_id = req.getId();
+ req.log = log.child(props, props.serializers ? false : true);
+ if (props.req_id)
+ delete props.req_id;
- next();
- }
+ next();
+ }
- return (bunyan);
+ return (bunyan);
}
-
///--- Exports
module.exports = requestLogger;
diff --git a/lib/plugins/conditional_request.js b/lib/plugins/conditional_request.js
index 63cc9212f..3e3321be7 100644
--- a/lib/plugins/conditional_request.js
+++ b/lib/plugins/conditional_request.js
@@ -3,7 +3,6 @@
var errors = require('../errors');
-
///--- Globals
var BadRequestError = errors.BadRequestError;
@@ -15,165 +14,163 @@ var IF_MOD_FAIL = 'object was modified at \'%s\'; if-modified-since \'%s\'';
var IF_UNMOD_FAIL = 'object was modified at \'%s\'; if-unmodified-since \'%s\'';
-
///--- API
// Reference RFC2616 section 14 for an explanation of what this all does.
function checkIfMatch(req, res, next) {
- var clientETags;
- var cur;
- var etag = res.etag || res.getHeader('etag') || '';
- var ifMatch;
- var matched = false;
-
- if ((ifMatch = req.headers['if-match'])) {
- /* JSSTYLED */
- clientETags = ifMatch.split(/\s*,\s*/);
-
- for (var i = 0; i < clientETags.length; i++) {
- cur = clientETags[i];
- // only strong comparison
- /* JSSTYLED */
- cur = cur.replace(/^W\//, '');
- /* JSSTYLED */
- cur = cur.replace(/^"(\w*)"$/, '$1');
-
- if (cur === '*' || cur === etag) {
- matched = true;
- break;
- }
- }
-
- if (!matched) {
- var err = new PreconditionFailedError(IF_MATCH_FAIL,
- ifMatch,
- etag);
- return (next(err));
- }
+ var clientETags;
+ var cur;
+ var etag = res.etag || res.getHeader('etag') || '';
+ var ifMatch;
+ var matched = false;
+
+ if ((ifMatch = req.headers['if-match'])) {
+ /* JSSTYLED */
+ clientETags = ifMatch.split(/\s*,\s*/);
+
+ for (var i = 0; i < clientETags.length; i++) {
+ cur = clientETags[i];
+ // only strong comparison
+ /* JSSTYLED */
+ cur = cur.replace(/^W\//, '');
+ /* JSSTYLED */
+ cur = cur.replace(/^"(\w*)"$/, '$1');
+
+ if (cur === '*' || cur === etag) {
+ matched = true;
+ break;
+ }
}
- return (next());
-}
-
-
-function checkIfNoneMatch(req, res, next) {
- var clientETags;
- var cur;
- var etag = res.etag || res.getHeader('etag') || '';
- var ifNoneMatch;
- var matched = false;
-
- if ((ifNoneMatch = req.headers['if-none-match'])) {
- /* JSSTYLED */
- clientETags = ifNoneMatch.split(/\s*,\s*/);
-
- for (var i = 0; i < clientETags.length; i++) {
- cur = clientETags[i];
- // ignore weak validation
- /* JSSTYLED */
- cur = cur.replace(/^W\//, '');
- /* JSSTYLED */
- cur = cur.replace(/^"(\w*)"$/, '$1');
-
- if (cur === '*' || cur === etag) {
- matched = true;
- break;
- }
- }
-
- if (!matched)
- return (next());
-
- if (req.method !== 'GET' && req.method !== 'HEAD') {
- var err = new PreconditionFailedError(IF_NO_MATCH_FAIL,
- ifNoneMatch,
- etag);
- return (next(err));
- }
-
- res.send(304);
- return (next(false));
+ if (!matched) {
+ var err = new PreconditionFailedError(IF_MATCH_FAIL,
+ ifMatch,
+ etag);
+ return (next(err));
}
+ }
- return (next());
+ return (next());
}
-function checkIfModified(req, res, next) {
- var code;
- var err;
- var ctime = req.header('if-modified-since');
- var mtime = res.mtime || res.header('Last-Modified') || '';
-
- if (!mtime || !ctime) {
- next();
- return;
+function checkIfNoneMatch(req, res, next) {
+ var clientETags;
+ var cur;
+ var etag = res.etag || res.getHeader('etag') || '';
+ var ifNoneMatch;
+ var matched = false;
+
+ if ((ifNoneMatch = req.headers['if-none-match'])) {
+ /* JSSTYLED */
+ clientETags = ifNoneMatch.split(/\s*,\s*/);
+
+ for (var i = 0; i < clientETags.length; i++) {
+ cur = clientETags[i];
+ // ignore weak validation
+ /* JSSTYLED */
+ cur = cur.replace(/^W\//, '');
+ /* JSSTYLED */
+ cur = cur.replace(/^"(\w*)"$/, '$1');
+
+ if (cur === '*' || cur === etag) {
+ matched = true;
+ break;
+ }
}
- try {
- //
- // TODO handle Range header modifications
- //
- // Note: this is not technically correct as per 2616 -
- // 2616 only specifies semantics for GET requests, not
- // any other method - but using if-modified-since with a
- // PUT or DELETE seems like returning 412 is sane
- //
- if (Date.parse(mtime) <= Date.parse(ctime)) {
- switch (req.method) {
- case 'GET':
- case 'HEAD':
- code = 304;
- break;
-
- default:
- err = new PreconditionFailedError(IF_MOD_FAIL,
- mtime,
- ctime);
- break;
- }
- }
- } catch (e) {
- next(new BadRequestError(e.message));
- return;
- }
+ if (!matched)
+ return (next());
- if (code !== undefined) {
- res.send(code);
- next(false);
- return;
+ if (req.method !== 'GET' && req.method !== 'HEAD') {
+ var err = new PreconditionFailedError(IF_NO_MATCH_FAIL,
+ ifNoneMatch,
+ etag);
+ return (next(err));
}
- next(err);
-}
+ res.send(304);
+ return (next(false));
+ }
+ return (next());
+}
-function checkIfUnmodified(req, res, next) {
- var err;
- var ctime = req.headers['if-unmodified-since'];
- var mtime = res.mtime || res.header('Last-Modified') || '';
- if (!mtime || !ctime) {
- next();
- return;
+function checkIfModified(req, res, next) {
+ var code;
+ var err;
+ var ctime = req.header('if-modified-since');
+ var mtime = res.mtime || res.header('Last-Modified') || '';
+
+ if (!mtime || !ctime) {
+ next();
+ return;
+ }
+
+ try {
+ //
+ // TODO handle Range header modifications
+ //
+ // Note: this is not technically correct as per 2616 -
+ // 2616 only specifies semantics for GET requests, not
+ // any other method - but using if-modified-since with a
+ // PUT or DELETE seems like returning 412 is sane
+ //
+ if (Date.parse(mtime) <= Date.parse(ctime)) {
+ switch (req.method) {
+ case 'GET':
+ case 'HEAD':
+ code = 304;
+ break;
+
+ default:
+ err = new PreconditionFailedError(IF_MOD_FAIL,
+ mtime,
+ ctime);
+ break;
+ }
}
+ } catch (e) {
+ next(new BadRequestError(e.message));
+ return;
+ }
+
+ if (code !== undefined) {
+ res.send(code);
+ next(false);
+ return;
+ }
+
+ next(err);
+}
+
- try {
- if (Date.parse(mtime) > Date.parse(ctime)) {
- err = new PreconditionFailedError(IF_UNMOD_FAIL,
- mtime,
- ctime);
- }
- } catch (e) {
- next(new BadRequestError(e.message));
- return;
+function checkIfUnmodified(req, res, next) {
+ var err;
+ var ctime = req.headers['if-unmodified-since'];
+ var mtime = res.mtime || res.header('Last-Modified') || '';
+
+ if (!mtime || !ctime) {
+ next();
+ return;
+ }
+
+ try {
+ if (Date.parse(mtime) > Date.parse(ctime)) {
+ err = new PreconditionFailedError(IF_UNMOD_FAIL,
+ mtime,
+ ctime);
}
+ } catch (e) {
+ next(new BadRequestError(e.message));
+ return;
+ }
- next(err);
+ next(err);
}
-
///--- Exports
/**
@@ -183,13 +180,13 @@ function checkIfUnmodified(req, res, next) {
* If-Unmodified-Since header.
*/
function conditionalRequest() {
- var chain = [
- checkIfMatch,
- checkIfNoneMatch,
- checkIfModified,
- checkIfUnmodified
- ];
- return (chain);
+ var chain = [
+ checkIfMatch,
+ checkIfNoneMatch,
+ checkIfModified,
+ checkIfUnmodified
+ ];
+ return (chain);
}
module.exports = conditionalRequest;
diff --git a/lib/plugins/cors.js b/lib/plugins/cors.js
index fb1f19dda..8b69b163c 100644
--- a/lib/plugins/cors.js
+++ b/lib/plugins/cors.js
@@ -3,27 +3,26 @@
var assert = require('assert-plus');
-
///--- Globals
var ALLOW_HEADERS = [
- 'accept',
- 'accept-version',
- 'content-type',
- 'request-id',
- 'origin',
- 'x-api-version',
- 'x-request-id'
+ 'accept',
+ 'accept-version',
+ 'content-type',
+ 'request-id',
+ 'origin',
+ 'x-api-version',
+ 'x-request-id'
];
var EXPOSE_HEADERS = [
- 'api-version',
- 'content-length',
- 'content-md5',
- 'content-type',
- 'date',
- 'request-id',
- 'response-time'
+ 'api-version',
+ 'content-length',
+ 'content-md5',
+ 'content-type',
+ 'date',
+ 'request-id',
+ 'response-time'
];
// Normal
@@ -32,24 +31,22 @@ var AC_ALLOW_CREDS = 'Access-Control-Allow-Credentials';
var AC_EXPOSE_HEADERS = 'Access-Control-Expose-Headers';
-
///--- Internal Functions
function matchOrigin(req, origins) {
- var origin = req.headers['origin'];
-
- function belongs(o) {
- if (origin === o || o === '*') {
- origin = o;
- return (true);
- }
+ var origin = req.headers['origin'];
- return (false);
+ function belongs(o) {
+ if (origin === o || o === '*') {
+ origin = o;
+ return (true);
}
- return ((origin && origins.some(belongs)) ? origin : false);
-}
+ return (false);
+ }
+ return ((origin && origins.some(belongs)) ? origin : false);
+}
///--- API
@@ -74,47 +71,46 @@ function matchOrigin(req, origins) {
// Pre-flight requests are handled by the router internally
//
function cors(opts) {
- assert.optionalObject(opts, 'options');
- opts = opts || {};
- assert.optionalArrayOfString(opts.origins, 'options.origins');
- assert.optionalBool(opts.credentials, 'options.credentials');
- assert.optionalArrayOfString(opts.headers, 'options.headers');
-
- var headers = (opts.headers || []).slice(0);
- var origins = opts.origins || ['*'];
-
- EXPOSE_HEADERS.forEach(function (h) {
- if (headers.indexOf(h) === -1)
- headers.push(h);
- });
-
- // Handler for simple requests
- function restifyCORSSimple(req, res, next) {
- var origin;
- if (!(origin = matchOrigin(req, origins))) {
- next();
- return;
- }
-
- function corsOnHeader() {
- origin = req.headers['origin'];
- if (opts.credentials) {
- res.setHeader(AC_ALLOW_ORIGIN, origin);
- res.setHeader(AC_ALLOW_CREDS, 'true');
- } else {
- res.setHeader(AC_ALLOW_ORIGIN, origin);
- }
-
- res.setHeader(AC_EXPOSE_HEADERS, headers.join(', '));
- }
-
- res.once('header', corsOnHeader);
- next();
+ assert.optionalObject(opts, 'options');
+ opts = opts || {};
+ assert.optionalArrayOfString(opts.origins, 'options.origins');
+ assert.optionalBool(opts.credentials, 'options.credentials');
+ assert.optionalArrayOfString(opts.headers, 'options.headers');
+
+ var headers = (opts.headers || []).slice(0);
+ var origins = opts.origins || ['*'];
+
+ EXPOSE_HEADERS.forEach(function (h) {
+ if (headers.indexOf(h) === -1)
+ headers.push(h);
+ });
+
+ // Handler for simple requests
+ function restifyCORSSimple(req, res, next) {
+ var origin;
+ if (!(origin = matchOrigin(req, origins))) {
+ next();
+ return;
}
- return (restifyCORSSimple);
-}
+ function corsOnHeader() {
+ origin = req.headers['origin'];
+ if (opts.credentials) {
+ res.setHeader(AC_ALLOW_ORIGIN, origin);
+ res.setHeader(AC_ALLOW_CREDS, 'true');
+ } else {
+ res.setHeader(AC_ALLOW_ORIGIN, origin);
+ }
+
+ res.setHeader(AC_EXPOSE_HEADERS, headers.join(', '));
+ }
+ res.once('header', corsOnHeader);
+ next();
+ }
+
+ return (restifyCORSSimple);
+}
///--- Exports
diff --git a/lib/plugins/date.js b/lib/plugins/date.js
index 1605d056a..dfae70ea8 100644
--- a/lib/plugins/date.js
+++ b/lib/plugins/date.js
@@ -5,7 +5,6 @@ var assert = require('assert-plus');
var errors = require('../errors');
-
///--- Globals
var InvalidHeaderError = errors.InvalidHeaderError;
@@ -15,7 +14,6 @@ var BAD_MSG = 'Date header is invalid';
var OLD_MSG = 'Date header %s is too old';
-
///--- API
/**
@@ -29,51 +27,51 @@ var OLD_MSG = 'Date header %s is too old';
* @throws {TypeError} on bad input
*/
function dateParser(clockSkew) {
- if (!clockSkew)
- clockSkew = 300;
- assert.number(clockSkew, 'clockSkew');
+ if (!clockSkew)
+ clockSkew = 300;
+ assert.number(clockSkew, 'clockSkew');
- clockSkew = clockSkew * 1000;
+ clockSkew = clockSkew * 1000;
- function parseDate(req, res, next) {
- if (!req.headers.date)
- return (next());
+ function parseDate(req, res, next) {
+ if (!req.headers.date)
+ return (next());
- var e;
- var date = req.headers.date;
- var log = req.log;
+ var e;
+ var date = req.headers.date;
+ var log = req.log;
- try {
- var now = Date.now();
- var sent = new Date(date).getTime();
+ try {
+ var now = Date.now();
+ var sent = new Date(date).getTime();
- if (log.trace()) {
- log.trace({
- allowedSkew: clockSkew,
- now: now,
- sent: sent
- }, 'Checking clock skew');
- }
+ if (log.trace()) {
+ log.trace({
+ allowedSkew: clockSkew,
+ now: now,
+ sent: sent
+ }, 'Checking clock skew');
+ }
- if ((now - sent) > clockSkew) {
- e = new RequestExpiredError(OLD_MSG, date);
- return (next(e));
- }
+ if ((now - sent) > clockSkew) {
+ e = new RequestExpiredError(OLD_MSG, date);
+ return (next(e));
+ }
- } catch (err) {
- log.trace({
- err: err
- }, 'Bad Date header: %s', date);
+ } catch (err) {
+ log.trace({
+ err: err
+ }, 'Bad Date header: %s', date);
- e = new InvalidHeaderError(BAD_MSG, date);
- return (next(e));
- }
-
- return (next());
+ e = new InvalidHeaderError(BAD_MSG, date);
+ return (next(e));
}
- return (parseDate);
+ return (next());
+ }
+
+ return (parseDate);
}
module.exports = dateParser;
diff --git a/lib/plugins/fielded_text_body_parser.js b/lib/plugins/fielded_text_body_parser.js
index 3deb09b56..9adbc971b 100644
--- a/lib/plugins/fielded_text_body_parser.js
+++ b/lib/plugins/fielded_text_body_parser.js
@@ -2,7 +2,7 @@
* Dependencies
*/
-var csv = require('csv');
+var csv = require('csv');
var assert = require('assert-plus');
var bodyReader = require('./body_reader');
var errors = require('../errors');
@@ -19,64 +19,63 @@ var errors = require('../errors');
function fieldedTextParser(options) {
- assert.optionalObject(options, 'options');
- options = options || {};
-
- function parseFieldedText(req, res, next) {
-
- var contentType = req.getContentType();
-
- if (contentType !== 'text/csv' &&
- contentType !== 'text/tsv' &&
- contentType !== 'text/tab-separated-values' ||
- !req.body) {
- next();
- return;
- }
-
-
- var hDelimiter = req.headers['x-content-delimiter'];
- var hEscape = req.headers['x-content-escape'];
- var hQuote = req.headers['x-content-quote'];
- var hColumns = req.headers['x-content-columns'];
-
-
- var delimiter = (contentType === 'text/tsv') ? '\t' : ',';
- delimiter = (hDelimiter) ? hDelimiter : delimiter;
- var escape = (hEscape) ? hEscape : '\\';
- var quote = (hQuote) ? hQuote : '"';
- var columns = (hColumns) ? hColumns : true;
-
- var parsedBody = [];
-
- csv()
- .from(req.body, {
- delimiter: delimiter,
- quote: quote,
- escape: escape,
- columns: columns
- })
- .on('record', function (row, index) {
- row.index = index;
- parsedBody.push(row);
- })
- .on('end', function (count) {
- req.body = parsedBody;
- return (next());
- })
- .on('error', function (error) {
- return (next(error));
- });
+ assert.optionalObject(options, 'options');
+ options = options || {};
- }
+ function parseFieldedText(req, res, next) {
+
+ var contentType = req.getContentType();
- var chain = [];
- if (!options.bodyReader) {
- chain.push(bodyReader(options));
+ if (contentType !== 'text/csv' &&
+ contentType !== 'text/tsv' &&
+ contentType !== 'text/tab-separated-values' || !req.body) {
+ next();
+ return;
}
- chain.push(parseFieldedText);
- return (chain);
+
+ var hDelimiter = req.headers['x-content-delimiter'];
+ var hEscape = req.headers['x-content-escape'];
+ var hQuote = req.headers['x-content-quote'];
+ var hColumns = req.headers['x-content-columns'];
+
+
+ var delimiter = (contentType === 'text/tsv') ? '\t' : ',';
+ delimiter = (hDelimiter) ? hDelimiter : delimiter;
+ var escape = (hEscape) ? hEscape : '\\';
+ var quote = (hQuote) ? hQuote : '"';
+ var columns = (hColumns) ? hColumns : true;
+
+ var parsedBody = [];
+
+ csv()
+ .from(req.body, {
+ delimiter: delimiter,
+ quote: quote,
+ escape: escape,
+ columns: columns
+ })
+ .on('record', function (row, index) {
+ row.index = index;
+ parsedBody.push(row);
+ })
+ .on('end', function (count) {
+ req.body = parsedBody;
+ return (next());
+ })
+ .on('error', function (error) {
+ return (next(error));
+ });
+
+ }
+
+ var chain = [];
+ if (!options.bodyReader) {
+ chain.push(bodyReader(options));
+ }
+ chain.push(parseFieldedText);
+
+ return (chain);
}
diff --git a/lib/plugins/form_body_parser.js b/lib/plugins/form_body_parser.js
index 682e2ad20..e880d777e 100644
--- a/lib/plugins/form_body_parser.js
+++ b/lib/plugins/form_body_parser.js
@@ -9,13 +9,11 @@ var bodyReader = require('./body_reader');
var errors = require('../errors');
-
///--- Globals
var MIME_TYPE = 'application/x-www-form-urlencoded';
-
///--- API
/**
@@ -29,47 +27,47 @@ var MIME_TYPE = 'application/x-www-form-urlencoded';
* @throws {TypeError} on bad input
*/
function urlEncodedBodyParser(options) {
- options = options || {};
- assert.object(options, 'options');
-
- var override = options.overrideParams;
-
- function parseUrlEncodedBody(req, res, next) {
- if (req.getContentType() !== MIME_TYPE || !req.body) {
- next();
- return;
- }
-
- try {
- var params = querystring.parse(req.body);
- if (options.mapParams !== false) {
- var keys = Object.keys(params);
- keys.forEach(function (k) {
- var p = req.params[k];
- if (p && !override)
- return (false);
-
- req.params[k] = params[k];
- return (true);
- });
- } else {
- req._body = req.body;
- req.body = params;
- }
- } catch (e) {
- next(new errors.InvalidContentError(e.message));
- return;
- }
-
- req.log.trace('req.params now: %j', req.params);
- next();
+ options = options || {};
+ assert.object(options, 'options');
+
+ var override = options.overrideParams;
+
+ function parseUrlEncodedBody(req, res, next) {
+ if (req.getContentType() !== MIME_TYPE || !req.body) {
+ next();
+ return;
}
- var chain = [];
- if (!options.bodyReader)
- chain.push(bodyReader(options));
- chain.push(parseUrlEncodedBody);
- return (chain);
+ try {
+ var params = querystring.parse(req.body);
+ if (options.mapParams !== false) {
+ var keys = Object.keys(params);
+ keys.forEach(function (k) {
+ var p = req.params[k];
+ if (p && !override)
+ return (false);
+
+ req.params[k] = params[k];
+ return (true);
+ });
+ } else {
+ req._body = req.body;
+ req.body = params;
+ }
+ } catch (e) {
+ next(new errors.InvalidContentError(e.message));
+ return;
+ }
+
+ req.log.trace('req.params now: %j', req.params);
+ next();
+ }
+
+ var chain = [];
+ if (!options.bodyReader)
+ chain.push(bodyReader(options));
+ chain.push(parseUrlEncodedBody);
+ return (chain);
}
module.exports = urlEncodedBodyParser;
diff --git a/lib/plugins/full_response.js b/lib/plugins/full_response.js
index 19d298fdf..2335b179b 100644
--- a/lib/plugins/full_response.js
+++ b/lib/plugins/full_response.js
@@ -5,106 +5,102 @@ var crypto = require('crypto');
var httpDate = require('../http_date');
-
///--- Globals
var ALLOW_HEADERS = [
- 'Accept',
- 'Accept-Version',
- 'Content-Length',
- 'Content-MD5',
- 'Content-Type',
- 'Date',
- 'Api-Version',
- 'Response-Time'
+ 'Accept',
+ 'Accept-Version',
+ 'Content-Length',
+ 'Content-MD5',
+ 'Content-Type',
+ 'Date',
+ 'Api-Version',
+ 'Response-Time'
].join(', ');
var EXPOSE_HEADERS = [
- 'Api-Version',
- 'Request-Id',
- 'Response-Time'
+ 'Api-Version',
+ 'Request-Id',
+ 'Response-Time'
].join(', ');
-
///--- API
function setHeaders(req, res) {
- var hash;
- var now = new Date();
- var methods;
+ var hash;
+ var now = new Date();
+ var methods;
- if (!res.getHeader('Access-Control-Allow-Origin'))
- res.setHeader('Access-Control-Allow-Origin', '*');
+ if (!res.getHeader('Access-Control-Allow-Origin'))
+ res.setHeader('Access-Control-Allow-Origin', '*');
- if (!res.getHeader('Access-Control-Allow-Headers'))
- res.setHeader('Access-Control-Allow-Headers', ALLOW_HEADERS);
+ if (!res.getHeader('Access-Control-Allow-Headers'))
+ res.setHeader('Access-Control-Allow-Headers', ALLOW_HEADERS);
- if (!res.getHeader('Access-Control-Allow-Methods')) {
- if (res.methods && res.methods.length > 0) {
- methods = res.methods.join(', ');
- res.setHeader('Access-Control-Allow-Methods', methods);
- }
+ if (!res.getHeader('Access-Control-Allow-Methods')) {
+ if (res.methods && res.methods.length > 0) {
+ methods = res.methods.join(', ');
+ res.setHeader('Access-Control-Allow-Methods', methods);
}
+ }
- if (!res.getHeader('Access-Control-Expose-Headers'))
- res.setHeader('Access-Control-Expose-Headers', EXPOSE_HEADERS);
+ if (!res.getHeader('Access-Control-Expose-Headers'))
+ res.setHeader('Access-Control-Expose-Headers', EXPOSE_HEADERS);
- if (!res.getHeader('Connection')) {
- res.setHeader('Connection',
- req.isKeepAlive() ? 'Keep-Alive' : 'close');
- }
+ if (!res.getHeader('Connection')) {
+ res.setHeader('Connection',
+ req.isKeepAlive() ? 'Keep-Alive' : 'close');
+ }
- if (res._data && !res.getHeader('Content-MD5')) {
- hash = crypto.createHash('md5');
- hash.update(res._data);
- res.setHeader('Content-MD5', hash.digest('base64'));
- }
+ if (res._data && !res.getHeader('Content-MD5')) {
+ hash = crypto.createHash('md5');
+ hash.update(res._data);
+ res.setHeader('Content-MD5', hash.digest('base64'));
+ }
- if (!res.getHeader('Date'))
- res.setHeader('Date', httpDate(now));
+ if (!res.getHeader('Date'))
+ res.setHeader('Date', httpDate(now));
- if (res.etag && !res.getHeader('Etag'))
- res.setHeader('Etag', res.etag);
+ if (res.etag && !res.getHeader('Etag'))
+ res.setHeader('Etag', res.etag);
- if (!res.getHeader('Server'))
- res.setHeader('Server', res.serverName);
+ if (!res.getHeader('Server'))
+ res.setHeader('Server', res.serverName);
- if (res.version && !res.getHeader('Api-Version'))
- res.setHeader('Api-Version', res.version);
+ if (res.version && !res.getHeader('Api-Version'))
+ res.setHeader('Api-Version', res.version);
- if (!res.getHeader('Request-Id'))
- res.setHeader('Request-Id', req.getId());
+ if (!res.getHeader('Request-Id'))
+ res.setHeader('Request-Id', req.getId());
- if (!res.getHeader('Response-Time'))
- res.setHeader('Response-Time', now.getTime() - req._time);
+ if (!res.getHeader('Response-Time'))
+ res.setHeader('Response-Time', now.getTime() - req._time);
}
-
function fullResponse() {
- function restifyResponseHeaders(req, res, next) {
- res.once('header', function () {
+ function restifyResponseHeaders(req, res, next) {
+ res.once('header', function () {
- // Restify 1.0 compatibility
- if (res.defaultResponseFormatters)
- res.defaultResponseFormatters(res._data);
+ // Restify 1.0 compatibility
+ if (res.defaultResponseFormatters)
+ res.defaultResponseFormatters(res._data);
- res.emit('beforeSend', res._data, res._body);
+ res.emit('beforeSend', res._data, res._body);
- // end backwards-compatibility
- return (setHeaders(req, res));
- });
+ // end backwards-compatibility
+ return (setHeaders(req, res));
+ });
- return (next());
- }
+ return (next());
+ }
- return (restifyResponseHeaders);
+ return (restifyResponseHeaders);
}
-
///--- Exports
module.exports = fullResponse;
diff --git a/lib/plugins/gzip.js b/lib/plugins/gzip.js
index 6f5d2ea66..855a6ae1b 100644
--- a/lib/plugins/gzip.js
+++ b/lib/plugins/gzip.js
@@ -6,47 +6,46 @@ var assert = require('assert-plus');
function _writeHead(originalFunction) {
- this.removeHeader('Content-Length');
- originalFunction.apply(this, Array.prototype.slice.call(arguments, 1));
+ this.removeHeader('Content-Length');
+ originalFunction.apply(this, Array.prototype.slice.call(arguments, 1));
}
///--- API
function gzipResponse(opts) {
- assert.optionalObject(opts, 'options');
-
- function gzip(req, res, next) {
- if (!req.acceptsEncoding('gzip')) {
- next();
- return;
- }
-
- var gz = zlib.createGzip(opts);
-
- gz.on('data', res.write.bind(res));
- gz.once('end', res.end.bind(res));
- gz.on('drain', res.emit.bind(res, 'drain'));
-
- var origWrite = res.write;
- var origEnd = res.end;
- var origWriteHead = res.writeHead;
- res.handledGzip = function _handledGzip() {
- res.write = origWrite;
- res.end = origEnd;
- res.writeHead = origWriteHead;
- };
-
- res.write = gz.write.bind(gz);
- res.end = gz.end.bind(gz);
-
- res.writeHead = _writeHead.bind(res, res.writeHead);
- res.setHeader('Content-Encoding', 'gzip');
- next();
+ assert.optionalObject(opts, 'options');
+
+ function gzip(req, res, next) {
+ if (!req.acceptsEncoding('gzip')) {
+ next();
+ return;
}
- return (gzip);
-}
+ var gz = zlib.createGzip(opts);
+
+ gz.on('data', res.write.bind(res));
+ gz.once('end', res.end.bind(res));
+ gz.on('drain', res.emit.bind(res, 'drain'));
+
+ var origWrite = res.write;
+ var origEnd = res.end;
+ var origWriteHead = res.writeHead;
+ res.handledGzip = function _handledGzip() {
+ res.write = origWrite;
+ res.end = origEnd;
+ res.writeHead = origWriteHead;
+ };
+ res.write = gz.write.bind(gz);
+ res.end = gz.end.bind(gz);
+
+ res.writeHead = _writeHead.bind(res, res.writeHead);
+ res.setHeader('Content-Encoding', 'gzip');
+ next();
+ }
+
+ return (gzip);
+}
///--- Exports
diff --git a/lib/plugins/index.js b/lib/plugins/index.js
index 521294f97..c4fc56bc3 100644
--- a/lib/plugins/index.js
+++ b/lib/plugins/index.js
@@ -3,28 +3,28 @@
///--- Exports
module.exports = {
- acceptParser: require('./accept'),
- auditLogger: require('./audit'),
- authorizationParser: require('./authorization'),
- bodyParser: require('./body_parser'),
- conditionalRequest: require('./conditional_request'),
- CORS: require('./cors'),
- dateParser: require('./date'),
- jsonp: require('./jsonp'),
- urlEncodedBodyParser: require('./form_body_parser'),
- requestLogger: require('./bunyan'),
- gzipResponse: require('./gzip'),
- fullResponse: require('./full_response'),
- jsonBodyParser: require('./json_body_parser'),
- multipartBodyParser: require('./multipart_parser'),
- queryParser: require('./query'),
- sanitizePath: require('./pre/pre_path'),
- serveStatic: require('./static'),
- throttle: require('./throttle'),
+ acceptParser: require('./accept'),
+ auditLogger: require('./audit'),
+ authorizationParser: require('./authorization'),
+ bodyParser: require('./body_parser'),
+ conditionalRequest: require('./conditional_request'),
+ CORS: require('./cors'),
+ dateParser: require('./date'),
+ jsonp: require('./jsonp'),
+ urlEncodedBodyParser: require('./form_body_parser'),
+ requestLogger: require('./bunyan'),
+ gzipResponse: require('./gzip'),
+ fullResponse: require('./full_response'),
+ jsonBodyParser: require('./json_body_parser'),
+ multipartBodyParser: require('./multipart_parser'),
+ queryParser: require('./query'),
+ sanitizePath: require('./pre/pre_path'),
+ serveStatic: require('./static'),
+ throttle: require('./throttle'),
- pre: {
- pause: require('./pre/pause'),
- sanitizePath: require('./pre/pre_path'),
- userAgentConnection: require('./pre/user_agent')
- }
+ pre: {
+ pause: require('./pre/pause'),
+ sanitizePath: require('./pre/pre_path'),
+ userAgentConnection: require('./pre/user_agent')
+ }
};
diff --git a/lib/plugins/json_body_parser.js b/lib/plugins/json_body_parser.js
index 579820048..1a43c0809 100644
--- a/lib/plugins/json_body_parser.js
+++ b/lib/plugins/json_body_parser.js
@@ -6,7 +6,6 @@ var bodyReader = require('./body_reader');
var errors = require('../errors');
-
///--- API
/**
@@ -20,54 +19,54 @@ var errors = require('../errors');
* @throws {TypeError} on bad input
*/
function jsonBodyParser(options) {
- assert.optionalObject(options, 'options');
- options = options || {};
+ assert.optionalObject(options, 'options');
+ options = options || {};
- var override = options.overrideParams;
+ var override = options.overrideParams;
- function parseJson(req, res, next) {
- if (req.getContentType() !== 'application/json' || !req.body) {
- next();
- return;
- }
+ function parseJson(req, res, next) {
+ if (req.getContentType() !== 'application/json' || !req.body) {
+ next();
+ return;
+ }
- var params;
- try {
- params = JSON.parse(req.body);
- } catch (e) {
- next(new errors.InvalidContentError('Invalid JSON: ' +
- e.message));
- return;
- }
+ var params;
+ try {
+ params = JSON.parse(req.body);
+ } catch (e) {
+ next(new errors.InvalidContentError('Invalid JSON: ' +
+ e.message));
+ return;
+ }
- if (options.mapParams !== false) {
- if (Array.isArray(params)) {
- req.params = params;
- } else if (typeof (params) === 'object') {
- Object.keys(params).forEach(function (k) {
- var p = req.params[k];
- if (p && !override)
- return (false);
- req.params[k] = params[k];
- return (true);
- });
- } else {
- req.params = params;
- }
- } else {
- req._body = req.body;
- }
+ if (options.mapParams !== false) {
+ if (Array.isArray(params)) {
+ req.params = params;
+ } else if (typeof (params) === 'object') {
+ Object.keys(params).forEach(function (k) {
+ var p = req.params[k];
+ if (p && !override)
+ return (false);
+ req.params[k] = params[k];
+ return (true);
+ });
+ } else {
+ req.params = params;
+ }
+ } else {
+ req._body = req.body;
+ }
- req.body = params;
+ req.body = params;
- next();
- }
+ next();
+ }
- var chain = [];
- if (!options.bodyReader)
- chain.push(bodyReader(options));
- chain.push(parseJson);
- return (chain);
+ var chain = [];
+ if (!options.bodyReader)
+ chain.push(bodyReader(options));
+ chain.push(parseJson);
+ return (chain);
}
module.exports = jsonBodyParser;
diff --git a/lib/plugins/jsonp.js b/lib/plugins/jsonp.js
index 28eee2da8..f14b94719 100644
--- a/lib/plugins/jsonp.js
+++ b/lib/plugins/jsonp.js
@@ -3,24 +3,23 @@
var qs = require('qs');
-
///--- API
function jsonp() {
- function _jsonp(req, res, next) {
- var q = req.getQuery();
+ function _jsonp(req, res, next) {
+ var q = req.getQuery();
- // If the query plugin wasn't used, we need to hack it in now
- if (typeof (q) === 'string')
- req.query = qs.parse(q);
+ // If the query plugin wasn't used, we need to hack it in now
+ if (typeof (q) === 'string')
+ req.query = qs.parse(q);
- if (req.query.callback || req.query.jsonp)
- res.setHeader('Content-Type', 'application/javascript');
+ if (req.query.callback || req.query.jsonp)
+ res.setHeader('Content-Type', 'application/javascript');
- next();
- }
+ next();
+ }
- return (_jsonp);
+ return (_jsonp);
}
diff --git a/lib/plugins/multipart_parser.js b/lib/plugins/multipart_parser.js
index 4e875e775..722830795 100644
--- a/lib/plugins/multipart_parser.js
+++ b/lib/plugins/multipart_parser.js
@@ -6,13 +6,11 @@ var formidable = require('formidable');
var errors = require('../errors');
-
///--- Globals
var BadRequestError = errors.BadRequestError;
-
///--- API
/**
@@ -26,61 +24,62 @@ var BadRequestError = errors.BadRequestError;
* @throws {TypeError} on bad input
*/
function multipartBodyParser(options) {
- if (!options)
- options = {};
- assert.object(options, 'options');
-
- var override = options.overrideParams;
- function parseMultipartBody(req, res, next) {
- if (req.getContentType() !== 'multipart/form-data' ||
- (req.getContentLength() === 0 && !req.isChunked()))
- return (next());
-
- var form = new formidable.IncomingForm();
- form.keepExtensions = options.keepExtensions ? true : false;
- if (options.uploadDir)
- form.uploadDir = options.uploadDir;
-
- form.parse(req, function (err, fields, files) {
- if (err)
- return (next(new BadRequestError(err.message)));
-
- req.body = fields;
- req.files = files;
-
- if (options.mapParams !== false) {
- Object.keys(fields).forEach(function (k) {
- if (req.params[k] && !override)
- return (false);
-
- req.params[k] = fields[k];
- return (true);
- });
-
- Object.keys(files).forEach(function (f) {
- if (req.params[f] && !override)
- return (false);
- var fs = require('fs');
- return fs.readFile(
- files[f].path,
- 'utf8',
- function (ex, data) {
- if (ex) {
- return (false);
- }
- req.params[f] = data;
- return (true);
- });
- });
- }
-
- return (next());
+ if (!options)
+ options = {};
+ assert.object(options, 'options');
+
+ var override = options.overrideParams;
+
+ function parseMultipartBody(req, res, next) {
+ if (req.getContentType() !== 'multipart/form-data' ||
+ (req.getContentLength() === 0 && !req.isChunked()))
+ return (next());
+
+ var form = new formidable.IncomingForm();
+ form.keepExtensions = options.keepExtensions ? true : false;
+ if (options.uploadDir)
+ form.uploadDir = options.uploadDir;
+
+ form.parse(req, function (err, fields, files) {
+ if (err)
+ return (next(new BadRequestError(err.message)));
+
+ req.body = fields;
+ req.files = files;
+
+ if (options.mapParams !== false) {
+ Object.keys(fields).forEach(function (k) {
+ if (req.params[k] && !override)
+ return (false);
+
+ req.params[k] = fields[k];
+ return (true);
});
- return (false);
- }
+ Object.keys(files).forEach(function (f) {
+ if (req.params[f] && !override)
+ return (false);
+ var fs = require('fs');
+ return fs.readFile(
+ files[f].path,
+ 'utf8',
+ function (ex, data) {
+ if (ex) {
+ return (false);
+ }
+ req.params[f] = data;
+ return (true);
+ });
+ });
+ }
+
+ return (next());
+ });
+
+ return (false);
+ }
- return (parseMultipartBody);
+ return (parseMultipartBody);
}
module.exports = multipartBodyParser;
diff --git a/lib/plugins/pre/pause.js b/lib/plugins/pre/pause.js
index 3e74d2550..2daf5e6ff 100644
--- a/lib/plugins/pre/pause.js
+++ b/lib/plugins/pre/pause.js
@@ -1,54 +1,52 @@
// Copyright 2012 Mark Cavage, Inc. All rights reserved.
-
///--- Helpers
function pauseStream(stream) {
- function _buffer(chunk) {
- stream.__buffered.push(chunk);
- }
-
- function _catchEnd(chunk) {
- stream.__rstfy_ended = true;
- }
-
- stream.__rstfy_ended = false;
- stream.__rstfy_paused = true;
- stream.__buffered = [];
- stream.on('data', _buffer);
- stream.once('end', _catchEnd);
- stream.pause();
-
- stream._resume = stream.resume;
- stream.resume = function _rstfy_resume() {
- if (!stream.__rstfy_paused)
- return;
-
- stream.removeListener('data', _buffer);
- stream.removeListener('end', _catchEnd);
-
- stream.__buffered.forEach(stream.emit.bind(stream, 'data'));
- stream.__buffered.length = 0;
-
- stream._resume();
- stream.resume = stream._resume;
-
- if (stream.__rstfy_ended)
- stream.emit('end');
- };
+ function _buffer(chunk) {
+ stream.__buffered.push(chunk);
+ }
+
+ function _catchEnd(chunk) {
+ stream.__rstfy_ended = true;
+ }
+
+ stream.__rstfy_ended = false;
+ stream.__rstfy_paused = true;
+ stream.__buffered = [];
+ stream.on('data', _buffer);
+ stream.once('end', _catchEnd);
+ stream.pause();
+
+ stream._resume = stream.resume;
+ stream.resume = function _rstfy_resume() {
+ if (!stream.__rstfy_paused)
+ return;
+
+ stream.removeListener('data', _buffer);
+ stream.removeListener('end', _catchEnd);
+
+ stream.__buffered.forEach(stream.emit.bind(stream, 'data'));
+ stream.__buffered.length = 0;
+
+ stream._resume();
+ stream.resume = stream._resume;
+
+ if (stream.__rstfy_ended)
+ stream.emit('end');
+ };
}
-
///--- Exports
module.exports = function pause() {
- function prePause(req, res, next) {
- pauseStream(req);
- next();
- }
+ function prePause(req, res, next) {
+ pauseStream(req);
+ next();
+ }
- return (prePause);
+ return (prePause);
};
diff --git a/lib/plugins/pre/pre_path.js b/lib/plugins/pre/pre_path.js
index 10807478e..d57a8ab54 100644
--- a/lib/plugins/pre/pre_path.js
+++ b/lib/plugins/pre/pre_path.js
@@ -1,7 +1,6 @@
// Copyright 2012 Mark Cavage, Inc. All rights reserved.
-
///--- Helpers
/**
@@ -9,35 +8,34 @@
*
*/
function strip(path) {
- var cur;
- var next;
- var str = '';
+ var cur;
+ var next;
+ var str = '';
- for (var i = 0; i < path.length; i++) {
- cur = path.charAt(i);
- if (i !== path.length - 1)
- next = path.charAt(i + 1);
+ for (var i = 0; i < path.length; i++) {
+ cur = path.charAt(i);
+ if (i !== path.length - 1)
+ next = path.charAt(i + 1);
- if (cur === '/' && (next === '/' || (next === '?' && i > 0)))
- continue;
+ if (cur === '/' && (next === '/' || (next === '?' && i > 0)))
+ continue;
- str += cur;
- }
+ str += cur;
+ }
- return (str);
+ return (str);
}
-
///--- Exports
module.exports = function sanitizePath(options) {
- options = options || {};
+ options = options || {};
- function _sanitizePath(req, res, next) {
- req.url = strip(req.url);
- next();
- }
+ function _sanitizePath(req, res, next) {
+ req.url = strip(req.url);
+ next();
+ }
- return (_sanitizePath);
+ return (_sanitizePath);
};
diff --git a/lib/plugins/pre/user_agent.js b/lib/plugins/pre/user_agent.js
index aac310088..2bb1fe3ba 100644
--- a/lib/plugins/pre/user_agent.js
+++ b/lib/plugins/pre/user_agent.js
@@ -3,7 +3,6 @@
var assert = require('assert-plus');
-
///--- API
/**
@@ -21,29 +20,29 @@ var assert = require('assert-plus');
* agent regexp, however.
*/
function userAgentConnection(opts) {
- assert.optionalObject(opts, 'options');
- opts = opts || {};
- assert.optionalObject(opts.userAgentRegExp, 'options.userAgentRegExp');
-
- var re = opts.userAgentRegExp;
- if (!re)
- re = /^curl.+/;
+ assert.optionalObject(opts, 'options');
+ opts = opts || {};
+ assert.optionalObject(opts.userAgentRegExp, 'options.userAgentRegExp');
- function handleUserAgent(req, res, next) {
- var ua = req.headers['user-agent'];
+ var re = opts.userAgentRegExp;
+ if (!re)
+ re = /^curl.+/;
- if (ua && re.test(ua))
- res.setHeader('Connection', 'close');
+ function handleUserAgent(req, res, next) {
+ var ua = req.headers['user-agent'];
- if (req.method === 'HEAD') {
- res.once('header',
- res.removeHeader.bind(res, 'content-length'));
- }
+ if (ua && re.test(ua))
+ res.setHeader('Connection', 'close');
- next();
+ if (req.method === 'HEAD') {
+ res.once('header',
+ res.removeHeader.bind(res, 'content-length'));
}
- return (handleUserAgent);
+ next();
+ }
+
+ return (handleUserAgent);
}
module.exports = userAgentConnection;
\ No newline at end of file
diff --git a/lib/plugins/query.js b/lib/plugins/query.js
index 9dd592f02..fb9ded901 100644
--- a/lib/plugins/query.js
+++ b/lib/plugins/query.js
@@ -6,7 +6,6 @@ var url = require('url');
var assert = require('assert-plus');
-
/**
* Returns a plugin that will parse the query string, and merge the results
* into req.params.
@@ -15,32 +14,32 @@ var assert = require('assert-plus');
* @throws {TypeError} on bad input
*/
function queryParser(options) {
- if (!options)
- options = {};
- assert.object(options, 'options');
-
+ if (!options)
+ options = {};
+ assert.object(options, 'options');
- function parseQueryString(req, res, next) {
- if (!req.getQuery()) {
- req.query = {};
- return (next());
- }
- req._query = req.query = qs.parse(req.getQuery());
- if (options.mapParams !== false) {
- Object.keys(req.query).forEach(function (k) {
- if (req.params[k] && !options.overrideParams)
- return (false);
+ function parseQueryString(req, res, next) {
+ if (!req.getQuery()) {
+ req.query = {};
+ return (next());
+ }
- req.params[k] = req.query[k];
- return (true);
- });
- }
+ req._query = req.query = qs.parse(req.getQuery());
+ if (options.mapParams !== false) {
+ Object.keys(req.query).forEach(function (k) {
+ if (req.params[k] && !options.overrideParams)
+ return (false);
- return (next());
+ req.params[k] = req.query[k];
+ return (true);
+ });
}
- return (parseQueryString);
+ return (next());
+ }
+
+ return (parseQueryString);
}
module.exports = queryParser;
diff --git a/lib/plugins/static.js b/lib/plugins/static.js
index 296a113cb..ac5577a80 100644
--- a/lib/plugins/static.js
+++ b/lib/plugins/static.js
@@ -16,124 +16,123 @@ var NotAuthorizedError = errors.NotAuthorizedError;
var ResourceNotFoundError = errors.ResourceNotFoundError;
-
///--- Functions
function serveStatic(opts) {
- opts = opts || {};
- assert.object(opts, 'options');
- assert.string(opts.directory, 'options.directory');
- assert.optionalNumber(opts.maxAge, 'options.maxAge');
- assert.optionalObject(opts.match, 'options.match');
- assert.optionalString(opts.charSet, 'options.charSet');
-
- var p = path.normalize(opts.directory).replace(/\\/g, '/');
- var re = new RegExp('^' + escapeRE(p) + '/?.*');
-
- function serveFileFromStats(file, err, stats, isGzip, req, res, next) {
- if (err) {
- next(new ResourceNotFoundError(err,
- req.path()));
- return;
- } else if (!stats.isFile()) {
- next(new ResourceNotFoundError(req.path()));
- return;
- }
-
- if (res.handledGzip && isGzip) {
- res.handledGzip();
- }
+ opts = opts || {};
+ assert.object(opts, 'options');
+ assert.string(opts.directory, 'options.directory');
+ assert.optionalNumber(opts.maxAge, 'options.maxAge');
+ assert.optionalObject(opts.match, 'options.match');
+ assert.optionalString(opts.charSet, 'options.charSet');
+
+ var p = path.normalize(opts.directory).replace(/\\/g, '/');
+ var re = new RegExp('^' + escapeRE(p) + '/?.*');
+
+ function serveFileFromStats(file, err, stats, isGzip, req, res, next) {
+ if (err) {
+ next(new ResourceNotFoundError(err,
+ req.path()));
+ return;
+ } else if (!stats.isFile()) {
+ next(new ResourceNotFoundError(req.path()));
+ return;
+ }
- var fstream = fs.createReadStream(file + (isGzip ? '.gz' : ''));
- var maxAge = opts.maxAge === undefined ? 3600 : opts.maxAge;
- fstream.once('open', function (fd) {
- res.cache({maxAge: maxAge});
- res.set('Content-Length', stats.size);
- res.set('Content-Type', mime.lookup(file));
- res.set('Last-Modified', stats.mtime);
- if (opts.charSet) {
- var type = res.getHeader('Content-Type') +
- '; charset=' + opts.charSet;
- res.setHeader('Content-Type', type);
- }
- if (opts.etag) {
- res.set('ETag', opts.etag(stats, opts));
- }
- res.writeHead(200);
- fstream.pipe(res);
- fstream.once('end', function () {
- next(false);
- });
- });
+ if (res.handledGzip && isGzip) {
+ res.handledGzip();
}
- function serveNormal(file, req, res, next) {
- fs.stat(file, function (err, stats) {
- if (!err && stats.isDirectory() && opts.default) {
- // Serve an index.html page or similar
- file = path.join(file, opts.default);
- fs.stat(file, function (dirErr, dirStats) {
- serveFileFromStats(file,
- dirErr,
- dirStats,
- false,
- req,
- res,
- next);
- });
- } else {
- serveFileFromStats(file,
- err,
- stats,
- false,
- req,
- res,
- next);
- }
+ var fstream = fs.createReadStream(file + (isGzip ? '.gz' : ''));
+ var maxAge = opts.maxAge === undefined ? 3600 : opts.maxAge;
+ fstream.once('open', function (fd) {
+ res.cache({maxAge: maxAge});
+ res.set('Content-Length', stats.size);
+ res.set('Content-Type', mime.lookup(file));
+ res.set('Last-Modified', stats.mtime);
+ if (opts.charSet) {
+ var type = res.getHeader('Content-Type') +
+ '; charset=' + opts.charSet;
+ res.setHeader('Content-Type', type);
+ }
+ if (opts.etag) {
+ res.set('ETag', opts.etag(stats, opts));
+ }
+ res.writeHead(200);
+ fstream.pipe(res);
+ fstream.once('end', function () {
+ next(false);
+ });
+ });
+ }
+
+ function serveNormal(file, req, res, next) {
+ fs.stat(file, function (err, stats) {
+ if (!err && stats.isDirectory() && opts.default) {
+ // Serve an index.html page or similar
+ file = path.join(file, opts.default);
+ fs.stat(file, function (dirErr, dirStats) {
+ serveFileFromStats(file,
+ dirErr,
+ dirStats,
+ false,
+ req,
+ res,
+ next);
});
+ } else {
+ serveFileFromStats(file,
+ err,
+ stats,
+ false,
+ req,
+ res,
+ next);
+ }
+ });
+ }
+
+ function serve(req, res, next) {
+ var file = path.join(opts.directory,
+ decodeURIComponent(req.path()));
+
+ if (req.method !== 'GET' && req.method !== 'HEAD') {
+ next(new MethodNotAllowedError(req.method));
+ return;
}
- function serve(req, res, next) {
- var file = path.join(opts.directory,
- decodeURIComponent(req.path()));
-
- if (req.method !== 'GET' && req.method !== 'HEAD') {
- next(new MethodNotAllowedError(req.method));
- return;
- }
-
- if (!re.test(file.replace(/\\/g, '/'))) {
- next(new NotAuthorizedError(req.path()));
- return;
- }
+ if (!re.test(file.replace(/\\/g, '/'))) {
+ next(new NotAuthorizedError(req.path()));
+ return;
+ }
- if (opts.match && !opts.match.test(file)) {
- next(new NotAuthorizedError(req.path()));
- return;
- }
+ if (opts.match && !opts.match.test(file)) {
+ next(new NotAuthorizedError(req.path()));
+ return;
+ }
- if (opts.gzip && req.acceptsEncoding('gzip')) {
- fs.stat(file + '.gz', function (err, stats) {
- if (!err) {
- res.setHeader('Content-Encoding', 'gzip');
- serveFileFromStats(file,
- err,
- stats,
- true,
- req,
- res,
- next);
- } else {
- serveNormal(file, req, res, next);
- }
- });
+ if (opts.gzip && req.acceptsEncoding('gzip')) {
+ fs.stat(file + '.gz', function (err, stats) {
+ if (!err) {
+ res.setHeader('Content-Encoding', 'gzip');
+ serveFileFromStats(file,
+ err,
+ stats,
+ true,
+ req,
+ res,
+ next);
} else {
- serveNormal(file, req, res, next);
+ serveNormal(file, req, res, next);
}
-
+ });
+ } else {
+ serveNormal(file, req, res, next);
}
- return (serve);
+ }
+
+ return (serve);
}
module.exports = serveStatic;
diff --git a/lib/plugins/throttle.js b/lib/plugins/throttle.js
index a62b7f77c..15c10b88c 100644
--- a/lib/plugins/throttle.js
+++ b/lib/plugins/throttle.js
@@ -8,7 +8,6 @@ var LRU = require('lru-cache');
var errors = require('../errors');
-
///--- Globals
var TooManyRequestsError = errors.TooManyRequestsError;
@@ -16,22 +15,20 @@ var TooManyRequestsError = errors.TooManyRequestsError;
var MESSAGE = 'You have exceeded your request rate of %s r/s.';
-
///--- Helpers
function xor() {
- var x = false;
- for (var i = 0; i < arguments.length; i++) {
- if (arguments[i] && !x)
- x = true;
- else if (arguments[i] && x)
- return (false);
- }
- return (x);
+ var x = false;
+ for (var i = 0; i < arguments.length; i++) {
+ if (arguments[i] && !x)
+ x = true;
+ else if (arguments[i] && x)
+ return (false);
+ }
+ return (x);
}
-
///--- Internal Class (TokenBucket)
/**
@@ -55,13 +52,13 @@ function xor() {
* - {Number} fillRate the rate to refill tokens.
*/
function TokenBucket(options) {
- assert.object(options, 'options');
- assert.number(options.capacity, 'options.capacity');
- assert.number(options.fillRate, 'options.fillRate');
+ assert.object(options, 'options');
+ assert.number(options.capacity, 'options.capacity');
+ assert.number(options.fillRate, 'options.fillRate');
- this.tokens = this.capacity = options.capacity;
- this.fillRate = options.fillRate;
- this.time = Date.now();
+ this.tokens = this.capacity = options.capacity;
+ this.fillRate = options.fillRate;
+ this.time = Date.now();
}
@@ -74,12 +71,12 @@ function TokenBucket(options) {
* @return {Boolean} true if capacity, false otherwise.
*/
TokenBucket.prototype.consume = function consume(tokens) {
- if (tokens <= this._fill()) {
- this.tokens -= tokens;
- return (true);
- }
+ if (tokens <= this._fill()) {
+ this.tokens -= tokens;
+ return (true);
+ }
- return (false);
+ return (false);
};
@@ -95,43 +92,41 @@ TokenBucket.prototype.consume = function consume(tokens) {
* @return {Number} the current number of tokens in the bucket.
*/
TokenBucket.prototype._fill = function _fill() {
- var now = Date.now();
- if (now < this.time) // reset account for clock drift (like DST)
- this.time = now - 1000;
+ var now = Date.now();
+ if (now < this.time) // reset account for clock drift (like DST)
+ this.time = now - 1000;
- if (this.tokens < this.capacity) {
- var delta = this.fillRate * ((now - this.time) / 1000);
- this.tokens = Math.min(this.capacity, this.tokens + delta);
- }
- this.time = now;
+ if (this.tokens < this.capacity) {
+ var delta = this.fillRate * ((now - this.time) / 1000);
+ this.tokens = Math.min(this.capacity, this.tokens + delta);
+ }
+ this.time = now;
- return (this.tokens);
+ return (this.tokens);
};
-
///--- Internal Class (TokenTable)
// Just a wrapper over LRU that supports put/get to store token -> bucket
// mappings
function TokenTable(options) {
- assert.object(options, 'options');
+ assert.object(options, 'options');
- this.table = new LRU(options.size || 10000);
+ this.table = new LRU(options.size || 10000);
}
TokenTable.prototype.put = function put(key, value) {
- this.table.set(key, value);
+ this.table.set(key, value);
};
TokenTable.prototype.get = function get(key) {
- return (this.table.get(key));
+ return (this.table.get(key));
};
-
///--- Exported API
/**
@@ -189,79 +184,79 @@ TokenTable.prototype.get = function get(key) {
* @throws {TypeError} on bad input.
*/
function throttle(options) {
- assert.object(options, 'options');
- assert.number(options.burst, 'options.burst');
- assert.number(options.rate, 'options.rate');
- if (!xor(options.ip, options.xff, options.username))
- throw new Error('(ip ^ username ^ xff)');
-
- var burst = options.burst;
- var rate = options.rate;
- var table = options.tokensTable ||
- new TokenTable({size: options.maxKeys});
-
- function rateLimit(req, res, next) {
- var attr;
- if (options.ip) {
- attr = req.connection.remoteAddress;
- } else if (options.xff) {
- attr = req.headers['x-forwarded-for'];
- } else if (options.username) {
- attr = req.username;
- } else {
- req.log.warn({config: options},
- 'Invalid throttle configuration');
- return (next());
- }
-
- // Before bothering with overrides, see if this request
- // even matches
- if (!attr)
- return (next());
-
- // Check the overrides
- if (options.overrides &&
- options.overrides[attr] &&
- options.overrides[attr].burst !== undefined &&
- options.overrides[attr].rate !== undefined) {
-
- burst = options.overrides[attr].burst;
- rate = options.overrides[attr].rate;
- }
-
- if (!rate || !burst)
- return (next());
-
- var bucket = table.get(attr);
- if (!bucket) {
- bucket = new TokenBucket({
- capacity: burst,
- fillRate: rate
- });
- table.put(attr, bucket);
- }
-
- req.log.trace('Throttle(%s): num_tokens= %d',
- attr, bucket.tokens);
-
- if (!bucket.consume(1)) {
- req.log.info({
- address: req.connection.remoteAddress || '?',
- method: req.method,
- url: req.url,
- user: req.username || '?'
- }, 'Throttling');
-
-
- // Until https://github.com/joyent/node/pull/2371 is in
- var msg = sprintf(MESSAGE, rate);
- return (next(new TooManyRequestsError(msg)));
- }
-
- return (next());
+ assert.object(options, 'options');
+ assert.number(options.burst, 'options.burst');
+ assert.number(options.rate, 'options.rate');
+ if (!xor(options.ip, options.xff, options.username))
+ throw new Error('(ip ^ username ^ xff)');
+
+ var burst = options.burst;
+ var rate = options.rate;
+ var table = options.tokensTable ||
+ new TokenTable({size: options.maxKeys});
+
+ function rateLimit(req, res, next) {
+ var attr;
+ if (options.ip) {
+ attr = req.connection.remoteAddress;
+ } else if (options.xff) {
+ attr = req.headers['x-forwarded-for'];
+ } else if (options.username) {
+ attr = req.username;
+ } else {
+ req.log.warn({config: options},
+ 'Invalid throttle configuration');
+ return (next());
}
- return (rateLimit);
+ // Before bothering with overrides, see if this request
+ // even matches
+ if (!attr)
+ return (next());
+
+ // Check the overrides
+ if (options.overrides &&
+ options.overrides[attr] &&
+ options.overrides[attr].burst !== undefined &&
+ options.overrides[attr].rate !== undefined) {
+
+ burst = options.overrides[attr].burst;
+ rate = options.overrides[attr].rate;
+ }
+
+ if (!rate || !burst)
+ return (next());
+
+ var bucket = table.get(attr);
+ if (!bucket) {
+ bucket = new TokenBucket({
+ capacity: burst,
+ fillRate: rate
+ });
+ table.put(attr, bucket);
+ }
+
+ req.log.trace('Throttle(%s): num_tokens= %d',
+ attr, bucket.tokens);
+
+ if (!bucket.consume(1)) {
+ req.log.info({
+ address: req.connection.remoteAddress || '?',
+ method: req.method,
+ url: req.url,
+ user: req.username || '?'
+ }, 'Throttling');
+
+
+ // Until https://github.com/joyent/node/pull/2371 is in
+ var msg = sprintf(MESSAGE, rate);
+ return (next(new TooManyRequestsError(msg)));
+ }
+
+ return (next());
+ }
+
+ return (rateLimit);
}
module.exports = throttle;
diff --git a/lib/request.js b/lib/request.js
index 1893ed949..a35fe6045 100644
--- a/lib/request.js
+++ b/lib/request.js
@@ -12,7 +12,6 @@ var uuid = require('node-uuid');
var utils = require('./utils');
-
///--- Globals
var Request = http.IncomingMessage;
@@ -21,22 +20,21 @@ var parseAccept = utils.parseAccept;
var sanitizePath = utils.sanitizePath;
-
///-- Helpers
function negotiator(req) {
- var h = req.headers;
- if (!req._negotatiator) {
- req._negotiator = new Negotatior({
- headers: {
- accept: h.accept || '*/*',
- 'accept-encoding': h['accept-encoding'] ||
- 'identity'
- }
- });
- }
+ var h = req.headers;
+ if (!req._negotatiator) {
+ req._negotiator = new Negotatior({
+ headers: {
+ accept: h.accept || '*/*',
+ 'accept-encoding': h['accept-encoding'] ||
+ 'identity'
+ }
+ });
+ }
- return (req._negotiator);
+ return (req._negotiator);
}
@@ -45,275 +43,275 @@ function negotiator(req) {
///--- Patches
Request.prototype.absoluteUri = function absoluteUri(path) {
- assert.string(path, 'path');
+ assert.string(path, 'path');
- var protocol = this.secure ? 'https://' : 'http://';
- var hostname = this.headers['host'];
- return (url.resolve(protocol + hostname + this.path + '/', path));
+ var protocol = this.secure ? 'https://' : 'http://';
+ var hostname = this.headers['host'];
+ return (url.resolve(protocol + hostname + this.path + '/', path));
};
Request.prototype.accepts = function accepts(types) {
- if (typeof (types) === 'string')
- types = [types];
-
- types = types.map(function (t) {
- assert.string(t, 'type');
- if (t.indexOf('/') === -1)
- t = mime.lookup(t);
- return (t);
- });
+ if (typeof (types) === 'string')
+ types = [types];
- negotiator(this);
+ types = types.map(function (t) {
+ assert.string(t, 'type');
+ if (t.indexOf('/') === -1)
+ t = mime.lookup(t);
+ return (t);
+ });
- return (this._negotiator.preferredMediaType(types));
+ negotiator(this);
+
+ return (this._negotiator.preferredMediaType(types));
};
Request.prototype.acceptsEncoding = function acceptsEncoding(types) {
- if (typeof (types) === 'string')
- types = [types];
+ if (typeof (types) === 'string')
+ types = [types];
- assert.arrayOfString(types, 'types');
+ assert.arrayOfString(types, 'types');
- negotiator(this);
+ negotiator(this);
- return (this._negotiator.preferredEncoding(types));
+ return (this._negotiator.preferredEncoding(types));
};
Request.prototype.getContentLength = function getContentLength() {
- if (this._clen !== undefined)
- return (this._clen === false ? undefined : this._clen);
+ if (this._clen !== undefined)
+ return (this._clen === false ? undefined : this._clen);
- // We should not attempt to read and parse the body of an
- // Upgrade request, so force Content-Length to zero:
- if (this.isUpgradeRequest())
- return (0);
+ // We should not attempt to read and parse the body of an
+ // Upgrade request, so force Content-Length to zero:
+ if (this.isUpgradeRequest())
+ return (0);
- var len = this.header('content-length');
- if (!len) {
- this._clen = false;
- } else {
- this._clen = parseInt(len, 10);
- }
+ var len = this.header('content-length');
+ if (!len) {
+ this._clen = false;
+ } else {
+ this._clen = parseInt(len, 10);
+ }
- return (this._clen === false ? undefined : this._clen);
+ return (this._clen === false ? undefined : this._clen);
};
Request.prototype.contentLength = Request.prototype.getContentLength;
Request.prototype.getContentType = function getContentType() {
- if (this._contentType !== undefined)
- return (this._contentType);
+ if (this._contentType !== undefined)
+ return (this._contentType);
- var index;
- var type = this.headers['content-type'];
+ var index;
+ var type = this.headers['content-type'];
- if (!type) {
- // RFC2616 section 7.2.1
- this._contentType = 'application/octet-stream';
+ if (!type) {
+ // RFC2616 section 7.2.1
+ this._contentType = 'application/octet-stream';
+ } else {
+ if ((index = type.indexOf(';')) === -1) {
+ this._contentType = type;
} else {
- if ((index = type.indexOf(';')) === -1) {
- this._contentType = type;
- } else {
- this._contentType = type.substring(0, index);
- }
+ this._contentType = type.substring(0, index);
}
+ }
- return (this._contentType);
+ return (this._contentType);
};
Request.prototype.contentType = Request.prototype.getContentType;
Request.prototype.date = function date() {
- if (this._date !== undefined)
- return (this._date);
-
- this._date = new Date(this._time);
+ if (this._date !== undefined)
return (this._date);
+
+ this._date = new Date(this._time);
+ return (this._date);
};
Request.prototype.getHref = function getHref() {
- if (this._href !== undefined)
- return (this._href);
-
- this._href = this.getUrl().href;
+ if (this._href !== undefined)
return (this._href);
+
+ this._href = this.getUrl().href;
+ return (this._href);
};
Request.prototype.href = Request.prototype.getHref;
Request.prototype.getId = function getId() {
- if (this._id !== undefined)
- return (this._id);
+ if (this._id !== undefined)
+ return (this._id);
- this._id = this.headers['request-id'] ||
- this.headers['x-request-id'] ||
- uuid.v1();
+ this._id = this.headers['request-id'] ||
+ this.headers['x-request-id'] ||
+ uuid.v1();
- return (this._id);
+ return (this._id);
};
Request.prototype.id = Request.prototype.getId;
Request.prototype.getPath = function getPath() {
- if (this._path !== undefined)
- return (this._path);
-
- this._path = this.getUrl().pathname;
+ if (this._path !== undefined)
return (this._path);
+
+ this._path = this.getUrl().pathname;
+ return (this._path);
};
Request.prototype.path = Request.prototype.getPath;
Request.prototype.getQuery = function getQuery() {
- if (this._query !== undefined)
- return (this._query);
-
- this._query = this.getUrl().query || {};
+ if (this._query !== undefined)
return (this._query);
+
+ this._query = this.getUrl().query || {};
+ return (this._query);
};
Request.prototype.query = Request.prototype.getQuery;
Request.prototype.time = function time() {
- return (this._time);
+ return (this._time);
};
Request.prototype.getUrl = function getUrl() {
- if (this._url !== undefined)
- return (this._url);
-
- this._url = url.parse(this.url);
+ if (this._url !== undefined)
return (this._url);
+
+ this._url = url.parse(this.url);
+ return (this._url);
};
Request.prototype.getVersion = function getVersion() {
- if (this._version !== undefined)
- return (this._version);
+ if (this._version !== undefined)
+ return (this._version);
- this._version =
- this.headers['accept-version'] ||
- this.headers['x-api-version'] ||
- '*';
+ this._version =
+ this.headers['accept-version'] ||
+ this.headers['x-api-version'] ||
+ '*';
- return (this._version);
+ return (this._version);
};
Request.prototype.version = Request.prototype.getVersion;
Request.prototype.header = function header(name, value) {
- assert.string(name, 'name');
+ assert.string(name, 'name');
- name = name.toLowerCase();
+ name = name.toLowerCase();
- if (name === 'referer' || name === 'referrer')
- name = 'referer';
+ if (name === 'referer' || name === 'referrer')
+ name = 'referer';
- return (this.headers[name] || value);
+ return (this.headers[name] || value);
};
Request.prototype.trailer = function trailer(name, value) {
- assert.string(name, 'name');
- name = name.toLowerCase();
+ assert.string(name, 'name');
+ name = name.toLowerCase();
- if (name === 'referer' || name === 'referrer')
- name = 'referer';
+ if (name === 'referer' || name === 'referrer')
+ name = 'referer';
- return ((this.trailers || {})[name] || value);
+ return ((this.trailers || {})[name] || value);
};
Request.prototype.is = function is(type) {
- assert.string(type, 'type');
-
- var contentType = this.getContentType();
- var matches = true;
- if (!contentType)
- return (false);
-
- if (type.indexOf('/') === -1)
- type = mime.lookup(type);
-
- if (type.indexOf('*') !== -1) {
- type = type.split('/');
- contentType = contentType.split('/');
- matches &= (type[0] === '*' || type[0] === contentType[0]);
- matches &= (type[1] === '*' || type[1] === contentType[1]);
- } else {
- matches = (contentType === type);
- }
-
- return (matches);
+ assert.string(type, 'type');
+
+ var contentType = this.getContentType();
+ var matches = true;
+ if (!contentType)
+ return (false);
+
+ if (type.indexOf('/') === -1)
+ type = mime.lookup(type);
+
+ if (type.indexOf('*') !== -1) {
+ type = type.split('/');
+ contentType = contentType.split('/');
+ matches &= (type[0] === '*' || type[0] === contentType[0]);
+ matches &= (type[1] === '*' || type[1] === contentType[1]);
+ } else {
+ matches = (contentType === type);
+ }
+
+ return (matches);
};
Request.prototype.isChunked = function isChunked() {
- return (this.headers['transfer-encoding'] === 'chunked');
+ return (this.headers['transfer-encoding'] === 'chunked');
};
Request.prototype.isKeepAlive = function isKeepAlive() {
- if (this._keepAlive !== undefined)
- return (this._keepAlive);
+ if (this._keepAlive !== undefined)
+ return (this._keepAlive);
- if (this.headers.connection) {
- this._keepAlive = /keep-alive/i.test(this.headers.connection);
- } else {
- this._keepAlive = this.httpVersion === '1.0' ? false : true;
- }
+ if (this.headers.connection) {
+ this._keepAlive = /keep-alive/i.test(this.headers.connection);
+ } else {
+ this._keepAlive = this.httpVersion === '1.0' ? false : true;
+ }
- return (this._keepAlive);
+ return (this._keepAlive);
};
Request.prototype.isSecure = function isSecure() {
- if (this._secure !== undefined)
- return (this._secure);
-
- this._secure = this.connection.encrypted ? true : false;
+ if (this._secure !== undefined)
return (this._secure);
+
+ this._secure = this.connection.encrypted ? true : false;
+ return (this._secure);
};
Request.prototype.isUpgradeRequest = function isUpgradeRequest() {
- if (this._upgradeRequest !== undefined)
- return (this._upgradeRequest);
- else
- return (false);
+ if (this._upgradeRequest !== undefined)
+ return (this._upgradeRequest);
+ else
+ return (false);
};
Request.prototype.isUpload = function isUpload() {
- var m = this.method;
- return (m === 'PATH' || m === 'POST' || m === 'PUT');
+ var m = this.method;
+ return (m === 'PATH' || m === 'POST' || m === 'PUT');
};
Request.prototype.toString = function toString() {
- var headers = '';
- var self = this;
- var str;
+ var headers = '';
+ var self = this;
+ var str;
- Object.keys(this.headers).forEach(function (k) {
- headers += sprintf('%s: %s\n', k, self.headers[k]);
- });
+ Object.keys(this.headers).forEach(function (k) {
+ headers += sprintf('%s: %s\n', k, self.headers[k]);
+ });
- str = sprintf('%s %s HTTP/%s\n%s',
- this.method,
- this.url,
- this.httpVersion,
- headers);
+ str = sprintf('%s %s HTTP/%s\n%s',
+ this.method,
+ this.url,
+ this.httpVersion,
+ headers);
- return (str);
+ return (str);
};
Request.prototype.userAgent = function userAgent() {
- return (this.headers['user-agent']);
+ return (this.headers['user-agent']);
};
diff --git a/lib/response.js b/lib/response.js
index 88b03341d..ed4e10bc6 100644
--- a/lib/response.js
+++ b/lib/response.js
@@ -12,7 +12,6 @@ var errors = require('./errors');
var httpDate = require('./http_date');
-
///--- Globals
var HttpError = errors.HttpError;
@@ -21,258 +20,257 @@ var RestError = errors.RestError;
var Response = http.ServerResponse;
-
///--- API
Response.prototype.cache = function cache(type, options) {
- if (typeof (type) !== 'string') {
- options = type;
- type = 'public';
- }
+ if (typeof (type) !== 'string') {
+ options = type;
+ type = 'public';
+ }
- if (options && options.maxAge !== undefined) {
- assert.number(options.maxAge, 'options.maxAge');
- type += ', max-age=' + options.maxAge;
- }
+ if (options && options.maxAge !== undefined) {
+ assert.number(options.maxAge, 'options.maxAge');
+ type += ', max-age=' + options.maxAge;
+ }
- return (this.header('Cache-Control', type));
+ return (this.header('Cache-Control', type));
};
Response.prototype.charSet = function charSet(type) {
- assert.string(type, 'charset');
+ assert.string(type, 'charset');
- this._charSet = type;
+ this._charSet = type;
- return (this);
+ return (this);
};
Response.prototype.format = function format(body, cb) {
- var log = this.log;
- var formatter;
- var type = this.contentType || this.getHeader('Content-Type');
- var self = this;
+ var log = this.log;
+ var formatter;
+ var type = this.contentType || this.getHeader('Content-Type');
+ var self = this;
+
+ if (!type) {
+ for (var i = 0; i < this.acceptable.length; i++) {
+ if (this.req.accepts(this.acceptable[i])) {
+ type = this.acceptable[i];
+ break;
+ }
+ }
if (!type) {
- for (var i = 0; i < this.acceptable.length; i++) {
- if (this.req.accepts(this.acceptable[i])) {
- type = this.acceptable[i];
- break;
- }
- }
-
- if (!type) {
- // The importance of a status code outside of the
- // 2xx range probably outweighs that of unable being to
- // format the response body
- if (this.statusCode >= 200 && this.statusCode < 300)
- this.statusCode = 406;
-
- return (null);
- }
- } else if (type.indexOf(';') !== '-1') {
- type = type.split(';')[0];
+ // The importance of a status code outside of the
+ // 2xx range probably outweighs that of unable being to
+ // format the response body
+ if (this.statusCode >= 200 && this.statusCode < 300)
+ this.statusCode = 406;
+
+ return (null);
}
+ } else if (type.indexOf(';') !== '-1') {
+ type = type.split(';')[0];
+ }
- if (!(formatter = this.formatters[type])) {
- if (type.indexOf('/') === -1)
- type = mime.lookup(type);
+ if (!(formatter = this.formatters[type])) {
+ if (type.indexOf('/') === -1)
+ type = mime.lookup(type);
- if (this.acceptable.indexOf(type) === -1)
- type = 'application/octet-stream';
+ if (this.acceptable.indexOf(type) === -1)
+ type = 'application/octet-stream';
- formatter = this.formatters[type] || this.formatters['*/*'];
+ formatter = this.formatters[type] || this.formatters['*/*'];
- if (!formatter) {
- log.warn({
- req: self.req
- }, 'no formatter found. Returning 500.');
- this.statusCode = 500;
- return (null);
- }
+ if (!formatter) {
+ log.warn({
+ req: self.req
+ }, 'no formatter found. Returning 500.');
+ this.statusCode = 500;
+ return (null);
}
+ }
- if (this._charSet) {
- type = type + '; charset=' + this._charSet;
- }
+ if (this._charSet) {
+ type = type + '; charset=' + this._charSet;
+ }
- this.setHeader('Content-Type', type);
+ this.setHeader('Content-Type', type);
- if (body instanceof Error && body.statusCode !== undefined)
- this.statusCode = body.statusCode;
- return (formatter.call(this, this.req, this, body, cb));
+ if (body instanceof Error && body.statusCode !== undefined)
+ this.statusCode = body.statusCode;
+ return (formatter.call(this, this.req, this, body, cb));
};
Response.prototype.get = function get(name) {
- assert.string(name, 'name');
+ assert.string(name, 'name');
- return (this.getHeader(name));
+ return (this.getHeader(name));
};
Response.prototype.getHeaders = function getHeaders() {
- return (this._headers || {});
+ return (this._headers || {});
};
Response.prototype.headers = Response.prototype.getHeaders;
Response.prototype.header = function header(name, value) {
- assert.string(name, 'name');
+ assert.string(name, 'name');
- if (value === undefined)
- return (this.getHeader(name));
+ if (value === undefined)
+ return (this.getHeader(name));
- if (value instanceof Date) {
- value = httpDate(value);
- } else if (arguments.length > 2) {
- // Support res.header('foo', 'bar %s', 'baz');
- var arg = Array.prototype.slice.call(arguments).slice(2);
- value = sprintf(value, arg);
- }
+ if (value instanceof Date) {
+ value = httpDate(value);
+ } else if (arguments.length > 2) {
+ // Support res.header('foo', 'bar %s', 'baz');
+ var arg = Array.prototype.slice.call(arguments).slice(2);
+ value = sprintf(value, arg);
+ }
- this.setHeader(name, value);
- return (value);
+ this.setHeader(name, value);
+ return (value);
};
Response.prototype.json = function json(code, object, headers) {
- if (!/application\/json/.test(this.header('content-type')))
- this.header('Content-Type', 'application/json');
+ if (!/application\/json/.test(this.header('content-type')))
+ this.header('Content-Type', 'application/json');
- return (this.send(code, object, headers));
+ return (this.send(code, object, headers));
};
Response.prototype.link = function link(l, rel) {
- assert.string(l, 'link');
- assert.string(rel, 'rel');
+ assert.string(l, 'link');
+ assert.string(rel, 'rel');
- var _link = sprintf('<%s>; rel="%s"', l, rel);
- return (this.header('Link', _link));
+ var _link = sprintf('<%s>; rel="%s"', l, rel);
+ return (this.header('Link', _link));
};
Response.prototype.send = function send(code, body, headers) {
- var isHead = (this.req.method === 'HEAD');
- var log = this.log;
- var self = this;
-
- if (code === undefined) {
- this.statusCode = 200;
- } else if (code.constructor.name === 'Number') {
- this.statusCode = code;
- if (body instanceof Error) {
- body.statusCode = this.statusCode;
- }
- } else {
- headers = body;
- body = code;
- code = null;
- }
+ var isHead = (this.req.method === 'HEAD');
+ var log = this.log;
+ var self = this;
- headers = headers || {};
-
- if (log.trace()) {
- var _props = {
- code: self.statusCode,
- headers: headers
- };
- if (body instanceof Error) {
- _props.err = body;
- } else {
- _props.body = body;
- }
- log.trace(_props, 'response::send entered');
+ if (code === undefined) {
+ this.statusCode = 200;
+ } else if (code.constructor.name === 'Number') {
+ this.statusCode = code;
+ if (body instanceof Error) {
+ body.statusCode = this.statusCode;
}
+ } else {
+ headers = body;
+ body = code;
+ code = null;
+ }
+
+ headers = headers || {};
+
+ if (log.trace()) {
+ var _props = {
+ code: self.statusCode,
+ headers: headers
+ };
+ if (body instanceof Error) {
+ _props.err = body;
+ } else {
+ _props.body = body;
+ }
+ log.trace(_props, 'response::send entered');
+ }
- this._body = body;
+ this._body = body;
- function _cb(err, _body) {
- self._data = _body;
- Object.keys(headers).forEach(function (k) {
- self.setHeader(k, headers[k]);
- });
+ function _cb(err, _body) {
+ self._data = _body;
+ Object.keys(headers).forEach(function (k) {
+ self.setHeader(k, headers[k]);
+ });
- self.writeHead(self.statusCode);
+ self.writeHead(self.statusCode);
- if (self._data && !(isHead || code === 204 || code === 304))
- self.write(self._data);
+ if (self._data && !(isHead || code === 204 || code === 304))
+ self.write(self._data);
- self.end();
+ self.end();
- if (log.trace())
- log.trace({res: self}, 'response sent');
- }
+ if (log.trace())
+ log.trace({res: self}, 'response sent');
+ }
- if (body) {
- var ret = this.format(body, _cb);
- if (!(ret instanceof Response)) {
- _cb(null, ret);
- }
- } else {
- _cb(null, null);
+ if (body) {
+ var ret = this.format(body, _cb);
+ if (!(ret instanceof Response)) {
+ _cb(null, ret);
}
+ } else {
+ _cb(null, null);
+ }
- return (this);
+ return (this);
};
Response.prototype.set = function set(name, val) {
- var self = this;
+ var self = this;
- if (arguments.length === 2) {
- assert.string(name, 'name');
- this.header(name, val);
- } else {
- assert.object(name, 'object');
- Object.keys(name).forEach(function (k) {
- self.header(k, name[k]);
- });
- }
+ if (arguments.length === 2) {
+ assert.string(name, 'name');
+ this.header(name, val);
+ } else {
+ assert.object(name, 'object');
+ Object.keys(name).forEach(function (k) {
+ self.header(k, name[k]);
+ });
+ }
- return (this);
+ return (this);
};
Response.prototype.status = function status(code) {
- assert.number(code, 'code');
+ assert.number(code, 'code');
- this.statusCode = code;
- return (code);
+ this.statusCode = code;
+ return (code);
};
Response.prototype.toString = function toString() {
- var headers = this.getHeaders();
- var headerString = '';
- var str;
-
- Object.keys(headers).forEach(function (k) {
- headerString += k + ': ' + headers[k] + '\n';
- });
- str = sprintf('HTTP/1.1 %s %s\n%s',
- this.statusCode,
- http.STATUS_CODES[this.statusCode],
- headerString);
-
- return (str);
+ var headers = this.getHeaders();
+ var headerString = '';
+ var str;
+
+ Object.keys(headers).forEach(function (k) {
+ headerString += k + ': ' + headers[k] + '\n';
+ });
+ str = sprintf('HTTP/1.1 %s %s\n%s',
+ this.statusCode,
+ http.STATUS_CODES[this.statusCode],
+ headerString);
+
+ return (str);
};
if (!Response.prototype.hasOwnProperty('_writeHead'))
- Response.prototype._writeHead = Response.prototype.writeHead;
+ Response.prototype._writeHead = Response.prototype.writeHead;
Response.prototype.writeHead = function restifyWriteHead() {
- this.emit('header');
+ this.emit('header');
- if (this.statusCode === 204 || this.statusCode === 304) {
- this.removeHeader('Content-Length');
- this.removeHeader('Content-MD5');
- this.removeHeader('Content-Type');
- this.removeHeader('Content-Encoding');
- }
+ if (this.statusCode === 204 || this.statusCode === 304) {
+ this.removeHeader('Content-Length');
+ this.removeHeader('Content-MD5');
+ this.removeHeader('Content-Type');
+ this.removeHeader('Content-Encoding');
+ }
- this._writeHead.apply(this, arguments);
+ this._writeHead.apply(this, arguments);
};
diff --git a/lib/router.js b/lib/router.js
index bcb6c120c..679c8010d 100644
--- a/lib/router.js
+++ b/lib/router.js
@@ -15,7 +15,6 @@ var errors = require('./errors');
var utils = require('./utils');
-
///--- Globals
var DEF_CT = 'application/octet-stream';
@@ -33,135 +32,133 @@ var UnsupportedMediaTypeError = errors.UnsupportedMediaTypeError;
var shallowCopy = utils.shallowCopy;
-
///--- Helpers
function createCachedRoute(o, path, version, route) {
- if (!o.hasOwnProperty(path))
- o[path] = {};
+ if (!o.hasOwnProperty(path))
+ o[path] = {};
- if (!o[path].hasOwnProperty(version))
- o[path][version] = route;
+ if (!o[path].hasOwnProperty(version))
+ o[path][version] = route;
}
function matchURL(re, req) {
- var i = 0;
- var result = re.exec(req.path());
- var params = {};
+ var i = 0;
+ var result = re.exec(req.path());
+ var params = {};
- if (!result)
- return (false);
+ if (!result)
+ return (false);
- // This means the user original specified a regexp match, not a url
- // string like /:foo/:bar
- if (!re.restifyParams) {
- for (i = 1; i < result.length; i++)
- params[(i - 1)] = result[i];
+ // This means the user original specified a regexp match, not a url
+ // string like /:foo/:bar
+ if (!re.restifyParams) {
+ for (i = 1; i < result.length; i++)
+ params[(i - 1)] = result[i];
- return (params);
- }
+ return (params);
+ }
- // This was a static string, like /foo
- if (re.restifyParams.length === 0)
- return (params);
+ // This was a static string, like /foo
+ if (re.restifyParams.length === 0)
+ return (params);
- // This was the "normal" case, of /foo/:id
- re.restifyParams.forEach(function (p) {
- if (++i < result.length)
- params[p] = decodeURIComponent(result[i]);
- });
+ // This was the "normal" case, of /foo/:id
+ re.restifyParams.forEach(function (p) {
+ if (++i < result.length)
+ params[p] = decodeURIComponent(result[i]);
+ });
- return (params);
+ return (params);
}
function compileURL(options) {
- if (options.url instanceof RegExp)
- return (options.url);
- assert.string(options.url, 'url');
-
- var params = [];
- var pattern = '^';
- var re;
- var _url = url.parse(options.url).pathname;
- _url.split('/').forEach(function (frag) {
- if (frag.length <= 0)
- return (false);
-
- pattern += '\\/+';
- if (frag.charAt(0) === ':') {
- if (options.urlParamPattern) {
- pattern += '(' + options.urlParamPattern + ')';
- } else {
- // Strictly adhere to RFC3986
- pattern += '([a-zA-Z0-9-_~\\.%@]+)';
- }
- params.push(frag.slice(1));
- } else {
- pattern += frag;
- }
+ if (options.url instanceof RegExp)
+ return (options.url);
+ assert.string(options.url, 'url');
+
+ var params = [];
+ var pattern = '^';
+ var re;
+ var _url = url.parse(options.url).pathname;
+ _url.split('/').forEach(function (frag) {
+ if (frag.length <= 0)
+ return (false);
+
+ pattern += '\\/+';
+ if (frag.charAt(0) === ':') {
+ if (options.urlParamPattern) {
+ pattern += '(' + options.urlParamPattern + ')';
+ } else {
+ // Strictly adhere to RFC3986
+ pattern += '([a-zA-Z0-9-_~\\.%@]+)';
+ }
+ params.push(frag.slice(1));
+ } else {
+ pattern += frag;
+ }
- return (true);
- });
+ return (true);
+ });
- if (pattern === '^')
- pattern += '\\/';
- pattern += '$';
+ if (pattern === '^')
+ pattern += '\\/';
+ pattern += '$';
- re = new RegExp(pattern, options.flags);
- re.restifyParams = params;
+ re = new RegExp(pattern, options.flags);
+ re.restifyParams = params;
- return (re);
+ return (re);
}
-
///--- API
function Router(options) {
- assert.object(options, 'options');
- assert.object(options.log, 'options.log');
-
- EventEmitter.call(this);
-
- this.cache = LRU({max: 100});
- this.contentType = options.contentType || [];
- if (!Array.isArray(this.contentType))
- this.contentType = [this.contentType];
- assert.arrayOfString(this.contentType, 'options.contentType');
-
- this.log = options.log;
- this.mounts = {};
- this.name = 'RestifyRouter';
-
- // A list of methods to routes
- this.routes = {
- DELETE: [],
- GET: [],
- HEAD: [],
- OPTIONS: [],
- PATCH: [],
- POST: [],
- PUT: []
- };
-
- // So we can retrun 405 vs 404, we maintain a reverse mapping of URLs
- // to method
- this.reverse = {};
-
- this.versions = options.versions || options.version || [];
- if (!Array.isArray(this.versions))
- this.versions = [this.versions];
- assert.arrayOfString(this.versions, 'options.versions');
-
- this.versions.forEach(function (v) {
- if (semver.valid(v))
- return (true);
-
- throw new InvalidArgumentError('%s is not a valid semver', v);
- });
- this.versions.sort();
+ assert.object(options, 'options');
+ assert.object(options.log, 'options.log');
+
+ EventEmitter.call(this);
+
+ this.cache = LRU({max: 100});
+ this.contentType = options.contentType || [];
+ if (!Array.isArray(this.contentType))
+ this.contentType = [this.contentType];
+ assert.arrayOfString(this.contentType, 'options.contentType');
+
+ this.log = options.log;
+ this.mounts = {};
+ this.name = 'RestifyRouter';
+
+ // A list of methods to routes
+ this.routes = {
+ DELETE: [],
+ GET: [],
+ HEAD: [],
+ OPTIONS: [],
+ PATCH: [],
+ POST: [],
+ PUT: []
+ };
+
+ // So we can retrun 405 vs 404, we maintain a reverse mapping of URLs
+ // to method
+ this.reverse = {};
+
+ this.versions = options.versions || options.version || [];
+ if (!Array.isArray(this.versions))
+ this.versions = [this.versions];
+ assert.arrayOfString(this.versions, 'options.versions');
+
+ this.versions.forEach(function (v) {
+ if (semver.valid(v))
+ return (true);
+
+ throw new InvalidArgumentError('%s is not a valid semver', v);
+ });
+ this.versions.sort();
}
util.inherits(Router, EventEmitter);
@@ -169,322 +166,321 @@ module.exports = Router;
Router.prototype.mount = function mount(options) {
- assert.object(options, 'options');
- assert.string(options.method, 'options.method');
- assert.string(options.name, 'options.name');
-
- var exists;
- var name = options.name;
- var route;
- var routes = this.routes[options.method];
- var self = this;
- var type = options.contentType || self.contentType;
- var versions = options.versions || options.version || self.versions;
-
- if (type) {
- if (!Array.isArray(type))
- type = [type];
- type.filter(function (t) {
- return (t);
- }).sort().join();
- }
-
- if (versions) {
- if (!Array.isArray(versions))
- versions = [versions];
- versions.sort();
- }
-
- exists = routes.some(function (r) {
- return (r.name === name);
- });
- if (exists)
- return (false);
-
- route = {
- name: name,
- method: options.method,
- path: compileURL({
- url: options.path || options.url,
- flags: options.flags,
- urlParamPattern: options.urlParamPattern
- }),
- spec: options,
- types: type,
- versions: versions
- };
- routes.push(route);
-
- if (!this.reverse[route.path.source])
- this.reverse[route.path.source] = [];
-
- if (this.reverse[route.path.source].indexOf(route.method) === -1)
- this.reverse[route.path.source].push(route.method);
-
- this.mounts[route.name] = route;
-
- this.emit('mount',
- route.method,
- route.path,
- route.types,
- route.versions);
-
- return (route.name);
+ assert.object(options, 'options');
+ assert.string(options.method, 'options.method');
+ assert.string(options.name, 'options.name');
+
+ var exists;
+ var name = options.name;
+ var route;
+ var routes = this.routes[options.method];
+ var self = this;
+ var type = options.contentType || self.contentType;
+ var versions = options.versions || options.version || self.versions;
+
+ if (type) {
+ if (!Array.isArray(type))
+ type = [type];
+ type.filter(function (t) {
+ return (t);
+ }).sort().join();
+ }
+
+ if (versions) {
+ if (!Array.isArray(versions))
+ versions = [versions];
+ versions.sort();
+ }
+
+ exists = routes.some(function (r) {
+ return (r.name === name);
+ });
+ if (exists)
+ return (false);
+
+ route = {
+ name: name,
+ method: options.method,
+ path: compileURL({
+ url: options.path || options.url,
+ flags: options.flags,
+ urlParamPattern: options.urlParamPattern
+ }),
+ spec: options,
+ types: type,
+ versions: versions
+ };
+ routes.push(route);
+
+ if (!this.reverse[route.path.source])
+ this.reverse[route.path.source] = [];
+
+ if (this.reverse[route.path.source].indexOf(route.method) === -1)
+ this.reverse[route.path.source].push(route.method);
+
+ this.mounts[route.name] = route;
+
+ this.emit('mount',
+ route.method,
+ route.path,
+ route.types,
+ route.versions);
+
+ return (route.name);
};
Router.prototype.unmount = function unmount(name) {
- var route = this.mounts[name];
- if (!route) {
- this.log.warn('router.unmount(%s): route does not exist', name);
- return (false);
- }
+ var route = this.mounts[name];
+ if (!route) {
+ this.log.warn('router.unmount(%s): route does not exist', name);
+ return (false);
+ }
- var reverse = this.reverse[route.path.source];
- var routes = this.routes[route.method];
- this.routes[route.method] = routes.filter(function (r) {
- return (r.name !== route.name);
- });
+ var reverse = this.reverse[route.path.source];
+ var routes = this.routes[route.method];
+ this.routes[route.method] = routes.filter(function (r) {
+ return (r.name !== route.name);
+ });
- this.reverse[route.path.source] = reverse.filter(function (r) {
- return (r !== route.method);
- });
+ this.reverse[route.path.source] = reverse.filter(function (r) {
+ return (r !== route.method);
+ });
- if (this.reverse[route.path.source].length === 0)
- delete this.reverse[route.path.source];
+ if (this.reverse[route.path.source].length === 0)
+ delete this.reverse[route.path.source];
- delete this.mounts[name];
+ delete this.mounts[name];
- return (name);
+ return (name);
};
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;
- }
+ 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());
- }
+ if (route) {
+ cb(null, route, params || {});
+ } else {
+ cb(new InternalError());
+ }
};
Router.prototype.find = function find(req, res, callback) {
- var candidates = [];
- var ct = req.headers['content-type'] || DEF_CT;
- var cacheKey = req.method + req.url + req.version() + ct;
- var cacheVal;
- var neg;
- var params;
- var r;
- var reverse;
- var routes = this.routes[req.method] || [];
- var typed;
- var versioned;
-
- if ((cacheVal = this.cache.get(cacheKey))) {
- res.methods = cacheVal.methods.slice();
- callback(null, cacheVal, shallowCopy(cacheVal.params));
- return;
+ var candidates = [];
+ var ct = req.headers['content-type'] || DEF_CT;
+ var cacheKey = req.method + req.url + req.version() + ct;
+ var cacheVal;
+ var neg;
+ var params;
+ var r;
+ var reverse;
+ var routes = this.routes[req.method] || [];
+ var typed;
+ var versioned;
+
+ if ((cacheVal = this.cache.get(cacheKey))) {
+ res.methods = cacheVal.methods.slice();
+ callback(null, cacheVal, shallowCopy(cacheVal.params));
+ return;
+ }
+
+ for (var i = 0; i < routes.length; i++) {
+ try {
+ params = matchURL(routes[i].path, req);
+ } catch (e) {
+ this.log.trace({err: e}, 'error parsing URL');
+ callback(new BadRequestError(e.message));
+ return;
}
- for (var i = 0; i < routes.length; i++) {
- try {
- params = matchURL(routes[i].path, req);
- } catch (e) {
- this.log.trace({err: e}, 'error parsing URL');
- callback(new BadRequestError(e.message));
- return;
- }
-
- if (params === false)
- continue;
-
- reverse = this.reverse[routes[i].path.source];
-
- if (routes[i].types.length && req.isUpload()) {
- candidates.push({
- p: params,
- r: routes[i]
- });
- typed = true;
- continue;
- }
+ if (params === false)
+ continue;
- // 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;
- }
+ reverse = this.reverse[routes[i].path.source];
- if (routes[i].versions.length > 0) {
- candidates.push({
- p: params,
- r: routes[i]
- });
- versioned = true;
- }
+ if (routes[i].types.length && req.isUpload()) {
+ candidates.push({
+ p: params,
+ r: routes[i]
+ });
+ typed = true;
+ continue;
}
- if (!r) {
- // If upload and typed
- if (typed) {
- /* JSSTYLED */
- var _t = ct.split(/\s*,\s*/);
- candidates = candidates.filter(function (c) {
- neg = new Negotiator({
- headers: {
- accept: c.r.types.join(', ')
- }
- });
- var tmp = neg.preferredMediaType(_t);
- return (tmp && tmp.length);
- });
-
- // Pick the first one in case not versioned
- if (candidates.length) {
- r = candidates[0].r;
- params = candidates[0].p;
- }
- }
-
- if (versioned) {
- candidates.forEach(function (c) {
- var k = c.r.versions;
- var v = semver.maxSatisfying(k, req.version());
-
- if (v) {
- if (!r ||
- r.versions.some(function (v2) {
- return (semver.gt(v, v2));
- })) {
- r = c.r;
- params = c.p;
- }
- }
- });
- }
+ // 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;
}
- // In order, we check if the route exists, in which case, we're good.
- // Otherwise we look to see if ver was set to false; that would tell us
- // we indeed did find a matching route (method+url), but the version
- // field didn't line up, so we return bad version. If no route and no
- // version, we now need to go walk the reverse map and look at whether
- // we should return 405 or 404. If it was an OPTIONS request, we need
- // to handle this having been a preflight request.
- if (params && r) {
- cacheVal = {
- methods: reverse,
- name: r.name,
- params: params,
- spec: r.spec
- };
- this.cache.set(cacheKey, cacheVal);
- res.methods = reverse.slice();
- callback(null, cacheVal, shallowCopy(params));
- return;
+ if (routes[i].versions.length > 0) {
+ candidates.push({
+ p: params,
+ r: routes[i]
+ });
+ versioned = true;
}
+ }
+ if (!r) {
+ // If upload and typed
if (typed) {
- callback(new UnsupportedMediaTypeError(ct));
- return;
- }
- if (versioned) {
- callback(new InvalidVersionError('%s is not supported by %s %s',
- req.version() || '?',
- req.method,
- req.path()));
- return;
+ /* JSSTYLED */
+ var _t = ct.split(/\s*,\s*/);
+ candidates = candidates.filter(function (c) {
+ neg = new Negotiator({
+ headers: {
+ accept: c.r.types.join(', ')
+ }
+ });
+ var tmp = neg.preferredMediaType(_t);
+ return (tmp && tmp.length);
+ });
+
+ // Pick the first one in case not versioned
+ if (candidates.length) {
+ r = candidates[0].r;
+ params = candidates[0].p;
+ }
}
- // This is a very generic preflight handler - it does
- // not handle requiring authentication, nor does it do
- // any special checking for extra user headers. The
- // user will need to defined their own .opts handler to
- // do that
- function preflight(methods) {
- var headers = req.headers['access-control-request-headers'];
- var method = req.headers['access-control-request-method'];
- var origin = req.headers['origin'];
-
- if (req.method !== 'OPTIONS' ||
- !origin ||
- !method ||
- methods.indexOf(method) === -1) {
- return (false);
+ if (versioned) {
+ candidates.forEach(function (c) {
+ var k = c.r.versions;
+ var v = semver.maxSatisfying(k, req.version());
+
+ if (v) {
+ if (!r ||
+ r.versions.some(function (v2) {
+ return (semver.gt(v, v2));
+ })) {
+ r = c.r;
+ params = c.p;
+ }
}
- // Last, check request-headers
- var ok = true;
- /* JSSTYLED */
- (headers || '').split(/\s*,\s*/).forEach(function (h) {
- if (!h)
- return;
-
- h = h.toLowerCase();
- ok = cors.ALLOW_HEADERS.indexOf(h) !== -1 && ok;
- });
- if (!ok)
- return (false);
-
- res.setHeader('Access-Control-Allow-Origin', '*');
- res.setHeader('Access-Control-Allow-Methods',
- methods.join(', '));
- res.setHeader('Access-Control-Allow-Headers',
- cors.ALLOW_HEADERS.join(', '));
- res.setHeader('Access-Control-Max-Age', 3600);
-
- return (true);
+ });
+ }
+ }
+
+ // In order, we check if the route exists, in which case, we're good.
+ // Otherwise we look to see if ver was set to false; that would tell us
+ // we indeed did find a matching route (method+url), but the version
+ // field didn't line up, so we return bad version. If no route and no
+ // version, we now need to go walk the reverse map and look at whether
+ // we should return 405 or 404. If it was an OPTIONS request, we need
+ // to handle this having been a preflight request.
+ if (params && r) {
+ cacheVal = {
+ methods: reverse,
+ name: r.name,
+ params: params,
+ spec: r.spec
+ };
+ this.cache.set(cacheKey, cacheVal);
+ res.methods = reverse.slice();
+ callback(null, cacheVal, shallowCopy(params));
+ return;
+ }
+
+ if (typed) {
+ callback(new UnsupportedMediaTypeError(ct));
+ return;
+ }
+ if (versioned) {
+ callback(new InvalidVersionError('%s is not supported by %s %s',
+ req.version() || '?',
+ req.method,
+ req.path()));
+ return;
+ }
+
+ // This is a very generic preflight handler - it does
+ // not handle requiring authentication, nor does it do
+ // any special checking for extra user headers. The
+ // user will need to defined their own .opts handler to
+ // do that
+ function preflight(methods) {
+ var headers = req.headers['access-control-request-headers'];
+ var method = req.headers['access-control-request-method'];
+ var origin = req.headers['origin'];
+
+ if (req.method !== 'OPTIONS' || !origin || !method ||
+ methods.indexOf(method) === -1) {
+ return (false);
}
+ // Last, check request-headers
+ var ok = true;
+ /* JSSTYLED */
+ (headers || '').split(/\s*,\s*/).forEach(function (h) {
+ if (!h)
+ return;
- // Check for 405 instead of 404
- var urls = Object.keys(this.reverse);
- for (i = 0; i < urls.length; i++) {
- if (matchURL(new RegExp(urls[i]), req)) {
- res.methods = this.reverse[urls[i]].slice();
- res.setHeader('Allow', res.methods.join(', '));
- if (preflight(res.methods)) {
- callback(null, { name: 'preflight' });
- return;
- }
- var err = new MethodNotAllowedError('%s is not allowed',
- req.method);
- callback(err);
- return;
- }
+ h = h.toLowerCase();
+ ok = cors.ALLOW_HEADERS.indexOf(h) !== -1 && ok;
+ });
+ if (!ok)
+ return (false);
+
+ res.setHeader('Access-Control-Allow-Origin', '*');
+ res.setHeader('Access-Control-Allow-Methods',
+ methods.join(', '));
+ res.setHeader('Access-Control-Allow-Headers',
+ cors.ALLOW_HEADERS.join(', '));
+ res.setHeader('Access-Control-Max-Age', 3600);
+
+ return (true);
+ }
+
+ // Check for 405 instead of 404
+ var urls = Object.keys(this.reverse);
+ for (i = 0; i < urls.length; i++) {
+ if (matchURL(new RegExp(urls[i]), req)) {
+ res.methods = this.reverse[urls[i]].slice();
+ res.setHeader('Allow', res.methods.join(', '));
+ if (preflight(res.methods)) {
+ callback(null, { name: 'preflight' });
+ return;
+ }
+ var err = new MethodNotAllowedError('%s is not allowed',
+ req.method);
+ callback(err);
+ return;
}
+ }
- callback(new ResourceNotFoundError('%s does not exist', req.url));
+ callback(new ResourceNotFoundError('%s does not exist', req.url));
};
Router.prototype.toString = function toString() {
- var self = this;
- var str = this.name + ':\n';
-
- Object.keys(this.routes).forEach(function (k) {
- var routes = self.routes[k].map(function (r) {
- return (r.name);
- });
+ var self = this;
+ var str = this.name + ':\n';
- str += '\t\t' + k + ': [' + routes.join(', ') + ']\n';
+ Object.keys(this.routes).forEach(function (k) {
+ var routes = self.routes[k].map(function (r) {
+ return (r.name);
});
- return (str);
+ str += '\t\t' + k + ': [' + routes.join(', ') + ']\n';
+ });
+
+ return (str);
};
diff --git a/lib/server.js b/lib/server.js
index ced5c544f..babe794d8 100644
--- a/lib/server.js
+++ b/lib/server.js
@@ -27,7 +27,6 @@ require('./request');
require('./response');
-
///--- Globals
var sprintf = util.format;
@@ -37,266 +36,264 @@ var InvalidVersionError = errors.InvalidVersionError;
var ResourceNotFoundError = errors.ResourceNotFoundError;
var PROXY_EVENTS = [
- 'clientError',
- 'close',
- 'connection',
- 'error',
- 'listening',
- 'secureConnection'
+ 'clientError',
+ 'close',
+ 'connection',
+ 'error',
+ 'listening',
+ 'secureConnection'
];
-
///--- Helpers
function argumentsToChain(args, start) {
- assert.ok(args);
+ assert.ok(args);
- args = Array.prototype.slice.call(args, start);
+ args = Array.prototype.slice.call(args, start);
- if (args.length < 0)
- throw new TypeError('handler (function) required');
+ if (args.length < 0)
+ throw new TypeError('handler (function) required');
- var chain = [];
+ var chain = [];
- function process(handlers) {
- for (var i = 0; i < handlers.length; i++) {
- if (Array.isArray(handlers[i])) {
- process(handlers[i], 0);
- } else {
- assert.func(handlers[i], 'handler');
- chain.push(handlers[i]);
- }
- }
-
- return (chain);
+ function process(handlers) {
+ for (var i = 0; i < handlers.length; i++) {
+ if (Array.isArray(handlers[i])) {
+ process(handlers[i], 0);
+ } else {
+ assert.func(handlers[i], 'handler');
+ chain.push(handlers[i]);
+ }
}
- return (process(args));
+ return (chain);
+ }
+
+ return (process(args));
}
function mergeFormatters(fmt) {
- var arr = [];
- var defaults = Object.keys(formatters).length;
- var i = 0;
- var obj = {};
-
- function addFormatter(src, k) {
- assert.func(src[k], 'formatter');
-
- var q;
- var t = k;
- if (k.indexOf(';') !== -1) {
- /* JSSTYLED */
- var tmp = k.split(/\s*;\s*/);
- t = tmp[0];
- if (tmp[1].indexOf('q=') !== -1) {
- q = parseFloat(tmp[1].split('=')[1], 10) * 10;
- }
- }
-
- if (k.indexOf('/') === -1)
- k = mime.lookup(k);
-
- obj[t] = src[k];
- arr.push({
- q: q || (i + defaults),
- t: t
- });
- i++;
+ var arr = [];
+ var defaults = Object.keys(formatters).length;
+ var i = 0;
+ var obj = {};
+
+ function addFormatter(src, k) {
+ assert.func(src[k], 'formatter');
+
+ var q;
+ var t = k;
+ if (k.indexOf(';') !== -1) {
+ /* JSSTYLED */
+ var tmp = k.split(/\s*;\s*/);
+ t = tmp[0];
+ if (tmp[1].indexOf('q=') !== -1) {
+ q = parseFloat(tmp[1].split('=')[1], 10) * 10;
+ }
}
- Object.keys(formatters).forEach(addFormatter.bind(this, formatters));
- Object.keys(fmt || {}).forEach(addFormatter.bind(this, fmt || {}));
+ if (k.indexOf('/') === -1)
+ k = mime.lookup(k);
- arr = arr.sort(function (a, b) {
- return (b.q - a.q);
- }).map(function (a) {
- return (a.t);
+ obj[t] = src[k];
+ arr.push({
+ q: q || (i + defaults),
+ t: t
});
+ i++;
+ }
- return ({
- formatters: obj,
- acceptable: arr
+ Object.keys(formatters).forEach(addFormatter.bind(this, formatters));
+ Object.keys(fmt || {}).forEach(addFormatter.bind(this, fmt || {}));
+
+ arr = arr.sort(function (a, b) {
+ return (b.q - a.q);
+ }).map(function (a) {
+ return (a.t);
});
+
+ return ({
+ formatters: obj,
+ acceptable: arr
+ });
}
function ifError(n) {
- function _ifError(err) {
- if (err) {
- err._restify_next = n;
- throw err;
- }
+ function _ifError(err) {
+ if (err) {
+ err._restify_next = n;
+ throw err;
}
- return (_ifError);
+ }
+
+ 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);
- }
+ 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;
+ var code = err.statusCode;
+ var ok = false;
- if (code === 404 && req.method === 'OPTIONS' && req.url === '*') {
- res.send(200);
- ok = true;
- }
+ if (code === 404 && req.method === 'OPTIONS' && req.url === '*') {
+ res.send(200);
+ ok = true;
+ }
- return (ok);
+ return (ok);
}
-
///--- API
function Server(options) {
- assert.object(options, 'options');
- assert.object(options.log, 'options.log');
- assert.object(options.router, 'options.router');
-
- var self = this;
-
- EventEmitter.call(this);
-
- this.before = [];
- this.chain = [];
- this.log = options.log;
- this.name = options.name || 'restify';
- this.router = options.router;
- this.routes = {};
- this.secure = false;
- this.versions = options.versions || options.version || [];
-
- var fmt = mergeFormatters(options.formatters);
- this.acceptable = fmt.acceptable;
- this.formatters = fmt.formatters;
-
- if (options.spdy) {
- this.spdy = true;
- this.server = spdy.createServer(options.spdy);
- } else if ((options.cert || options.certificate) && options.key) {
- this.ca = options.ca;
- this.certificate = options.certificate || options.cert;
- this.key = options.key;
- this.passphrase = options.passphrase || null;
- this.secure = true;
-
- this.server = https.createServer({
- ca: self.ca,
- cert: self.certificate,
- key: self.key,
- passphrase: self.passphrase,
- rejectUnauthorized: options.rejectUnauthorized,
- requestCert: options.requestCert,
- ciphers: options.ciphers
- });
- } else {
- this.server = http.createServer();
- }
-
- this.router.on('mount', this.emit.bind(this, 'mount'));
-
- if (!options.handleUpgrades && PROXY_EVENTS.indexOf('upgrade') === -1)
- PROXY_EVENTS.push('upgrade');
- PROXY_EVENTS.forEach(function (e) {
- self.server.on(e, self.emit.bind(self, e));
+ assert.object(options, 'options');
+ assert.object(options.log, 'options.log');
+ assert.object(options.router, 'options.router');
+
+ var self = this;
+
+ EventEmitter.call(this);
+
+ this.before = [];
+ this.chain = [];
+ this.log = options.log;
+ this.name = options.name || 'restify';
+ this.router = options.router;
+ this.routes = {};
+ this.secure = false;
+ this.versions = options.versions || options.version || [];
+
+ var fmt = mergeFormatters(options.formatters);
+ this.acceptable = fmt.acceptable;
+ this.formatters = fmt.formatters;
+
+ if (options.spdy) {
+ this.spdy = true;
+ this.server = spdy.createServer(options.spdy);
+ } else if ((options.cert || options.certificate) && options.key) {
+ this.ca = options.ca;
+ this.certificate = options.certificate || options.cert;
+ this.key = options.key;
+ this.passphrase = options.passphrase || null;
+ this.secure = true;
+
+ this.server = https.createServer({
+ ca: self.ca,
+ cert: self.certificate,
+ key: self.key,
+ passphrase: self.passphrase,
+ rejectUnauthorized: options.rejectUnauthorized,
+ requestCert: options.requestCert,
+ ciphers: options.ciphers
});
+ } else {
+ this.server = http.createServer();
+ }
+
+ this.router.on('mount', this.emit.bind(this, 'mount'));
+
+ if (!options.handleUpgrades && PROXY_EVENTS.indexOf('upgrade') === -1)
+ PROXY_EVENTS.push('upgrade');
+ PROXY_EVENTS.forEach(function (e) {
+ self.server.on(e, self.emit.bind(self, e));
+ });
+
+ // Now the things we can't blindly proxy
+ this.server.on('checkContinue', function onCheckContinue(req, res) {
+ if (self.listeners('checkContinue').length > 0) {
+ self.emit('checkContinue', req, res);
+ return;
+ }
- // Now the things we can't blindly proxy
- this.server.on('checkContinue', function onCheckContinue(req, res) {
- if (self.listeners('checkContinue').length > 0) {
- self.emit('checkContinue', req, res);
- return;
- }
+ if (!options.noWriteContinue)
+ res.writeContinue();
- if (!options.noWriteContinue)
- res.writeContinue();
+ self._setupRequest(req, res);
+ self._handle(req, res, true);
+ });
- self._setupRequest(req, res);
- self._handle(req, res, true);
+ if (options.handleUpgrades) {
+ this.server.on('upgrade', function onUpgrade(req, socket, head) {
+ req._upgradeRequest = true;
+ var res = upgrade.createResponse(req, socket, head);
+ self._setupRequest(req, res);
+ self._handle(req, res);
});
+ }
- if (options.handleUpgrades) {
- this.server.on('upgrade', function onUpgrade(req, socket,
- head) {
- req._upgradeRequest = true;
- var res = upgrade.createResponse(req, socket, head);
- self._setupRequest(req, res);
- self._handle(req, res);
- });
- }
+ this.server.on('request', function onRequest(req, res) {
+ self.emit('request', req, res);
+ /* JSSTYLED */
+ if (/^\/socket.io.*/.test(req.url))
+ return;
- this.server.on('request', function onRequest(req, res) {
- self.emit('request', req, res);
- /* JSSTYLED */
- if (/^\/socket.io.*/.test(req.url))
- return;
+ self._setupRequest(req, res);
+ self._handle(req, res);
+ });
- self._setupRequest(req, res);
- self._handle(req, res);
- });
+ this.__defineGetter__('maxHeadersCount', function () {
+ return (self.server.maxHeadersCount);
+ });
- this.__defineGetter__('maxHeadersCount', function () {
- return (self.server.maxHeadersCount);
- });
+ this.__defineSetter__('maxHeadersCount', function (c) {
+ self.server.maxHeadersCount = c;
+ return (c);
+ });
- this.__defineSetter__('maxHeadersCount', function (c) {
- self.server.maxHeadersCount = c;
- return (c);
- });
+ this.__defineGetter__('url', function () {
+ if (self.socketPath)
+ return ('http://' + self.socketPath);
- this.__defineGetter__('url', function () {
- if (self.socketPath)
- return ('http://' + self.socketPath);
-
- var addr = self.address();
- var str = '';
- if (self.spdy) {
- str += 'spdy://';
- } else if (self.secure) {
- str += 'https://';
- } else {
- str += 'http://';
- }
+ var addr = self.address();
+ var str = '';
+ if (self.spdy) {
+ str += 'spdy://';
+ } else if (self.secure) {
+ str += 'https://';
+ } else {
+ str += 'http://';
+ }
- if (addr) {
- str += addr.address;
- str += ':';
- str += addr.port;
- } else {
- str += '169.254.0.1:0000';
- }
+ if (addr) {
+ str += addr.address;
+ str += ':';
+ str += addr.port;
+ } else {
+ str += '169.254.0.1:0000';
+ }
- return (str);
- });
+ return (str);
+ });
}
util.inherits(Server, EventEmitter);
module.exports = Server;
Server.prototype.address = function address() {
- return (this.server.address());
+ return (this.server.address());
};
/**
@@ -311,8 +308,8 @@ Server.prototype.address = function address() {
* @throws {TypeError} on bad input.
*/
Server.prototype.listen = function listen() {
- var args = Array.prototype.slice.call(arguments);
- return (this.server.listen.apply(this.server, args));
+ var args = Array.prototype.slice.call(arguments);
+ return (this.server.listen.apply(this.server, args));
};
@@ -322,14 +319,14 @@ Server.prototype.listen = function listen() {
* @param {Function} callback optional callback to invoke when done.
*/
Server.prototype.close = function close(callback) {
- if (callback)
- assert.func(callback, 'callback');
+ if (callback)
+ assert.func(callback, 'callback');
- this.server.once('close', function onClose() {
- return (callback ? callback() : false);
- });
+ this.server.once('close', function onClose() {
+ return (callback ? callback() : false);
+ });
- return (this.server.close());
+ return (this.server.close());
};
@@ -341,71 +338,71 @@ Server.prototype.close = function close(callback) {
* @return {Route} the newly created route.
*/
[
- 'del',
- 'get',
- 'head',
- 'opts',
- 'post',
- 'put',
- 'patch'
+ 'del',
+ 'get',
+ 'head',
+ 'opts',
+ 'post',
+ 'put',
+ 'patch'
].forEach(function (method) {
Server.prototype[method] = function (opts) {
- if (opts instanceof RegExp || typeof (opts) === 'string') {
- opts = {
- path: opts
- };
- } else if (typeof (opts) === 'object') {
- opts = shallowCopy(opts);
- } else {
- throw new TypeError('path (string) required');
- }
-
- if (arguments.length < 2)
- throw new TypeError('handler (function) required');
-
- var chain = [];
- var route;
- var self = this;
-
- function addHandler(h) {
- assert.func(h, 'handler');
+ if (opts instanceof RegExp || typeof (opts) === 'string') {
+ opts = {
+ path: opts
+ };
+ } else if (typeof (opts) === 'object') {
+ opts = shallowCopy(opts);
+ } else {
+ throw new TypeError('path (string) required');
+ }
+
+ if (arguments.length < 2)
+ throw new TypeError('handler (function) required');
- chain.push(h);
+ var chain = [];
+ var route;
+ var self = this;
+
+ function addHandler(h) {
+ assert.func(h, 'handler');
+
+ chain.push(h);
+ }
+
+ if (method === 'del')
+ method = 'DELETE';
+ if (method === 'opts')
+ method = 'OPTIONS';
+ opts.method = method.toUpperCase();
+ 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.versions.length > 0) {
+ opts.name += '-' + opts.versions.join('--');
}
- if (method === 'del')
- method = 'DELETE';
- if (method === 'opts')
- method = 'OPTIONS';
- opts.method = method.toUpperCase();
- 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.versions.length > 0) {
- opts.name += '-' + opts.versions.join('--');
- }
-
- opts.name = opts.name.replace(/\W/g, '').toLowerCase();
- if (this.router.mounts[opts.name]) // GH-401
- opts.name += uuid.v4().substr(0, 7);
- } else {
- opts.name = opts.name.replace(/\W/g, '').toLowerCase();
- }
+ opts.name = opts.name.replace(/\W/g, '').toLowerCase();
+ if (this.router.mounts[opts.name]) // GH-401
+ opts.name += uuid.v4().substr(0, 7);
+ } else {
+ opts.name = opts.name.replace(/\W/g, '').toLowerCase();
+ }
- if (!(route = this.router.mount(opts)))
- return (false);
+ if (!(route = this.router.mount(opts)))
+ return (false);
- this.chain.forEach(addHandler);
- argumentsToChain(arguments, 1).forEach(addHandler);
- this.routes[route] = chain;
+ this.chain.forEach(addHandler);
+ argumentsToChain(arguments, 1).forEach(addHandler);
+ this.routes[route] = chain;
- return (route);
+ return (route);
};
-});
+ });
/**
@@ -426,15 +423,15 @@ Server.prototype.close = function close(callback) {
* @param {Function} The middleware function to execute
*/
Server.prototype.param = function param(name, fn) {
- this.use(function _param(req, res, next) {
- if (req.params && req.params[name]) {
- fn.call(this, req, res, next, req.params[name], name);
- } else {
- next();
- }
- });
+ this.use(function _param(req, res, next) {
+ if (req.params && req.params[name]) {
+ fn.call(this, req, res, next, req.params[name], name);
+ } else {
+ next();
+ }
+ });
- return (this);
+ return (this);
};
@@ -456,27 +453,27 @@ Server.prototype.param = function param(name, fn) {
* will be the selected version
*/
Server.prototype.versionedUse = function versionedUse(versions, fn) {
- if (!Array.isArray(versions))
- versions = [versions];
- assert.arrayOfString(versions, 'versions');
-
- versions.forEach(function (v) {
- if (!semver.valid(v))
- throw new TypeError('%s is not a valid semver', v);
- });
-
- this.use(function _versionedUse(req, res, next) {
- var ver;
- if (req.version() === '*' ||
- (ver = maxSatisfying(versions,
- req.version()) || false)) {
- fn.call(this, req, res, next, ver);
- } else {
- next();
- }
- });
+ if (!Array.isArray(versions))
+ versions = [versions];
+ assert.arrayOfString(versions, 'versions');
+
+ versions.forEach(function (v) {
+ if (!semver.valid(v))
+ throw new TypeError('%s is not a valid semver', v);
+ });
+
+ this.use(function _versionedUse(req, res, next) {
+ var ver;
+ if (req.version() === '*' ||
+ (ver = maxSatisfying(versions,
+ req.version()) || false)) {
+ fn.call(this, req, res, next, ver);
+ } else {
+ next();
+ }
+ });
- return (this);
+ return (this);
};
@@ -490,11 +487,11 @@ Server.prototype.versionedUse = function versionedUse(versions, fn) {
* @throws {TypeError} on bad input.
*/
Server.prototype.rm = function rm(route) {
- var r = this.router.unmount(route);
- if (r && this.routes[r])
- delete this.routes[r];
+ var r = this.router.unmount(route);
+ if (r && this.routes[r])
+ delete this.routes[r];
- return (r);
+ return (r);
};
@@ -507,13 +504,13 @@ Server.prototype.rm = function rm(route) {
* @throws {TypeError} on input error.
*/
Server.prototype.use = function use() {
- var self = this;
+ var self = this;
- (argumentsToChain(arguments) || []).forEach(function (h) {
- self.chain.push(h);
- });
+ (argumentsToChain(arguments) || []).forEach(function (h) {
+ self.chain.push(h);
+ });
- return (this);
+ return (this);
};
@@ -523,114 +520,113 @@ Server.prototype.use = function use() {
* depends on. Note that req.params will _not_ be set yet.
*/
Server.prototype.pre = function pre() {
- var self = this;
+ var self = this;
- argumentsToChain(arguments).forEach(function (h) {
- self.before.push(h);
- });
+ argumentsToChain(arguments).forEach(function (h) {
+ self.before.push(h);
+ });
- return (this);
+ return (this);
};
Server.prototype.toString = function toString() {
- var LINE_FMT = '\t%s: %s\n';
- var SUB_LINE_FMT = '\t\t%s: %s\n';
- var self = this;
- var str = '';
-
- function handlersToString(arr) {
- var s = '[' + arr.map(function (b) {
- return (b.name || 'function');
- }).join(', ') + ']';
-
- return (s);
- }
-
- str += sprintf(LINE_FMT, 'Accepts', this.acceptable.join(', '));
- str += sprintf(LINE_FMT, 'Name', this.name);
- str += sprintf(LINE_FMT, 'Pre', handlersToString(this.before));
- str += sprintf(LINE_FMT, 'Router', this.router.toString());
- str += sprintf(LINE_FMT, 'Routes', '');
- Object.keys(this.routes).forEach(function (k) {
- var handlers = handlersToString(self.routes[k]);
- str += sprintf(SUB_LINE_FMT, k, handlers);
- });
- str += sprintf(LINE_FMT, 'Secure', this.secure);
- str += sprintf(LINE_FMT, 'Url', this.url);
- str += sprintf(LINE_FMT, 'Version', this.versions.join());
-
- return (str);
+ var LINE_FMT = '\t%s: %s\n';
+ var SUB_LINE_FMT = '\t\t%s: %s\n';
+ var self = this;
+ var str = '';
+
+ function handlersToString(arr) {
+ var s = '[' + arr.map(function (b) {
+ return (b.name || 'function');
+ }).join(', ') + ']';
+
+ return (s);
+ }
+
+ str += sprintf(LINE_FMT, 'Accepts', this.acceptable.join(', '));
+ str += sprintf(LINE_FMT, 'Name', this.name);
+ str += sprintf(LINE_FMT, 'Pre', handlersToString(this.before));
+ str += sprintf(LINE_FMT, 'Router', this.router.toString());
+ str += sprintf(LINE_FMT, 'Routes', '');
+ Object.keys(this.routes).forEach(function (k) {
+ var handlers = handlersToString(self.routes[k]);
+ str += sprintf(SUB_LINE_FMT, k, handlers);
+ });
+ str += sprintf(LINE_FMT, 'Secure', this.secure);
+ str += sprintf(LINE_FMT, 'Url', this.url);
+ str += sprintf(LINE_FMT, 'Version', this.versions.join());
+
+ return (str);
};
-
///--- Private methods
Server.prototype._handle = function _handle(req, res) {
- var self = this;
+ var self = this;
- function routeAndRun() {
- self._route(req, res, function (route, context) {
- req.context = req.params = context;
- req.route = route.spec;
+ function routeAndRun() {
+ self._route(req, res, function (route, context) {
+ req.context = req.params = context;
+ req.route = route.spec;
- var r = route ? route.name : null;
- var chain = self.routes[r];
+ var r = route ? route.name : null;
+ var chain = self.routes[r];
- self._run(req, res, route, chain, function done(e) {
- self.emit('after', req, res, route, e);
- });
- });
- }
+ self._run(req, res, route, chain, function done(e) {
+ self.emit('after', req, res, route, e);
+ });
+ });
+ }
- if (this.before.length > 0) {
- this._run(req, res, null, this.before, function (err) {
- if (!err) {
- routeAndRun();
- }
- });
- } else {
+ if (this.before.length > 0) {
+ this._run(req, res, null, this.before, function (err) {
+ if (!err) {
routeAndRun();
- }
+ }
+ });
+ } else {
+ routeAndRun();
+ }
};
Server.prototype._route = function _route(req, res, name, cb) {
- var self = this;
-
- if (typeof (name) === 'function') {
- cb = name;
- name = null;
+ var self = this;
+
+ if (typeof (name) === 'function') {
+ cb = name;
+ name = null;
+ } else {
+ this.router.get(name, req, function (err, route, ctx) {
+ if (err) {
+ emitRouteError(self, req, res, err);
+ } else {
+ cb(route, ctx);
+ }
+ });
+ }
+
+ 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 {
- this.router.get(name, req, function (err, route, ctx) {
- if (err) {
- emitRouteError(self, req, res, err);
- } else {
- cb(route, ctx);
- }
- });
+ cb(route, ctx);
}
-
- 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(route, ctx);
- }
- });
+ });
};
@@ -646,151 +642,153 @@ Server.prototype._route = function _route(req, res, name, cb) {
// 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;
- var i = -1;
- var id = dtrace.nextId();
- var log = this.log;
- var self = this;
- var t;
-
- 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);
- });
- }
+ var d;
+ var i = -1;
+ var id = dtrace.nextId();
+ var log = this.log;
+ var self = this;
+ var t;
+
+ 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);
}
- if (arg === false)
- done = true;
-
- // Fire DTrace done for the previous handler.
- if ((i + 1) > 0 && chain[i] && !chain[i]._skip) {
- var _name = chain[i].name || ('handler-' + i);
- req.timers.push({
- name: _name,
- time: process.hrtime(t)
- });
-
- dtrace._rstfy_probes['handler-done'].fire(function () {
- return ([
- self.name,
- route !== null ? route.name : 'pre',
- _name,
- id
- ]);
- });
- }
+ self._route(req, res, arg, function (r, ctx) {
+ req.context = req.params = ctx;
+ req.route = r.spec;
- // Run the next handler up
- if (!done && chain[++i]) {
- if (chain[i]._skip)
- return (next());
-
- t = process.hrtime();
- if (log.trace())
- log.trace('running %s', chain[i].name || '?');
-
- dtrace._rstfy_probes['handler-start'].fire(function () {
- return ([
- self.name,
- route !== null ? route.name : 'pre',
- chain[i].name || ('handler-' + i),
- id
- ]);
- });
-
- var n = once(next);
- n.ifError = ifError(n);
- return (chain[i].call(self, req, res, n));
- }
+ var _c = chain.slice(0, i + 1);
- dtrace._rstfy_probes['route-done'].fire(function () {
- return ([
- self.name,
- route !== null ? route.name : 'pre',
- id,
- res.statusCode || 200,
- res.headers()
- ]);
+ 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);
});
+ }
+ }
- if (route === null) {
- self.emit('preDone', req, res);
- } else {
- self.emit('done', req, res, route);
- }
+ if (arg === false)
+ done = true;
+
+ // Fire DTrace done for the previous handler.
+ if ((i + 1) > 0 && chain[i] && !chain[i]._skip) {
+ var _name = chain[i].name || ('handler-' + i);
+ req.timers.push({
+ name: _name,
+ time: process.hrtime(t)
+ });
- return (cb ? cb(arg) : true);
+ dtrace._rstfy_probes['handler-done'].fire(function () {
+ return ([
+ self.name,
+ route !== null ? route.name : 'pre',
+ _name,
+ id
+ ]);
+ });
}
- var n1 = once(next);
- n1.ifError = ifError(n1);
- dtrace._rstfy_probes['route-start'].fire(function () {
+ // Run the next handler up
+ if (!done && chain[++i]) {
+ if (chain[i]._skip)
+ return (next());
+
+ t = process.hrtime();
+ if (log.trace())
+ log.trace('running %s', chain[i].name || '?');
+
+ dtrace._rstfy_probes['handler-start'].fire(function () {
return ([
- self.name,
- route !== null ? route.name : 'pre',
- id,
- req.method,
- req.href(),
- req.headers
+ self.name,
+ route !== null ? route.name : 'pre',
+ chain[i].name || ('handler-' + i),
+ id
]);
- });
+ });
- req.timers = [];
- d = domain.create();
- d.add(req);
- d.add(res);
- d.on('error', function onError(err) {
- if (err._restify_next) {
- err._restify_next(err);
- } else {
- log.trace({err: err}, 'uncaughtException');
- self.emit('uncaughtException', req, res, route, err);
- }
+ var n = once(next);
+ n.ifError = ifError(n);
+ return (chain[i].call(self, req, res, n));
+ }
+
+ dtrace._rstfy_probes['route-done'].fire(function () {
+ return ([
+ self.name,
+ route !== null ? route.name : 'pre',
+ id,
+ res.statusCode || 200,
+ res.headers()
+ ]);
});
- d.run(n1);
+
+ if (route === null) {
+ self.emit('preDone', req, res);
+ } else {
+ self.emit('done', req, res, route);
+ }
+
+ return (cb ? cb(arg) : true);
+ }
+
+ var n1 = once(next);
+ n1.ifError = ifError(n1);
+
+ dtrace._rstfy_probes['route-start'].fire(function () {
+ return ([
+ self.name,
+ route !== null ? route.name : 'pre',
+ id,
+ req.method,
+ req.href(),
+ req.headers
+ ]);
+ });
+
+ req.timers = [];
+ d = domain.create();
+ d.add(req);
+ d.add(res);
+ d.on('error', function onError(err) {
+ if (err._restify_next) {
+ err._restify_next(err);
+ } else {
+ log.trace({err: err}, 'uncaughtException');
+ self.emit('uncaughtException', req, res, route, err);
+ }
+ });
+ d.run(n1);
};
Server.prototype._setupRequest = function _setupRequest(req, res) {
- req.log = res.log = this.log;
- req._time = res._time = Date.now();
-
- res.acceptable = this.acceptable;
- res.formatters = this.formatters;
- res.req = req;
- res.serverName = this.name;
- res.version = this.router.versions[this.router.versions.length - 1];
+ req.log = res.log = this.log;
+ req._time = res._time = Date.now();
+
+ res.acceptable = this.acceptable;
+ res.formatters = this.formatters;
+ res.req = req;
+ res.serverName = this.name;
+ res.version = this.router.versions[this.router.versions.length - 1];
};
// vim: set et ts=8 sts=8 sw=8:
diff --git a/lib/upgrade.js b/lib/upgrade.js
index 3fbe5fd96..d8c9db2cd 100644
--- a/lib/upgrade.js
+++ b/lib/upgrade.js
@@ -5,11 +5,11 @@ var util = require('util');
var assert = require('assert-plus');
function InvalidUpgradeStateError(msg) {
- if (Error.captureStackTrace)
- Error.captureStackTrace(this, InvalidUpgradeStateError);
+ if (Error.captureStackTrace)
+ Error.captureStackTrace(this, InvalidUpgradeStateError);
- this.message = msg;
- this.name = 'InvalidUpgradeStateError';
+ this.message = msg;
+ this.name = 'InvalidUpgradeStateError';
}
util.inherits(InvalidUpgradeStateError, Error);
@@ -38,144 +38,144 @@ util.inherits(InvalidUpgradeStateError, Error);
// other handler, this method will throw.
//
function createServerUpgradeResponse(req, socket, head) {
- return (new ServerUpgradeResponse(socket, head));
+ return (new ServerUpgradeResponse(socket, head));
}
function ServerUpgradeResponse(socket, head) {
- assert.object(socket, 'socket');
- assert.buffer(head, 'head');
+ assert.object(socket, 'socket');
+ assert.buffer(head, 'head');
- EventEmitter.call(this);
+ EventEmitter.call(this);
- this.sendDate = true;
- this.statusCode = 400;
+ this.sendDate = true;
+ this.statusCode = 400;
- this._upgrade = {
- socket: socket,
- head: head
- };
+ this._upgrade = {
+ socket: socket,
+ head: head
+ };
- this._headWritten = false;
- this._upgradeClaimed = false;
+ this._headWritten = false;
+ this._upgradeClaimed = false;
}
util.inherits(ServerUpgradeResponse, EventEmitter);
function notImplemented(method) {
- if (!method.throws) {
- return function () {
- return (method.returns);
- };
- } else {
- return function () {
- throw (new Error('Method ' + method.name + ' is not ' +
- 'implemented!'));
- };
- }
+ if (!method.throws) {
+ return function () {
+ return (method.returns);
+ };
+ } else {
+ return function () {
+ throw (new Error('Method ' + method.name + ' is not ' +
+ 'implemented!'));
+ };
+ }
}
var NOT_IMPLEMENTED = [
- { name: 'writeContinue', throws: true },
- { name: 'setHeader', throws: false, returns: null },
- { name: 'getHeader', throws: false, returns: null },
- { name: 'getHeaders', throws: false, returns: {} },
- { name: 'removeHeader', throws: false, returns: null },
- { name: 'addTrailer', throws: false, returns: null },
- { name: 'cache', throws: false, returns: 'public' },
- { name: 'format', throws: true },
- { name: 'set', throws: false, returns: null },
- { name: 'get', throws: false, returns: null },
- { name: 'headers', throws: false, returns: {} },
- { name: 'header', throws: false, returns: null },
- { name: 'json', throws: false, returns: null },
- { name: 'link', throws: false, returns: null }
+ { name: 'writeContinue', throws: true },
+ { name: 'setHeader', throws: false, returns: null },
+ { name: 'getHeader', throws: false, returns: null },
+ { name: 'getHeaders', throws: false, returns: {} },
+ { name: 'removeHeader', throws: false, returns: null },
+ { name: 'addTrailer', throws: false, returns: null },
+ { name: 'cache', throws: false, returns: 'public' },
+ { name: 'format', throws: true },
+ { name: 'set', throws: false, returns: null },
+ { name: 'get', throws: false, returns: null },
+ { name: 'headers', throws: false, returns: {} },
+ { name: 'header', throws: false, returns: null },
+ { name: 'json', throws: false, returns: null },
+ { name: 'link', throws: false, returns: null }
];
NOT_IMPLEMENTED.forEach(function (method) {
- ServerUpgradeResponse.prototype[method.name] = notImplemented(method);
+ ServerUpgradeResponse.prototype[method.name] = notImplemented(method);
});
-ServerUpgradeResponse.prototype._writeHeadImpl = function _writeHeadImpl(
-statusCode, reason) {
+ServerUpgradeResponse.prototype._writeHeadImpl =
+ function _writeHeadImpl(statusCode, reason) {
if (this._headWritten)
- return;
+ return;
this._headWritten = true;
if (this._upgradeClaimed)
- throw new InvalidUpgradeStateError('Upgrade already claimed!');
+ throw new InvalidUpgradeStateError('Upgrade already claimed!');
var head = [
- 'HTTP/1.1 ' + statusCode + ' ' + reason,
- 'Connection: close'
+ 'HTTP/1.1 ' + statusCode + ' ' + reason,
+ 'Connection: close'
];
if (this.sendDate)
- head.push('Date: ' + new Date().toUTCString());
+ head.push('Date: ' + new Date().toUTCString());
this._upgrade.socket.write(head.join('\r\n') + '\r\n');
-};
+ };
ServerUpgradeResponse.prototype.status = function status(code) {
- assert.number(code, 'code');
- this.statusCode = code;
- return (code);
+ assert.number(code, 'code');
+ this.statusCode = code;
+ return (code);
};
ServerUpgradeResponse.prototype.send = function send(code, body) {
- if (typeof (code) === 'number')
- this.statusCode = code;
- else
- body = code;
-
- if (typeof (body) === 'object') {
- if (typeof (body.statusCode) === 'number')
- this.statusCode = body.statusCode;
- if (typeof (body.message) === 'string')
- this.statusReason = body.message;
- }
-
- return (this.end());
+ if (typeof (code) === 'number')
+ this.statusCode = code;
+ else
+ body = code;
+
+ if (typeof (body) === 'object') {
+ if (typeof (body.statusCode) === 'number')
+ this.statusCode = body.statusCode;
+ if (typeof (body.message) === 'string')
+ this.statusReason = body.message;
+ }
+
+ return (this.end());
};
ServerUpgradeResponse.prototype.end = function end() {
- this._writeHeadImpl(this.statusCode, 'Connection Not Upgraded');
- this._upgrade.socket.end('\r\n');
- return (true);
+ this._writeHeadImpl(this.statusCode, 'Connection Not Upgraded');
+ this._upgrade.socket.end('\r\n');
+ return (true);
};
ServerUpgradeResponse.prototype.write = function write() {
- this._writeHeadImpl(this.statusCode, 'Connection Not Upgraded');
- return (true);
+ this._writeHeadImpl(this.statusCode, 'Connection Not Upgraded');
+ return (true);
};
-ServerUpgradeResponse.prototype.writeHead = function writeHead(statusCode,
-reason) {
+ServerUpgradeResponse.prototype.writeHead =
+ function writeHead(statusCode, reason) {
assert.number(statusCode, 'statusCode');
assert.optionalString(reason, 'reason');
this.statusCode = statusCode;
if (!reason)
- reason = 'Connection Not Upgraded';
+ reason = 'Connection Not Upgraded';
if (this._headWritten)
- throw new Error('Head already written!');
+ throw new Error('Head already written!');
return (this._writeHeadImpl(statusCode, reason));
-};
+ };
ServerUpgradeResponse.prototype.claimUpgrade = function claimUpgrade() {
- if (this._upgradeClaimed)
- throw new InvalidUpgradeStateError('Upgrade already claimed!');
+ if (this._upgradeClaimed)
+ throw new InvalidUpgradeStateError('Upgrade already claimed!');
- if (this._headWritten)
- throw new InvalidUpgradeStateError('Upgrade already aborted!');
+ if (this._headWritten)
+ throw new InvalidUpgradeStateError('Upgrade already aborted!');
- this._upgradeClaimed = true;
+ this._upgradeClaimed = true;
- return (this._upgrade);
+ return (this._upgrade);
};
module.exports = {
- createResponse: createServerUpgradeResponse,
+ createResponse: createServerUpgradeResponse,
- InvalidUpgradeStateError: InvalidUpgradeStateError
+ InvalidUpgradeStateError: InvalidUpgradeStateError
};
// vim: set et ts=8 sts=8 sw=8:
diff --git a/lib/utils.js b/lib/utils.js
index 6349caf68..ce9e0b1b0 100644
--- a/lib/utils.js
+++ b/lib/utils.js
@@ -3,7 +3,6 @@
var assert = require('assert-plus');
-
/**
* Cleans up sloppy URL paths, like /foo////bar/// to /foo/bar.
*
@@ -11,39 +10,37 @@ var assert = require('assert-plus');
* @return {String} Cleaned up form of path.
*/
function sanitizePath(path) {
- assert.ok(path);
+ assert.ok(path);
- // Be nice like apache and strip out any //my//foo//bar///blah
- path = path.replace(/\/\/+/g, '/');
+ // Be nice like apache and strip out any //my//foo//bar///blah
+ path = path.replace(/\/\/+/g, '/');
- // Kill a trailing '/'
- if (path.lastIndexOf('/') === (path.length - 1) && path.length > 1)
- path = path.substr(0, path.length - 1);
+ // Kill a trailing '/'
+ if (path.lastIndexOf('/') === (path.length - 1) && path.length > 1)
+ path = path.substr(0, path.length - 1);
- return (path);
+ return (path);
}
-
/**
* 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);
+ if (!obj) {
+ return (obj);
+ }
+ var copy = {};
+ Object.keys(obj).forEach(function (k) {
+ copy[k] = obj[k];
+ });
+ return (copy);
}
-
///--- Exports
module.exports = {
- sanitizePath: sanitizePath,
- shallowCopy: shallowCopy
+ sanitizePath: sanitizePath,
+ shallowCopy: shallowCopy
};
diff --git a/test/client.test.js b/test/client.test.js
index 512672055..4f815ae97 100644
--- a/test/client.test.js
+++ b/test/client.test.js
@@ -7,11 +7,10 @@ var uuid = require('node-uuid');
var restify = require('../lib');
if (require.cache[__dirname + '/lib/helper.js'])
- delete require.cache[__dirname + '/lib/helper.js'];
+ delete require.cache[__dirname + '/lib/helper.js'];
var helper = require('./lib/helper.js');
-
///--- Globals
var after = helper.after;
@@ -25,695 +24,693 @@ var RAW_CLIENT;
var SERVER;
-
///--- Helpers
function sendJson(req, res, next) {
- res.send({hello: req.params.hello || req.params.name || null});
- next();
+ res.send({hello: req.params.hello || req.params.name || null});
+ next();
}
function sendText(req, res, next) {
- res.send('hello ' + (req.params.hello || req.params.name || ''));
- next();
+ res.send('hello ' + (req.params.hello || req.params.name || ''));
+ next();
}
function sendSignature(req, res, next) {
- res.header('content-type', 'text/plain');
- var hdr = req.header('Awesome-Signature');
- if (!hdr) {
- res.send('request NOT signed');
- } else {
- res.send('ok: ' + hdr);
- }
+ res.header('content-type', 'text/plain');
+ var hdr = req.header('Awesome-Signature');
+ if (!hdr) {
+ res.send('request NOT signed');
+ } else {
+ res.send('ok: ' + hdr);
+ }
}
function sendWhitespace(req, res, next) {
- var body = ' ';
- if (req.params.flavor === 'spaces') {
- body = ' ';
- } else if (req.params.flavor === 'tabs') {
- body = ' \t\t ';
- }
-
- // override contentType as otherwise the string is json-ified to
- // include quotes. Don't want that for this test.
- res.header('content-type', 'text/plain');
- res.send(body);
- next();
+ var body = ' ';
+ if (req.params.flavor === 'spaces') {
+ body = ' ';
+ } else if (req.params.flavor === 'tabs') {
+ body = ' \t\t ';
+ }
+
+ // override contentType as otherwise the string is json-ified to
+ // include quotes. Don't want that for this test.
+ res.header('content-type', 'text/plain');
+ res.send(body);
+ next();
}
-
///--- Tests
before(function (callback) {
- try {
- SERVER = restify.createServer({
- dtrace: helper.dtrace,
- log: helper.getLog('server')
- });
-
- SERVER.use(restify.acceptParser(['json', 'text/plain']));
- SERVER.use(restify.dateParser());
- SERVER.use(restify.authorizationParser());
- SERVER.use(restify.queryParser());
- SERVER.use(restify.bodyParser());
-
- SERVER.get('/signed', sendSignature);
- SERVER.get('/whitespace/:flavor', sendWhitespace);
-
- SERVER.get('/json/boom', function (req, res, next) {
- res.set('content-type', 'text/html');
- res.send(200, '');
- next();
- });
- SERVER.del('/contentLengthAllowed', function (req, res, next) {
- if (req.header('content-length')) {
- res.send(200, 'Allowed');
- } else {
- res.send(200, 'Not allowed');
- }
- next();
- });
-
- SERVER.get('/json/:name', sendJson);
- SERVER.head('/json/:name', sendJson);
- SERVER.put('/json/:name', sendJson);
- SERVER.post('/json/:name', sendJson);
- SERVER.patch('/json/:name', sendJson);
-
- SERVER.del('/str/:name', sendText);
- SERVER.get('/str/:name', sendText);
- SERVER.head('/str/:name', sendText);
- SERVER.put('/str/:name', sendText);
- SERVER.post('/str/:name', sendText);
- SERVER.patch('/str/:name', sendText);
-
- SERVER.listen(PORT, '127.0.0.1', function () {
- PORT = SERVER.address().port;
-
- JSON_CLIENT = restify.createJsonClient({
- url: 'http://127.0.0.1:' + PORT,
- dtrace: helper.dtrace,
- retry: false
- });
- STR_CLIENT = restify.createStringClient({
- url: 'http://127.0.0.1:' + PORT,
- dtrace: helper.dtrace,
- retry: false
- });
- RAW_CLIENT = restify.createClient({
- url: 'http://127.0.0.1:' + PORT,
- dtrace: helper.dtrace,
- retry: false,
- headers: {
- accept: 'text/plain'
- }
- });
- process.nextTick(callback);
- });
- } catch (e) {
- console.error(e.stack);
- process.exit(1);
- }
+ try {
+ SERVER = restify.createServer({
+ dtrace: helper.dtrace,
+ log: helper.getLog('server')
+ });
+
+ SERVER.use(restify.acceptParser(['json', 'text/plain']));
+ SERVER.use(restify.dateParser());
+ SERVER.use(restify.authorizationParser());
+ SERVER.use(restify.queryParser());
+ SERVER.use(restify.bodyParser());
+
+ SERVER.get('/signed', sendSignature);
+ SERVER.get('/whitespace/:flavor', sendWhitespace);
+
+ SERVER.get('/json/boom', function (req, res, next) {
+ res.set('content-type', 'text/html');
+ res.send(200, '