Comparing version 1.1.1 to 1.2.0
# restify Changelog | ||
## 1.2.1 (not yet released) | ||
## 1.2.0 | ||
- Don't rely on instanceof checks for Errors in response. | ||
- Change route.run log level from trace to debug on next(err). | ||
- Add `res.link` API (wrap up sending a Link: response header). | ||
- GH-98 req.secure needs to return a boolean, not an object | ||
- GH-97 Malformed URI results in server crash | ||
- GH-94 leverage `qs` module for object notation in query string. | ||
## 1.1.1 | ||
@@ -4,0 +15,0 @@ |
@@ -44,3 +44,6 @@ // Copyright 2012 Mark Cavage, Inc. All rights reserved. | ||
this.name = 'RestError'; | ||
this.name = restCode; | ||
if (!/\w+Error$/.test(this.name)) | ||
this.name += 'Error'; | ||
this.code = restCode; | ||
@@ -47,0 +50,0 @@ this.__defineGetter__('restCode', function () { |
// Copyright 2012 Mark Cavage, Inc. All rights reserved. | ||
var querystring = require('querystring'); | ||
var qs = require('qs'); | ||
var url = require('url'); | ||
@@ -24,6 +24,6 @@ | ||
if (u.query) { | ||
var qs = querystring.parse(u.query); | ||
req._query = qs; | ||
var query = qs.parse(u.query); | ||
req._query = query; | ||
if (options.mapParams !== false) { | ||
Object.keys(qs).forEach(function (k) { | ||
Object.keys(query).forEach(function (k) { | ||
if (req.params[k] && !options.overrideParams) { | ||
@@ -34,3 +34,3 @@ req.log.warn('%s is on both the URL and the querystring', k); | ||
req.params[k] = qs[k]; | ||
req.params[k] = query[k]; | ||
}); | ||
@@ -37,0 +37,0 @@ } |
@@ -184,3 +184,3 @@ // Copyright 2012 Mark Cavage, Inc. All rights reserved. | ||
this.__defineGetter__('secure', function () { | ||
return self.req.connection.encrypted || false; | ||
return self.req.connection.encrypted ? true :false; | ||
}); | ||
@@ -187,0 +187,0 @@ |
@@ -111,3 +111,4 @@ // Copyright 2012 Mark Cavage, Inc. All rights reserved. | ||
if (body instanceof Error) { | ||
if (body instanceof RestError) { | ||
// snoop for RestError, but don't rely on instanceof | ||
if (body.restCode && body.body) { | ||
body = body.body; | ||
@@ -444,2 +445,11 @@ } else { | ||
Response.prototype.link = function link(l, rel) { | ||
if (typeof (l) !== 'string') | ||
throw new TypeError('link (String) required'); | ||
if (typeof (rel) !== 'string') | ||
throw new TypeError('rel (String) required'); | ||
return this.header('Link', '<%s>; rel="%s"', l, rel); | ||
}; | ||
Response.prototype.status = function status(code) { | ||
@@ -521,3 +531,3 @@ this.code = code; | ||
body = null; | ||
} else if (body && body instanceof HttpError) { | ||
} else if (body && body instanceof Error && body.statusCode) { | ||
this.statusCode = body.statusCode; | ||
@@ -585,3 +595,3 @@ } | ||
if (body instanceof Error) | ||
this.code = (body instanceof errors.HttpError) ? body.statusCode : 500; | ||
this.code = body.statusCode || 500; | ||
@@ -588,0 +598,0 @@ var data = this.formatters[this.contentType](this.req, this, body); |
@@ -335,3 +335,3 @@ // Copyright 2012 Mark Cavage, Inc. All rights reserved. | ||
if (err) { | ||
log.trace({err: err}, 'next(err=%s)', err.name); | ||
log.debug({err: err}, 'next(err=%s)', err.name); | ||
@@ -359,2 +359,3 @@ res.send(err); | ||
} catch (e) { | ||
log.debug({err: e}, 'uncaught exception(e=%s)', e.name); | ||
return self.emit('uncaughtException', req, res, self, e); | ||
@@ -361,0 +362,0 @@ } |
@@ -492,19 +492,26 @@ // Copyright 2012 Mark Cavage, Inc. All rights reserved. | ||
for (var i = 0; i < this.routes.length; i++) { | ||
var r = this.routes[i]; | ||
try { | ||
for (var i = 0; i < this.routes.length; i++) { | ||
var r = this.routes[i]; | ||
if ((params = r.matchesUrl(req))) { | ||
if (r.matchesMethod(req)) { | ||
if (r.matchesVersion(req)) { | ||
route = r; | ||
break; | ||
if ((params = r.matchesUrl(req))) { | ||
if (r.matchesMethod(req)) { | ||
if (r.matchesVersion(req)) { | ||
route = r; | ||
break; | ||
} else { | ||
if (r.version && versions.indexOf(r.version) === -1) | ||
versions.push(r.version); | ||
} | ||
} else { | ||
if (r.version && versions.indexOf(r.version) === -1) | ||
versions.push(r.version); | ||
if (methods.indexOf(r.method) === -1) | ||
methods.push(r.method); | ||
} | ||
} else { | ||
if (methods.indexOf(r.method) === -1) | ||
methods.push(r.method); | ||
} | ||
} | ||
} catch (e) { | ||
// It's possible this is really a 500, but for most purposes, the things | ||
// that will throw from the code above are decodeURIComponent | ||
res.send(new errors.BadRequestError(e.message)); | ||
return false; | ||
} | ||
@@ -511,0 +518,0 @@ |
@@ -20,3 +20,3 @@ { | ||
"description": "REST framework", | ||
"version": "1.1.1", | ||
"version": "1.2.0", | ||
"repository": { | ||
@@ -43,2 +43,3 @@ "type": "git", | ||
"node-uuid": "1.3.3", | ||
"qs": "0.4.2", | ||
"retry": "0.6.0", | ||
@@ -45,0 +46,0 @@ "semver": "1.0.13" |
@@ -128,2 +128,19 @@ // Copyright 2012 Mark Cavage, Inc. All rights reserved. | ||
test('query object', function (t) { | ||
SERVER.get('/query/:id', function (req, res, next) { | ||
t.equal(req.params.id, 'foo'); | ||
t.ok(req.params.name); | ||
t.equal(req.params.name.first, 'mark'); | ||
t.equal(req.query.name.last, 'cavage'); | ||
res.send(); | ||
return next(); | ||
}); | ||
request('/query/foo?name[first]=mark&name[last]=cavage', function (res) { | ||
t.equal(res.statusCode, 200); | ||
t.end(); | ||
}).end(); | ||
}); | ||
test('body url-encoded ok', function (t) { | ||
@@ -130,0 +147,0 @@ SERVER.post('/bodyurl/:id', plugins.bodyParser(), function (req, res, next) { |
@@ -806,2 +806,75 @@ // Copyright 2012 Mark Cavage, Inc. All rights reserved. | ||
test('GH-77 uncaughtException (with custom handler)', function (t) { | ||
var server = restify.createServer({ dtrace: DTRACE, log: LOGGER }); | ||
server.on('uncaughtException', function (req, res, route, err) { | ||
res.send(204); | ||
}); | ||
server.get('/', function (req, res, next) { | ||
throw new Error('Catch me!'); | ||
}); | ||
server.listen(PORT, function () { | ||
var opts = { | ||
hostname: 'localhost', | ||
port: PORT, | ||
path: '/', | ||
method: 'GET', | ||
agent: false, | ||
headers: { | ||
accept: 'text/plain' | ||
} | ||
}; | ||
http.request(opts, function (res) { | ||
t.equal(res.statusCode, 204); | ||
var body = ''; | ||
res.setEncoding('utf8'); | ||
res.on('data', function (chunk) { | ||
body += chunk; | ||
}); | ||
res.on('end', function () { | ||
t.equal(body, ''); | ||
server.close(function () { | ||
t.end(); | ||
}); | ||
}); | ||
}).end(); | ||
}); | ||
}); | ||
test('GH-97 malformed URI breaks server', function (t) { | ||
var server = restify.createServer({ dtrace: DTRACE, log: LOGGER }); | ||
server.get('/echo/:name', function (req, res, next) { | ||
res.send(200); | ||
return next(); | ||
}); | ||
server.listen(PORT, function () { | ||
var opts = { | ||
hostname: 'localhost', | ||
port: PORT, | ||
path: '/echo/mark%', | ||
method: 'GET', | ||
agent: false, | ||
headers: { | ||
accept: 'text/plain' | ||
} | ||
}; | ||
http.request(opts, function (res) { | ||
t.equal(res.statusCode, 400); | ||
var body = ''; | ||
res.setEncoding('utf8'); | ||
res.on('data', function (chunk) { | ||
body += chunk; | ||
}); | ||
res.on('end', function () { | ||
t.ok(body); | ||
server.close(function () { | ||
t.end(); | ||
}); | ||
}); | ||
}).end(); | ||
}); | ||
}); | ||
// | ||
@@ -808,0 +881,0 @@ // Disabled, as Heroku (travis) doesn't allow us to write to /tmp |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
192072
5325
11