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
    }));
  }
}