Skip to main content

Problem Details for HTTP APIs

HTTP status codes are sometimes not sufficient to convey enough information about an error to be helpful to developers. Problem Details object can carry fine-grained details of the problem to be used by API clients.

What is Problem Details?

Official introduction of Problem Details can be found on RFC7807. But I would probably recommend this well-explained blog post from Nate Totten The Power of Problem Details for HTTP APIs

Refactoring my Express codes to include Problem Details

Create a ProblemDetails class.

problemDetails.js
/**
 * @typedef {Object} ErrorDetails
 * @property {string} type
 * @property {string} title
 * @property {number} status
 * @property {string} detail
 * @property {string|number|Array|Object} [additionalProperty]
 */

export default class ProblemDetails {
  /** @param {ErrorDetails} options */
  constructor(options) {
    Object.assign(this, options);
  }
}

And then import this class to be used by userController.js.

./controllers/userController.js
import ProblemDetails from "../problemDetails.js";

export const userSignUp = async (req, res) => {
  const user = req.body;
  try {
    const create = await createUser(user);
    // ...
  } catch (err) {
    // 1. Connect Timeout Error
    if (err.cause?.code === 'UND_ERR_CONNECT_TIMEOUT') {
      res.status(500).json(new ProblemDetails({
        type: "about:blank",
        title: err.cause.code,
        status: 500,
        detail: err.cause.code,
      }));
      return;
    }

    // 2. Fetch Error
    res.status(err.status).json(new ProblemDetails({
      type: "about:blank",
      title: err.errors?.[0].message,
      status: err.status,
      detail: err.errors?.[0].message
    }));
  }
}