如何允许跨域访问NextJS API路由?解决/api/revalidate跨域问题
Next.js API端点配置CORS的解决方案
针对你遇到的跨域调用/api/revalidate端点被CORS策略拦截的问题,以下是不同路由模式下的具体配置方案:
一、Pages Router 模式(传统pages/api目录)
方法1:手动设置响应头
直接在API路由文件中添加CORS相关响应头,同时处理预检OPTIONS请求:
// pages/api/revalidate.js export default async function handler(req, res) { // 配置允许的可信域名(建议从环境变量读取) const allowedOrigin = process.env.NEXT_PUBLIC_ALLOWED_ORIGIN; // 验证请求来源并设置允许跨域的域名 if (req.headers.origin === allowedOrigin) { res.setHeader('Access-Control-Allow-Origin', allowedOrigin); } // 允许的请求方法 res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS'); // 允许的请求头 res.setHeader('Access-Control-Allow-Headers', 'Content-Type'); // 处理浏览器预检OPTIONS请求,直接返回200 if (req.method === 'OPTIONS') { return res.status(200).end(); } // 你的按需缓存重新验证逻辑 try { await res.revalidate('/path-to-revalidate'); return res.json({ revalidated: true }); } catch (err) { return res.status(500).send('Error revalidating'); } }
方法2:使用cors第三方包
先安装依赖:
npm install cors # 或 yarn add cors
然后在API路由中集成中间件:
// pages/api/revalidate.js import cors from 'cors'; // 初始化cors中间件,指定允许的域名 const corsMiddleware = cors({ origin: process.env.NEXT_PUBLIC_ALLOWED_ORIGIN, methods: ['GET', 'POST', 'OPTIONS'], }); export default async function handler(req, res) { // 用Promise包装cors中间件,适配Next.js API路由逻辑 await new Promise((resolve, reject) => { corsMiddleware(req, res, (result) => { if (result instanceof Error) { return reject(result); } return resolve(result); }); }); // 处理预检请求 if (req.method === 'OPTIONS') { return res.status(200).end(); } // 你的重新验证逻辑 try { await res.revalidate('/path-to-revalidate'); return res.json({ revalidated: true }); } catch (err) { return res.status(500).send('Error revalidating'); } }
二、App Router 模式(Next.js 13+ app/api目录)
在app/api/revalidate/route.js中分别处理OPTIONS预检请求和业务请求:
// app/api/revalidate/route.js import { NextResponse, revalidatePath } from 'next/server'; // 处理浏览器OPTIONS预检请求 export async function OPTIONS() { const allowedOrigin = process.env.NEXT_PUBLIC_ALLOWED_ORIGIN; return NextResponse.json({}, { headers: { 'Access-Control-Allow-Origin': allowedOrigin, 'Access-Control-Allow-Methods': 'GET, POST, OPTIONS', 'Access-Control-Allow-Headers': 'Content-Type', }, }); } // 处理业务请求(以POST为例) export async function POST(request) { const allowedOrigin = process.env.NEXT_PUBLIC_ALLOWED_ORIGIN; const origin = request.headers.get('origin'); // 验证请求来源合法性 if (origin !== allowedOrigin) { return NextResponse.json({ error: 'Not allowed' }, { status: 403 }); } // 设置响应CORS头 const response = NextResponse.json({ revalidated: true }); response.headers.set('Access-Control-Allow-Origin', allowedOrigin); // 执行缓存重新验证逻辑 try { await revalidatePath('/path-to-revalidate'); return response; } catch (err) { return NextResponse.json({ error: 'Error revalidating' }, { status: 500 }); } }
注意事项
- 生产环境禁止使用
*作为Access-Control-Allow-Origin的值,必须限制为可信域名,避免安全风险 - 建议将允许的域名配置在环境变量中,方便开发、测试、生产环境的不同配置
- 必须正确处理OPTIONS预检请求,否则浏览器会直接拦截后续的业务请求
内容的提问来源于stack exchange,提问作者cbdeveloper
相关产品推荐
相关产品推荐

