#107 エラーの形式がバラバラ
中段 / 目安 30分
Issue #107 エラーの形式がバラバラ
報告者: 凛(テックリード)
「404 は {"error":...}、500 は素のスタックトレース、検証エラーは配列……クライアント担当が泣いています。エラー応答の形式を1つに統一してください」
受け取る側の身になると、この苦情は当然です。エラーのたびに形が違えば、形ごとに読み分けるコードを書くことになります。しかも新しいエラーが増えるたびに、その対応も増えます。
統一するには、エラーを返す場所を1か所に集めます。各ルートは「失敗した」とだけ伝え、どう返すかは1か所が決める形です。
伝え方が next(err) です。
JavaScript
const err = new Error("商品が見つかりません");
err.status = 404;
return next(err);引数なしの next() が「次へ進む」なのに対し、next(err) は「失敗したので受け皿へ」という意味になります。ステータスコードはエラー自身に持たせておきます。
受け皿がエラー用のミドルウェアです。
JavaScript
app.use((err, req, res, next) => {
res.status(err.status || 500).json({ error: err.message });
});引数が4つあるのが目印です。3つだと普通のミドルウェアとして扱われ、エラーを受け止められません。省略もできません。
置く場所はすべてのルートより後です。リクエストは上から順に通るので、途中に置くとその下のエラーを拾えません。
err.status が無いときは 500 に落とします。想定していなかった失敗は、こちらの都合の失敗だからです。
完成条件
エラー応答を {"error":"理由"} の形に統一してください。
各ルートは next(err) で投げ、共通のハンドラが受け止めます。ステータスは err.status を使い、無ければ 500 にします。
エラーの中身は外に出しません。 500 のときは決まった文言を返してください。
要件
- すべてのルートより後に、引数4つのエラー用ミドルウェアを置く
err.statusがあればそれを、無ければ 500 を使う- 500 のときは
{"error":"サーバーで問題が起きました"}を返し、エラーの中身は外に出さない
入出力例
request("GET", "/items/1") → "200 {"id":1,"name":"レザースニーカー","price":4800}"
request("GET", "/items/999") → "404 {"error":"商品が見つかりません"}"
request("GET", "/boom") → "500 {"error":"サーバーで問題が起きました"}"ヒント
前のヒントを開くと次が開きます。開かずに解けると未開封クリアです
ヒント 2ヒント 1 を開くと読めます
ヒント 3ヒント 2 を開くと読めます
編集 ゆめさく編集部