Next.js 13.5.2 API路由getServerSession返回null及报错求助
Next.js + Next-Auth 问题解决:API路由会话获取失败及请求错误
问题现象
- API路由中调用
getServerSession(authOptions)始终返回null,但Server组件和Client组件分别通过getServerSession和useSession()能正常获取会话 - 调用创建待办的API接口时出现错误:
⨯ TypeError: Response body object should not be disturbed or locked at extractBody
相关代码
Next-Auth配置
import { authOptions } from '@/lib/auth-options' import NextAuth from 'next-auth' const handler = NextAuth(authOptions) export {handler as GET,handler as POST}
authOptions配置
import { type NextAuthOptions } from "next-auth"; import GithubProvider from "next-auth/providers/github"; import { getAuthCredentials } from "./secrets"; export const authOptions: NextAuthOptions = { providers: [ GithubProvider({ clientId: getAuthCredentials().clientId, clientSecret: getAuthCredentials().clientSecret, }), ], secret: getAuthCredentials().secret, session: { strategy: "jwt", }, callbacks: { jwt: ({ token, user, session }) => { if (user) { token.id = user.id; } return token; }, session: ({ session, token }) => { if (token?.id) { session.user.id = token.id; } return session; }, }, pages: { signIn: "/signin", signOut: "/signout", }, };
创建待办的API路由(api/todos)
export async function POST(req: NextRequest) { let body = await req.json(); const session = await getServerSession(authOptions); console.log({ session }); // {session : null} let validateBody = addTodoSchema.safeParse(body); console.log({ validateBody }); if (!validateBody.success) { return NextResponse.json({ success: false, error: validateBody.error, }); } try { await connectToDatabase(); let todo = await prisma.todo.create({ data: { ...body, createdBy: session?.user.id, }, }); return NextResponse.json({ success: true, data: todo, message: "Todo created successfully", }); } catch (error: any) { console.log({ error }); return NextResponse.json({ success: false, error: error.message, }); } finally { await prisma.$disconnect(); } }
调用接口的服务端函数
"use server"; import { headers } from "next/headers"; export const addTodo = async ({ title }: { title: string }) => { try { let res = await fetch("http://localhost:3000/api/todos", { method: "POST", headers: headers(), body: JSON.stringify({ title, }), }); let data = await res.json(); console.log({ data }); } catch (error: any) { console.log({ error }); // throw new Error(error.message); } };
解决方案
1. 修复API路由getServerSession返回null的问题
问题根源在于服务端函数传递了所有请求头,其中包含Next.js内部非标准头,导致Next-Auth无法正确解析会话。只需传递必要的Cookie头即可:
修改调用接口的服务端函数:
"use server"; import { cookies } from "next/headers"; export const addTodo = async ({ title }: { title: string }) => { try { const cookieStore = cookies(); let res = await fetch("http://localhost:3000/api/todos", { method: "POST", headers: { "Content-Type": "application/json", "Cookie": cookieStore.toString() }, body: JSON.stringify({ title }), }); let data = await res.json(); console.log({ data }); } catch (error: any) { console.log({ error }); } };
同时确保authOptions中的secret与环境变量完全一致,JWT会话解析依赖该密钥。
2. 修复Response body锁定错误
该错误是由于传递多余请求头导致请求体解析异常,上述修改headers的操作已解决此问题。另外注意在API路由中只读取一次请求体(你的代码已做到),避免重复调用req.json()。
额外优化
- 移除API路由finally块中的
prisma.$disconnect(),Prisma会自动管理连接池,手动断开会降低性能。 - 在API路由中增加未授权判断,提前终止逻辑:
const session = await getServerSession(authOptions); if (!session) { return NextResponse.json( { success: false, error: "Unauthorized" }, { status: 401 } ); }
内容的提问来源于stack exchange,提问作者Sai Kolli
相关产品推荐
相关产品推荐

