Menu
CoddyTech

統一されたエラー形式

CoddyのNode.jsジャーニー「REST API」セクションの一部。レッスン 12/25。

現在、API は 2 種類の形式でエラーに応答します。404 では文字列、400 では zod のオブジェクトです。クライアントはそれぞれに対応する必要があります。すべてのエラーで形式を統一しましょう。

{ "error": { "code": "not_found", "message": "Invoice not found" } }

{ "error": { "code": "invalid_body", "message": "Too small: ...",
             "fields": { "amount": ["Too small: expected number to be >0"] } } }

code はプログラム向けです。変わることがないため、クライアントはその値を比較できます。message は人向けで、文言が変わる場合があります。fields は、フォームのどの入力欄に印を付けるかを示します。形式を 1 つの関数にまとめ、すべてのルートから呼び出せば、ルートごとに形式がずれることはありません。

sendError(res, 404, 'not_found', 'Invoice not found');
challenge icon

チャレンジ

簡単

あなたの API は、エラーを2種類の形式で送るようになりました。404では単なる文字列、400ではzodのオブジェクトです。クライアントがすべてのエラーを同じ方法で読み取れるように、すべてのエラーを同じ形式にしましょう。これからはすべてのエラーが次のようになり、表示する項目がある場合にだけfieldsが追加されます。

{ "error": { "code": "not_found", "message": "Task not found" } }
  1. errors.jsで、sendError(res, status, code, message, fields)を完成させましょう。指定されたステータスと上記の形式で応答します。引数が渡された場合にだけ、内側のオブジェクトにfieldsを追加してください。その下のsendInvalidはすでに記述されており、あなたの関数を呼び出します。
  2. routes/tasks.jsで、両方のヘルパーをインポートしましょう。
    • 1つのタスクに対する4つの404応答(GET、PATCH、PUT、DELETE)をsendErrorに置き換え、コードにはnot_found、メッセージにはTask not foundを使います。
    • 不正な本文に対する3つの400応答(POST、PATCH、PUT)をsendInvalid(res, result.error)に置き換えます。

    不正な本文は次のようになります(メッセージはzodが書き込みます)。

    {
      "error": {
        "code": "invalid_body",
        "message": "Invalid input: expected string, received number",
        "fields": { "title": ["Invalid input: expected string, received number"] }
      }
    }
  3. server.jsで、sendErrorをインポートし、末尾にあるエラーハンドラーで使います。
    • 有効なJSONではない本文の場合、ステータスは400、コードはinvalid_json、メッセージはThe body is not valid JSONになります。
    • それ以外の場合、ステータスは500、コードはserver_error、メッセージはSomething went wrongになります。

試してみましょう:DELETE /api/tasks/99は、{ "error": { "code": "not_found", "message": "Task not found" } }とともに404を返し、fieldsは含まれません。{ "title": 123 }を/api/tasksにPOSTすると、上記のinvalid_bodyエラーとともに400が返ります。リクエストバーは不正なJSONの送信を拒否するため、チェックではinvalid_jsonのケースがテストされます。

自分で試してみよう

import { z } from 'zod';

// すべてのエラーを同じ形式で送信する:
// { "error": { "code": "not_found", "message": "Task not found" } }
// "fields" は指定された場合にのみ追加する。
export const sendError = (res, status, code, message, fields) => {
    // ここでレスポンスを送信する
};

// zod エラーを 400 として送信する: 最初の問題をメッセージとし、各フィールドの
// 問題を fields に格納する。
export const sendInvalid = (res, zodError) =>
    sendError(res, 400, 'invalid_body', zodError.issues[0].message, z.flattenError(zodError).fieldErrors);
quiz icon腕試し

このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。

REST APIのすべてのレッスン

自分で練習してみよう: Expressプレイグラウンド