0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Hono × hono-openapi で400エラーにカスタムレスポンスを設定する

Posted at

Honoとzod-openapi

Honoとzod-openapiを組み合わせることで、zodスキーマを使用した堅牢なAPIインターフェースを実装しつつ、openapiのドキュメントを生成することができます。

上記のテキトーな日本語があっているかはわかりませんが、エンドポイントの生成、リクエストのバリデーション、openapiのドキュメントをとても楽に実装できます。初めて聞いたぜ!って方はぜひ以下のリンクから覗いてみてください。

Hono zod-openapi

zod-openapiを使用した場合の400エラーハンドリング

さあ、ここからがこの記事の本題です。

zod-openapiを使用してルーティングを設定した場合、リクエストボディがzodスキーマを満たさずにバリデーションエラーとなると以下のようなbodyで400レスポンスを返してきます。

{
  "success": false,
  "error": {
    "issues": [
      {
        "validation": "email",
        "code": "invalid_string",
        "message": "Please enter a valid email address",
        "path": [
          "email"
        ]
      }
    ],
    "name": "ZodError"
  }
}

zodエラーの内容がまるッとissuesの配列として渡ってくる感じですね。
これでも良いのですが、それぞれ仕様によっては上のような構造ではなく、独自のエラーレスポンスで返したい場合は往々にしてあると思います。

その場合、以下のようにOpenAPIHonoクラスからインスタンスを生成するときにdefaultHookを設定すると、バリデーションエラー時のエラーレスポンスをカスタマイズできます。

const app = new OpenAPIHono({
  defaultHook: (result) => {
    if (!result.success) {
      throw handleError(result.error);
    }
  },
});

参考: https://github.com/honojs/middleware/tree/main/packages/zod-openapi#a-dry-approach-to-handling-validation-errors

handleErrorは独自に定義しているユーティリティですが、その中で私は以下のような処理を実装しました。

if (error instanceof ZodError) {
  const details = error.errors.map((err) => ({
    field: err.path.join("."),
    message: err.message,
  }));

  return new HTTPException(400, {
    message: JSON.stringify({
      error: {
        code: "VALIDATION_ERROR",
        message: "Invalid input data",
        details,
      },
    }),
  });
}

リクエストボディに対してzodスキーマでのパースに失敗した場合、result.errorからZodErrorが渡ってきます。それをごにょごにょして良い感じのカスタムレスポンスを400ステータスで返しています。

この実装をしてから、以下のようなJSONで返却されるようになりました。

"error": {
  "code": "VALIDATION_ERROR",
  "message": "Invalid input data",
  "details": [
    {
      "field": "email",
      "message": "Please enter a valid email address"
    }
  ]
}

結構わかりやすく、完結にカスタムできたのではないでしょうか!
以上、hono/zod-openapiを使用した場合のバリデーション時エラーレスポンスのカスタム方法の紹介でした!

ありがとうございました!

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?