Axios+NextJS调用接口始终返回405方法不允许问题求助
问题分析
线上环境出现405错误的核心原因是跨域预请求(OPTIONS)未被正确处理:本地开发时同源请求不会触发OPTIONS预检查,而线上跨域场景下浏览器会先发OPTIONS请求验证权限,但当前代码既未在API路由中处理OPTIONS方法,也未在中间件中拦截响应,导致请求进入API路由的错误分支返回非法状态码;同时错误分支误用了406 Not Acceptable状态码,方法不允许的正确状态码应为405 Method Not Allowed。
解决方案
方案1:修改API路由直接处理OPTIONS请求
在API处理文件中新增OPTIONS方法的处理逻辑,直接返回200响应完成预检查:
import axios from 'utils/axios'; export default async function handler(req, res) { const { method, body: { currentPassword, password }, headers: { authorization } } = req; // 优先处理OPTIONS跨域预请求 if (method === 'OPTIONS') { res.status(200).end(); return; } try { if (method === 'POST') { const { data } = await axios.post( `${process.env.REACT_BACKEND_URL}users/change-password`, { password, currentPassword }, { headers: { Authorization: authorization } } ); res.status(200).send(data); } else { res.setHeader('Allow', ['POST']); // 修正方法不允许的状态码为405 res.status(405).end(`Method ${method} Not Allowed`); } } catch (error) { if (error.statusCode && error.statusCode !== 500) { res.status(error.statusCode).end(error.message); } else { res.status(500).end('Server Error'); } } }
方案2:在中间件层统一拦截OPTIONS请求
如果需要为所有API路由统一处理跨域预请求,修改中间件代码,直接对OPTIONS请求返回带CORS头的响应,无需进入API路由:
import { NextResponse } from 'next/server'; export function middleware(request) { // 拦截OPTIONS预请求直接返回响应 if (request.method === 'OPTIONS') { const res = new NextResponse(null, { status: 200 }); res.headers.append('Cache-control', 'no-store'); res.headers.append('Access-Control-Allow-Credentials', 'true'); res.headers.append('Access-Control-Allow-Origin', '*'); // 生产环境替换为实际前端域名 res.headers.append('Access-Control-Allow-Methods', 'GET,DELETE,PATCH,POST,PUT'); res.headers.append('Access-Control-Allow-Headers', '*'); return res; } // 其他请求正常添加CORS头并继续执行 const res = NextResponse.next(); res.headers.append('Cache-control', 'no-store'); res.headers.append('Access-Control-Allow-Credentials', 'true'); res.headers.append('Access-Control-Allow-Origin', '*'); // 生产环境替换为实际前端域名 res.headers.append('Access-Control-Allow-Methods', 'GET,DELETE,PATCH,POST,PUT'); res.headers.append('Access-Control-Allow-Headers', '*'); return res; } export const config = { matcher: '/api/:path*' };
额外注意事项
- 生产环境禁止使用
*作为Access-Control-Allow-Origin,替换为实际前端域名(如https://your-frontend-domain.com),避免安全风险 - 检查环境变量
REACT_BACKEND_URL是否配置正确,确保转发路径无拼写错误 - 确认前端请求的
Authorization头是否正确携带,避免后端返回错误触发API路由的异常分支
内容的提问来源于stack exchange,提问作者Julian Mendez
相关产品推荐
相关产品推荐

