Categories
Restify

Restify — Content Negotiation and Errors

Spread the love

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.

By John Au-Yeung

Web developer specializing in React, Vue, and front end development.

Leave a Reply

Your email address will not be published. Required fields are marked *