できない.dev

Next.js の Route Handler で CORS エラーが解消できない

App Router の Route Handler は自動 CORS を持たないため、`Access-Control-Allow-Origin` を自分で付与し、プリフライト用の `OPTIONS` ハンドラも同ファイルに実装する必要がある。

#nextjs#cors#route-handler#api#headers

公開:

要約

Next.js の Route Handler は Express のような自動 CORS が無いため、Response ヘッダーを自分で設定し、OPTIONS ハンドラを実装する ことで対応する。
クッキー連携時はオリジンを具体名で指定し Allow-Credentials: true を返す。

よくある原因

  1. ヘッダー未設定: ブラウザコンソールに「No 'Access-Control-Allow-Origin' header is present」エラー
  2. OPTIONS ハンドラ無し: プリフライトリクエストが 405 Method Not Allowed になる
  3. * と credentials の併用: ブラウザ仕様で禁止されている組み合わせ
  4. 設定の重複: middleware と Route Handler の両方でヘッダーを出して値が上書きされる

解決策

1. 個別 Route Handler でヘッダーを返す

公式の Route Handlers ドキュメントroute.js ファイル規約 に沿って、app/api/foo/route.ts を実装する。

const ALLOW_ORIGIN = "https://app.example.com";
 
export async function GET() {
  return new Response(JSON.stringify({ ok: true }), {
    headers: {
      "Content-Type": "application/json",
      "Access-Control-Allow-Origin": ALLOW_ORIGIN,
    },
  });
}
 
export async function OPTIONS() {
  return new Response(null, {
    status: 204,
    headers: {
      "Access-Control-Allow-Origin": ALLOW_ORIGIN,
      "Access-Control-Allow-Methods": "GET, POST, OPTIONS",
      "Access-Control-Allow-Headers": "Content-Type, Authorization",
    },
  });
}

2. 全 API へ middleware で一括付与する

オリジンを動的に判定したい場合は middleware.tsNextResponse のヘッダーを書き換える。
Route Handler 側との二重設定を避け、責任箇所を 1 つに絞ること。

3. クッキー連携時の注意

fetch(url, { credentials: "include" }) を使うクライアントには、Access-Control-Allow-Origin: * ではなく具体的オリジン、加えて Access-Control-Allow-Credentials: true を返す。* と credentials の併用はブラウザ側で拒否される。

この記事は役立ちましたか?