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 を返す。
よくある原因
- ヘッダー未設定: ブラウザコンソールに「No 'Access-Control-Allow-Origin' header is present」エラー
- OPTIONS ハンドラ無し: プリフライトリクエストが 405 Method Not Allowed になる
*と credentials の併用: ブラウザ仕様で禁止されている組み合わせ- 設定の重複: 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.ts で NextResponse のヘッダーを書き換える。
Route Handler 側との二重設定を避け、責任箇所を 1 つに絞ること。
3. クッキー連携時の注意
fetch(url, { credentials: "include" }) を使うクライアントには、Access-Control-Allow-Origin: * ではなく具体的オリジン、加えて Access-Control-Allow-Credentials: true を返す。* と credentials の併用はブラウザ側で拒否される。