Next.js中间件生产环境fetch报ECONNREFUSED问题求助
Next.js中间件生产环境fetch失败的原因及解决办法
报错原因
开发模式下Next.js的dev服务器监听localhost:3000,用url.origin(即http://localhost:3000)请求内部API时,相当于本地向自身服务发起请求,能正常连通。但生产环境下情况完全不同:
- 多数部署平台(如Vercel、容器服务)不会让应用监听
localhost:3000,要么分配随机端口,要么绑定0.0.0.0这类内部地址; - 中间件用完整外部URL发起请求,相当于绕到网络层访问应用本身,但生产环境的应用根本没对外暴露
localhost:3000这个地址,因此出现连接被拒绝的错误(ECONNREFUSED)。
解决方案
不要通过外部URL调用内部API,以下两种方式均可解决:
方式1:直接调用API逻辑函数
把/api/auth/session的代码抽成独立工具函数,比如放在lib/getSession.ts中:
// lib/getSession.ts export async function getSession(reqHeaders: Headers) { // 这里写原/api/auth/session里的逻辑,比如从cookie解析session }
然后在中间件里直接调用该函数,无需走fetch:
import { getSession } from '@/lib/getSession'; export default async function middleware(req: NextRequest) { const url = req.nextUrl.clone(); if (publicPaths.some((path) => url.pathname.includes(path))) return NextResponse.next(); let session; try { session = await getSession(req.headers); } catch (e) { console.error(e); } url.search = new URLSearchParams(`callbackUrl=${url}`).toString(); url.pathname = `/api/auth/signin`; return session?.user ? NextResponse.next() : NextResponse.redirect(url); }
方式2:用相对路径走内部fetch
如果坚持用fetch,Next.js支持直接用相对路径调用内部API,无需添加url.origin,此时Next.js会直接在内部处理请求,不走网络:
session = await fetch( `${env.NEXT_PUBLIC_APP_BASE_PATH}/api/auth/session`, { headers: req.headers, cache: 'no-store', // 根据业务需求调整缓存策略 } ).then((res) => res.json());
去掉url.origin后,Next.js会自动识别这是内部API,直接调用对应处理逻辑,不会发起外部网络请求,也就不会出现连接拒绝的问题。
内容的提问来源于stack exchange,提问作者Mugetsu
相关产品推荐
相关产品推荐

