Boomによるエラーハンドリング NodeJS


hapi/Boom

インストール
npm install @hapi/boom

実装

index.js
require('dotenv').config()
const express = require('express')
const errorHandler = require('./helpers/error') // ←こちらを指定

// 省略
// 

// エラー処理ミドルウェア
app.use(errorHandler)

const listener = app.listen(3000, function(){
  logger.info('Listening on port ' + listener.address().port)
})

ミドルウェア処理

helpers/error.js
const boom = require('boom')
const config = require('../config/default')
const log4js = require("log4js");
const logger = log4js.getLogger("default");

const errorHandler = (err, req, res, next) => {
    if (res.headersSent) return next(err)
    if (!err.statusCode) err = boom.boomify(err)

    if (err.hogehoge)  { // 各分岐処理
      // error
      }
      return
    }
    if (isMongodbErr(err)) { // mongoとかのエラー
      logger.warn(req.userId, err.message)
      res.status(500).json({message:err.message})
      return
    }

    if (err.isServer) {
      logger.error(req.userId, err)
      res.status(500).json({message: '予期せぬエラーとか'})
      return
      // boom通した500番台のエラーはisServerでtrueが返る
    }
    err.isBoom ? logger.warn(req.userId, err.output.payload) : logger.error(req.userId, err)
    return err.isBoom
      ? res.status(err.output.statusCode).json(err.output.payload)
      : res.status(err.statusCode).json(err)
  }

  const isMongodbErr = (err) => {
    return err.name === 'MongoServerSelectionError'
  }

module.exports = errorHandler

ハンドル方法

hoge.js

// モンゴDBからデータを取得する処理
router.get('/endpoint', async function (req, res, next) {
  try {
  // if (await cheackEndpoint(req.params.endpoint)) return next(Boom.badRequest('メッセージ')) //みたいにパラメーターチェックも可
    const obj = { Name: { $eq: req.params.hogehoge } }
    const result = await db.find(obj, 'ccc')
    if (result.length === 0) return next(Boom.notFound('data not found')) //0件の場合エラーとしたい時など
    res.json(result)
  } catch (error) {
    next(error) // try Catchに引っかかるとミドルウェアへnextされる
  }
})

クライアントには以下が返る。

{
    "statusCode": 400,
    "error": "Bad Request",
    "message": "invalid query"
}

BoomではbadRequestやnotFoundなどデフォルトのテンプレがあるので、それをうまく使おう。 クライアントへ送るメッセージはこちらでも設定できるので便利