初投稿です。
今までExpressのエラー処理は以下のように書いてました。
(例:必須のリクエストパラメータのチェック)
const { username } = req.body;
if (!username) {
const err = new Error('username is required');
console.log(err);
res.status(400).send({ error: err });
}
パラメータの個数分、同様の処理を書いていて冗長だなぁと感じていました。
エラー処理ミドルウェア関数
Express でのエラー処理にエラーハンドリングの方法が書いてありました。
err, req, res, nextの4つの引数を持つミドルウェア関数を定義して、全てのミドルウェアの最後で呼び出します。
function logErrors(err, req, res, next) {
console.error(err.stack);
next(err);
}
function errorHandler(err, req, res, next) {
res.status(500);
res.send({ error: err });
}
app.use(logErrors);
app.use(errorHandler);
logErrors関数はエラーのログを出力します。
errorHandler関数はクライアントにエラーレスポンスを返します。
そして、エラーを投げる側ではnext関数にエラーオブジェクトを渡します。
const { username } = req.body;
if (!username) {
const err = new Error('username is required');
next(err);
}
これでエラーログ出力とエラーレスポンス返却をエラー処理ミドルウェアに任せることができました。
しかし、今のままではerrorHandlerで常にステータスコードが500のエラーレスポンスが返されてしまいます。なので、ちょっと変えます。
function errorHandler(err, req, res, next) {
res.status(err.statusCode || 500);
res.send({ error: err });
}
const { username } = req.body;
if (!username) {
const err = new Error('username is required');
err.statusCode = 400;
next(err);
}
これでステータスコードが400のエラーレスポンスを返せるようになります。
ステータスコードの設定
毎回、エラーオブジェクトにステータスコードを設定するのは面倒臭いです。
CustomErrorクラスかboomを導入すると、ステータスコードの設定が簡潔になります。
CustomErrorクラス
class CustomError extends Error {
constructor(message, statusCode) {
super(message);
this.statusCode = statusCode;
}
}
if (!username) next(new CustomError('username is required', 400));
ワンライナーで書けました。
boom
hapijs/boom
boomはHTTPのエラーオブジェクト返すモジュール群です。
Boom.badRequest('invalid query')
上のコードは以下のオブジェクトを返します。
{
"statusCode": 400,
"error": "Bad Request",
"message": "invalid query"
}
コードを見ればどんなエラーかわかるのでいいですね。
badRequestの他にもunauthorizedやnotFoundなど基本的なエラーが揃っています。
boomを使って書くと、こうなります。
if (!username) next(Boom.badRequest('username is required'));
まとめ
- エラーミドルウェア関数を用いることで、エラーログ出力とエラーレスポンスの返却処理を共通化することができました
- CustomErrorクラス(またはboom)を用いることで、ステータスコードの設定が簡単になりました