React调用react-email API遇CORS及res.setHeader错误求助
问题分析与解决方案
核心问题
- CORS拦截:React应用(44411端口)与react-email服务(3000端口)属于不同域,浏览器同源策略会拦截跨域请求;Postman不受浏览器同源策略限制,因此能正常请求。
res.setHeader is not a function报错:你大概率在Next.js App Router的route.ts中使用了Express生态的cors中间件——Next.js App Router的Response对象遵循Web标准,没有Express的setHeader方法,导致中间件调用失败。
解决方案
方案1:手动设置CORS响应头(推荐,无需额外依赖)
直接在route.ts中添加CORS头,并处理OPTIONS预检请求:
import { NextResponse } from 'next/server'; import { Resend } from 'resend'; // 导入你的React Email组件 import YourEmailTemplate from '@/emails/YourEmailTemplate'; const resend = new Resend(process.env.RESEND_API_KEY); export async function POST(request: Request) { // 配置CORS头,允许你的React应用域名 const corsHeaders = new Headers({ 'Access-Control-Allow-Origin': 'http://localhost:44411', 'Access-Control-Allow-Methods': 'POST, OPTIONS', 'Access-Control-Allow-Headers': 'Content-Type', }); // 处理浏览器OPTIONS预检请求 if (request.method === 'OPTIONS') { return new NextResponse(null, { headers: corsHeaders }); } try { const payload = await request.json(); const { data, error } = await resend.emails.send({ from: 'Your App <onboarding@resend.dev>', to: [payload.toEmail], subject: payload.subject, react: YourEmailTemplate({ content: payload.content }), }); if (error) { return new NextResponse(JSON.stringify({ error }), { status: 400, headers: corsHeaders, }); } return new NextResponse(JSON.stringify(data), { headers: corsHeaders }); } catch (err) { return new NextResponse(JSON.stringify({ error: err }), { status: 500, headers: corsHeaders, }); } }
方案2:使用适配Next.js的CORS工具
如果不想手动写头,可以用next-cors包(专门适配Next.js的CORS处理工具):
- 安装依赖
npm install next-cors
- 修改
route.ts
import { NextResponse } from 'next/server'; import { Resend } from 'resend'; import nextCors from 'next-cors'; import YourEmailTemplate from '@/emails/YourEmailTemplate'; const resend = new Resend(process.env.RESEND_API_KEY); export async function POST(request: Request) { // 配置CORS规则 await nextCors(request, NextResponse, { origin: 'http://localhost:44411', methods: ['POST', 'OPTIONS'], allowedHeaders: ['Content-Type'], }); try { const payload = await request.json(); const { data, error } = await resend.emails.send({ from: 'Your App <onboarding@resend.dev>', to: [payload.toEmail], subject: payload.subject, react: YourEmailTemplate({ content: payload.content }), }); if (error) return NextResponse.json({ error }, { status: 400 }); return NextResponse.json(data); } catch (err) { return NextResponse.json({ error: err }, { status: 500 }); } }
注意事项
- 生产环境不要硬编码
http://localhost:44411,改用环境变量动态配置允许的域名,比如:'Access-Control-Allow-Origin': process.env.NEXT_PUBLIC_REACT_APP_URL || 'http://localhost:44411', - 确认React应用中的API请求地址正确,比如:
// React的handleSubmit代码示例 async function handleSubmit(formData) { try { const response = await fetch('http://localhost:3000/api/email', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(formData), }); const data = await response.json(); // 处理响应 } catch (err) { console.error('请求失败:', err); } } - 如果你用的是Next.js Pages Router的API路由(
pages/api/xxx.ts),可以直接使用Express的cors中间件,因为Pages Router的API基于Express,Response对象兼容setHeader方法。
内容的提问来源于stack exchange,提问作者Misterbobbie
相关产品推荐
相关产品推荐

