くらげになりたい。

くらげのようにふわふわ生きたい日曜プログラマなブログ。趣味の備忘録です。

NuxtでもNitroErrorHandlerを使いたい(ワークアラウンド)

unjs/nitroだと、自作のエラーハンドラーを設定できるので、
ErrorからAPIレスポンスに変換したりもできる

// ~/error.ts
import { EventHandlerRequest, H3Error, H3Event } from "h3";

export default defineNitroErrorHandler((error: H3Error, event: H3Event<EventHandlerRequest>) => {

  // H3Errorを、いい感じに、共通ErrorResponseに変換
  const res = { message: `${error}`, /* ... */};
  
  // ステータスコードを設定(例)
  setResponseStatus(event, error.statusCode);
  
  // 共通ErrorResponseをレスポンスに設定して返却
  return send(event, JSON.stringify(res));
});
// nitro.config.ts
export default defineNitroConfig({
  errorHandler: "~/error",
});

server/を使ったSSRなNuxtでも、API部分はこれを使いたいなと思い、
いろいろ調べたときの備忘録(*´ω`*)

そのままだとダメ

Nuxtでもnitroの設定ができるので、そのまま試してみたけどダメだった。。。
すべてのErrorがハンドリングされてしまい、error.vueが表示されない。。。

// nuxt.config.ts
// https://nuxt.com/docs/api/configuration/nuxt-config
export default defineNuxtConfig({
  nitro: {
    errorHandler: "~~/server/error.ts",
  }
});

Nuxt側でもnitro.errorHandlerを利用しているようで、
Nuxt側が設定したNitroErrorHandlerを上書きしてしまい、
すべてがjson形式になってしまうよう。。。

やったこと

まさになIssueがあったので、これを参考にワークアラウンド対応した

すべてのAPIserver/routes/api/*になる前提で、
パスが/api/以外は、NuxtのNitroErrorHandlerを使う形

import { EventHandlerRequest, H3Error, H3Event } from "h3";
import nuxtErrorHandler from '~~/node_modules/nuxt/dist/core/runtime/nitro/error.js';

export default defineNitroErrorHandler((error: H3Error, event: H3Event<EventHandlerRequest>) => {
  // /api配下以外はNuxtのerrorHandlerを使う
  if (!event.node.req.originalUrl?.startsWith("/api")) {
    return nuxtErrorHandler(error, event);
  }
  
  // 以下は同じ
  // H3Errorを、いい感じに、共通ErrorResponseに変換
  const res = { message: `${error}`, /* ... */};
  setResponseStatus(event, error.statusCode);
  return send(event, JSON.stringify(res));
});

残念ながら、exportはされていないので、
node_modules/nuxt/distからimportしている

v3.15.2だと、ここにあるerrorhandlerを利用している


以上! これで、Nuxtのserver/ディレクトリでも、defineNitroErrorHandlerを利用できて、
エラーレスポンスの共通化が簡単になった(*´ω`*)