Restify
Created: 2016-03-16 09:01:10 -0700 Modified: 2018-08-01 15:04:31 -0700
Description
Section titled DescriptionThis is a REST server and/or REST client that is lighter weight than using Express.
body vs. query vs. params
Section titled body vs. query vs. paramsIf you have a function like this:
someFunction(req, res, next) {}
“req.query” will be set if you did a “GET” command and have question-mark parameters right in the URL like “/users?id=1&name=Adam”
“req.params” will be set if you specified the route like this: ‘/users/:userId/:name’
“req.body” will be set if the client sent them in the body of the request as opposed to the headers or URL.
Throttling
Section titled ThrottlingI throttle using the plugin that they provide. It has two interesting options: “ip” and “xff”. If “ip” is specified, the IP address of the connection will be used for throttling, which is undesirable when you’re behind a load balancer since all requests will have the IP address of the load balancer and will thus get rate-limited very quickly. To get around that, you can use “xff”, which will take the “x-forwarded-for” header (code reference). This won’t exist on localhost though (actually, it won’t exist in production either unless you’re definitely behind a load balancer), so you’ll get undefined, which Restify treats as “always allow and never throttle” (code reference).
Troubleshooting
Section titled TroubleshootingI ran into a problem on 3/16/2016 where I was throwing an exception from inside a route, e.g.:
// this.server.listen() code goes here
this.server.get(‘/ping’, (req, res, next) => {throw new Error(‘hello world’)});
When I would GET the “/ping” route, the REST client would get this response:
{
“code”: “InternalError”,
“message”: “hello world”
}
This was incredibly difficult for me to track down because I expected the REST server to display the error somewhere before passing it off directly to the client (possibly leaking implementation details in the process).
I figured out what was going wrong. Restify has an ‘uncaughtException’ handler by default which outputs a 500 error to the client with the error message (e.g. “hello world”). This is what it looks like (taken from their source on 3/15/16):
server.on(‘uncaughtException’, function (req, res, route, e) {
if (this.listeners(‘uncaughtException’).length > 1 ||
res.headersSent) {
return (false);
}
res.send(new InternalError(e, e.message || ‘unexpected error’));
return (true);
});
As you can see above, if you install your own handler, it will essentially turn off their handler because they do a handler-length check. Here is a much saner handler:
this.server.on(‘uncaughtException’, function (req, res, route, err) {
console.error(‘Restify uncaughtException: ’ + err);
res.send(new InternalError(e, e.message || ‘unexpected error’));
return (true);
});
This is roughly the same as the default handler, but instead of blindly sending errors out, it also logs to the server. You would use a handler like this when you trust the client (e.g. for internal services).