Fetch请求返回HTML而非JSON的问题求助(Prisma+Next.js)
问题分析与解决方案
核心问题1:API路由错误使用redirect函数
在App Router的API路由中,不能使用next/navigation里的redirect函数——这个函数是给服务器组件用的,在API路由里调用它会直接返回登录页面的HTML内容,而不是正确的重定向响应,这就是你Fetch请求拿到HTML的直接原因。
核心问题2:Fetch请求未携带凭据(关键补充)
如果你的ListCompanies是客户端组件,Fetch请求默认不会发送cookie,导致API里拿不到session,进而触发重定向返回HTML。
修复后的API代码
import { getServerSession } from "next-auth"; import { authOptions } from "../../auth/[...nextauth]/route"; import { prisma } from "@/db"; import { NextResponse } from "next/server"; export async function GET() { const session = await getServerSession(authOptions); if (!session) { // 用NextResponse.redirect返回标准重定向响应,替代服务器组件的redirect函数 return NextResponse.redirect(new URL("/api/auth/signin", process.env.NEXTAUTH_URL || "http://localhost:3000")); } const currentUserEmail = session?.user?.email!; const user = await prisma.user.findUnique({ where: { email: currentUserEmail, }, }); if (user) { const companies = await prisma.company.findMany({ where: { user: user.id, // 已判断user存在,可去掉可选链 }, }); return NextResponse.json(companies); } // 处理user不存在的边界情况,返回明确响应 return NextResponse.json([], { status: 404 }); }
修复后的Fetch请求代码
如果是客户端组件,必须加上credentials: 'include'携带cookie,让API能识别会话:
export default async function ListCompanies() { const res = await fetch("http://localhost:3000/api/company/fetch", { credentials: 'include' // 关键:携带会话cookie }); // 先校验响应状态,避免JSON解析失败 if (!res.ok) { throw new Error(`请求失败:${res.status}`); } const companies = await res.json(); console.log("companies", companies); return ( // 你的组件内容 ); }
额外检查点
- 若
ListCompanies是服务器组件,Fetch无需加credentials,但更建议直接在组件内调用Prisma查询,跳过API环节提升效率。 - 检查
prisma.company.findMany的where条件:如果你的Company模型关联User的字段是userId而非user,需改成userId: user.id,避免查询无结果。
内容的提问来源于stack exchange,提问作者Daniel
相关产品推荐
相关产品推荐

