Vercel部署全栈应用遇CORS跨域错误(状态码204)求助
CORS跨域错误排查:Vercel部署后注册/登录请求失败(Status code:204)
本地全栈应用运行正常,但将前后端部署到Vercel后,点击注册/登录表单提交按钮时,浏览器控制台抛出错误:is not allowed by Access-Control-Allow-Origin. Status code: 204,已排查两天未解决。
错误截图

后端注册路由代码
const { firstName, username, age, email, password} = req.body; console.log("Registration user input:", firstName, username, age, email, password); try { const existingUser = await User.findOne({ username }); if (existingUser) { return res.status(400).json({ message: "Username already taken. Please try a different one." }); } const existingEmail = await User.findOne({ email }) if (existingEmail) { return res.status(400).json({ message: "Email already taken. Please try a different one." }); } const salt = await bcrypt.genSalt(10); const hashedPassword = await bcrypt.hash(password, salt); const newUser = new User({firstName,username,age,email,password: hashedPassword,}); await newUser.save(); const token = jwt.sign( { id: newUser._id, username: newUser.username }, process.env.JWT_SECRET!, { expiresIn: "1h" } ); res.status(201).json({ message: "User created successfully", token }); } catch (error) { console.error(error); res.status(500).json({ message: "Something went wrong" }); } });
前端提交代码
event.preventDefault(); setErrorMessage(""); if (!firstName || firstName.length <= 1) { setErrorMessage("First name is required and should be longer than 1 character."); } else if (!username || username.length <= 4) { setErrorMessage("Username is required and should be longer than 4 characters."); } else if (!age || Number(age) <= 12) { setErrorMessage("Age is required and should be more than 12."); } else if (!email || !email.includes("@")) { setErrorMessage("A valid email is required."); } else if (!password || !/[!@#$%^&*]/.test(password) || password.length <= 8) { setErrorMessage("Password is required, should be longer than 8 characters, and contain at least one special character."); } else if (password !== passwordConfirmation) { setErrorMessage("Password confirmation does not match the password."); } else { try { //const response = await fetch("http://localhost:3000/api/register", {method: "POST", mode: "cors", headers: { "Content-Type": "application/json" },body: JSON.stringify({ firstName, username, age, email, password })}); const response = await fetch("https://---------.vercel.app/api/register", { method: "POST", headers: { "Content-Type": "application/json" },body: JSON.stringify({ firstName, username, age, email, password })}); if (response.ok) { console.log("User registered successfully"); localStorage.setItem("isLoggedIn", "true"); navigate("/intro"); } else { const data = await response.json(); setErrorMessage(data.message || "Failed to register user"); console.error("Failed to register user"); } } catch (error) { console.error("An error occurred:", error); } } };
解决方案
1. 配置Vercel全局CORS规则
在后端项目根目录创建vercel.json文件,添加跨域配置:
{ "headers": [ { "source": "/api/(.*)", "headers": [ { "key": "Access-Control-Allow-Credentials", "value": "true" }, { "key": "Access-Control-Allow-Origin", "value": "https://your-frontend.vercel.app" }, // 替换为你的前端实际域名 { "key": "Access-Control-Allow-Methods", "value": "GET,OPTIONS,PATCH,DELETE,POST,PUT" }, { "key": "Access-Control-Allow-Headers", "value": "Content-Type" } ] } ] }
配置完成后重新部署后端项目,确保配置生效。
2. 处理OPTIONS预检请求
浏览器发送POST请求前会自动发送OPTIONS预检请求,需要在API路由中明确响应:
// 在注册路由前添加OPTIONS处理 app.options('/api/register', (req, res) => { res.setHeader('Access-Control-Allow-Origin', 'https://your-frontend.vercel.app'); res.setHeader('Access-Control-Allow-Methods', 'POST'); res.setHeader('Access-Control-Allow-Headers', 'Content-Type'); res.sendStatus(200); });
如果使用Next.js API路由,可借助cors包简化处理:
import Cors from 'cors'; const cors = Cors({ methods: ['POST', 'OPTIONS'], origin: 'https://your-frontend.vercel.app', }); function runMiddleware(req, res, fn) { return new Promise((resolve, reject) => { fn(req, res, (result) => { if (result instanceof Error) return reject(result); return resolve(result); }); }); } export default async function handler(req, res) { await runMiddleware(req, res, cors); // 原有的注册逻辑... }
3. 修正前端请求配置
在fetch中明确指定mode: "cors",确保浏览器按跨域规则处理请求:
const response = await fetch("https://your-backend.vercel.app/api/register", { method: "POST", mode: "cors", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ firstName, username, age, email, password }) });
4. 清除Vercel缓存重新部署
Vercel可能缓存旧代码,手动触发后端项目的重新部署,确保新的CORS配置完全生效。
内容的提问来源于stack exchange,提问作者MBahreman
相关产品推荐
相关产品推荐

