NextJS动态ID API路由调用报错:无效URL问题排查
NextJS服务端调用API路由出现Invalid URL错误问题
问题背景
我基于NextJS开发项目,搭建了三层逻辑分离架构,目标是把错误处理尽可能集中在getServerSideProps中,当前需求是从数据库获取用户的所有列表数据。
第一层:API路由(运行正常)
创建了get-all-lists文件夹及[userId].js文件,请求地址为http://localhost:3000/api/get-all-lists/iudga937gr8,通过Prisma实现数据库查询,代码如下:
import prisma from '../../../lib/prisma' export default async function handler(req, res) { const { userId } = req.query; if (req.method === 'GET') { try { const shoppingLists = await prisma.List.findMany({ where: { userId: userId }}); res.status(200).json({lists: shoppingLists}); } catch (error) { console.log(error); res.status(500).json({ message: 'Something went wrong. Please try again'}); } } else { res.status(500).json({message: 'Invalid method requested!'}); } }
第二层:抽象层(触发错误)
为了避免getServerSideProps中请求代码混乱,我写了抽象层函数用于获取列表,但调用时触发URL无效错误:
export const getAllLists = async userId => { try { const lists = await axios.get(`/api/get-all-lists/${userId}`); return lists; } catch (error) { console.log('Abstraction layer error: ', error); return 'Something went wrong. Please try again later'; } }
问题现象
用Postman或浏览器直接访问完整URL(如http://localhost:3000/api/get-all-lists/clbcpc0hi0002sb1wsiea3q5d)能得到正确结果,但调用抽象层函数时出现如下错误:
Abstraction layer error: TypeError [ERR_INVALID_URL]: Invalid URL at new NodeError (node:internal/errors:371:5) at onParseError (node:internal/url:552:9) at new URL (node:internal/url:628:5) at dispatchHttpRequest (file:///Users/sasdaniel/Desktop/massage/node_modules/axios/lib/adapters/http.js:176:20) at new Promise (<anonymous>) at http (file:///Users/sasdaniel/Desktop/massage/node_modules/axios/lib/adapters/http.js:112:10) at Axios.dispatchRequest (file:///Users/sasdaniel/Desktop/massage/node_modules/axios/lib/core/dispatchRequest.js:51:10) at Axios.request (file:///Users/sasdaniel/Desktop/massage/node_modules/axios/lib/core/Axios.js:142:33) at Axios.<computed> [as get] (file:///Users/sasdaniel/Desktop/massage/node_modules/axios/lib/core/Axios.js:168:17) at Function.wrap [as get] (file:///Users/sasdaniel/Desktop/massage/node_modules/axios/lib/helpers/bind.js:5:15) { input: '/api/get-all-lists/clbcpc0hi0002sb1wsiea3q5d', code: 'ERR_INVALID_URL' }
解决方案
错误原因
getServerSideProps运行在Node.js服务端环境中,axios无法识别相对路径/api/xxx——浏览器会自动补全域名生成完整URL,但Node.js没有当前域名的上下文,必须传入完整URL才能正常发起请求。
修复方案1:直接调用数据库逻辑(推荐)
既然抽象层是在服务端调用,完全没必要绕路调用自己的API路由,直接复用Prisma查询逻辑,既解决URL问题又提升性能:
// 调整后的抽象层代码 import prisma from '../lib/prisma'; // 路径根据你的项目结构自行调整 export const getAllLists = async userId => { try { const shoppingLists = await prisma.List.findMany({ where: { userId }}); return { data: { lists: shoppingLists } }; // 保持和原API返回结构一致,方便上层处理 } catch (error) { console.log('Abstraction layer error: ', error); throw new Error('Something went wrong. Please try again later'); // 抛出错误让getServerSideProps统一处理 } }
修复方案2:使用完整URL调用API路由
如果坚持要通过API路由获取数据,需要在抽象层中使用完整URL,建议通过环境变量配置避免硬编码:
- 在项目根目录的
.env.local文件中添加:
NEXT_PUBLIC_BASE_URL=http://localhost:3000
- 修改抽象层代码:
export const getAllLists = async userId => { try { const baseUrl = process.env.NEXT_PUBLIC_BASE_URL; const lists = await axios.get(`${baseUrl}/api/get-all-lists/${userId}`); return lists; } catch (error) { console.log('Abstraction layer error: ', error); throw new Error('Something went wrong. Please try again later'); } }
生产环境只需把NEXT_PUBLIC_BASE_URL改成你的实际域名即可。
额外提示
- 服务端逻辑(
getServerSideProps、API路由)中,优先直接调用数据库层,减少不必要的内部HTTP请求。 - 错误处理尽量用
throw代替返回字符串,这样能在getServerSideProps中统一捕获处理,符合你集中错误处理的设计目标。
内容的提问来源于stack exchange,提问作者daniel sas
相关产品推荐
相关产品推荐

