路由处理
2026年9月6日
页面用 page.tsx,接口用 route.ts。两边都按目录映射 URL,前端页面和后端处理可以放在同一个仓库。
文件放哪
app/
└── api/
├── user/route.ts → /api/user
├── login/route.ts → /api/login
└── user/[id]/route.ts → /api/user/:id
text
page.tsx 和 route.ts 不能同目录,框架无法同时当页面又当接口。前后端代码分开放更清楚。
导出的函数名必须是 HTTP 方法,且全大写:GET、POST、PUT、PATCH、DELETE、HEAD、OPTIONS。没写 OPTIONS 时,框架会补一份。
GET 和查询串
import { NextRequest, NextResponse } from "next/server";
export async function GET(request: NextRequest) {
const id = request.nextUrl.searchParams.get("id");
return NextResponse.json({ id });
}
ts
本地可以用 VS Code / Cursor 的 REST Client 插件,写一个 test.http:
GET http:/api/user?id=123 HTTP/1.1
http
POST 和 body
export async function POST(request: NextRequest) {
const body = await request.json();
return NextResponse.json({ ok: true, body }, { status: 201 });
}
ts
按 Content-Type 选读法:request.json()、formData()、text()、arrayBuffer()、blob()。
POST http:/api/user HTTP/1.1
Content-Type: application/json
{
"name": "槿",
"age": 18
}
http
动态段
第二参数里的 params 现在是 Promise:
export async function GET(
_request: NextRequest,
{ params }: { params: Promise<{ id: string }> }
) {
const { id } = await params;
return NextResponse.json({ hello: id });
}
ts
/api/user/886 会得到 id === "886"。
Cookie
next/headers 的 cookies() 在 Route Handler 里也能用。登录成功写 token、再提供检查接口,是常见写法:
import { cookies } from "next/headers";
import { NextRequest, NextResponse } from "next/server";
export async function POST(request: NextRequest) {
const { username, password } = await request.json();
if (username !== "admin" || password !== "demo") {
return NextResponse.json({ ok: false }, { status: 401 });
}
const jar = await cookies();
jar.set("token", "demo-token", {
httpOnly: true,
sameSite: "lax",
maxAge: 60 * 60 * 24 * 30,
});
return NextResponse.json({ ok: true });
}
export async function GET() {
const jar = await cookies();
const token = jar.get("token");
if (token?.value === "demo-token") {
return NextResponse.json({ ok: true });
}
return NextResponse.json({ ok: false }, { status: 401 });
}
ts
httpOnly 让脚本读不到 cookie,能少一类 XSS 偷 token。正式环境还要 secure、短过期、真正的会话存储,这里只演示 API 形状。
客户端登录页用 fetch('/api/login', { method: 'POST', ... }),成功后再 router.push('/home')。保护页面可以再打一次 GET,或把检查挪到下一篇的 Proxy。
下一篇用 Vercel AI SDK 把对话接口接到页面上。