Restify — Content Negotiation and Errors
By: John Au-Yeung
Tags: JavaScript, Software Development, Programming, Technology, Web Development

Photo by Will Francis on Unsplash

Restify is a simple Node back end framework.

In this article, we’ll look at how to handle content negotiation and errors with Restify.

Content Negotiation And Formatting

Restify will determine the content-type to respond with by from highest to lowest priority.

It’ll use the res.contentType if it’s present.

The Content-Type response header if it’s set.

application/json will be returned if the body is an object and not a Buffer instance.

Otherwise, it negotiates the content-type by matching the available formatters with the requests’s accept header.

If a content-type can’t be determined then Restify will respond with an error.

If a content-type can be negotiated, then it determines what formatter to use to format the response’s content.

If there’s no formatter matching the content-type can be found, then Restify will override the response’s content-type to 'application/octet-stream' and then error out if no formnatter if found for that content-type .

The default behavior can be changed by passing the strictFormatters: false property when creating the Restify server instance.

If no formatter is found for the content-type , then the response is flushed without applying any formatter.

Restify ships with application/json , text/plain , and application/octet-stream formatters.

We can add additional formatters to Restify by passing a hash of content type and parser when we create the server.

For example, we can write:

var restify = require('restify');

const util = require('util'); function respond(req, res, next) {

res.send('hello');

next();

} var server = restify.createServer({

formatters: {

['application/foo'](req, res, body) {

if (body instanceof Error)

return body.stack; if (Buffer.isBuffer(body))

return body.toString('base64'); return util.inspect(body);

}

}

}); server.get('/hello', respond);

server.head('/hello', respond); server.listen(8080);

We have the formatters object for the application/foo content type.

Then we return a base64 string if the body is a buffer.

We can also add a q-value to our formatter definition to change the priority of the formatter:

var restify = require('restify');

const util = require('util');

function respond(req, res, next) {

res.send('hello');

next();

}

var server = restify.createServer({

formatters: {

['application/foo q=0.9'](req, res, body) {

if (body instanceof Error)

return body.stack;

if (Buffer.isBuffer(body))

return body.toString('base64');

return util.inspect(body);

}

}

});

server.get('/hello', respond);

server.head('/hello', respond);

server.listen(8080);

Restify ships with default formatters.

It can be overridden when passing formatter options with createServer :

var restify = require('restify');



function respond(req, res, next) {

const body = 'hello world';

res.writeHead(200, {

'Content-Length': Buffer.byteLength(body),

'Content-Type': 'text/plain'

});

res.write(body);

res.end();

}

var server = restify.createServer();

server.get('/hello', respond);

server.head('/hello', respond);

server.listen(8080);

We called the writeHead method with an object with the content-type options we want to return in the header.

Error Handling

We can handle error conditions by passing an error object with the next function.

For example, we can write:

var restify = require('restify');

var errors = require('restify-errors'); var server = restify.createServer(); server.get('/hello/:foo', function(req, res, next) {

var err = new errors.NotFoundError('not found');

return next(err);

}); server.on('NotFound', function (req, res, err, cb) {

return cb();

}); server.listen(8080);

We have the NotFound handler to do logging or collect data.

The NotFoundError constructor is in the restify-errors module.

We shouldn’t call res.send in the NotFound handler since it’s in a different error context.

Conclusion

We can format the our data and do content negotiating the same way.

Also, we create error objects with the restify-errors module.

Enjoyed this article? If so, get more similar content by subscribing to Decoded, our YouTube channel!