第 160 章:Route Handlers(API)
学习目标
- 掌握 Route Handlers 创建 API
- 学会 GET / POST / PUT / DELETE
- 理解请求验证与错误处理
- 学会用中间件
一、Route Handlers 是什么
在 app/ 目录下的 route.ts 文件,导出 HTTP 方法函数,作为 API 端点。
app/
├── api/
│ ├── hello/
│ │ └── route.ts → /api/hello
│ ├── users/
│ │ ├── route.ts → /api/users
│ │ └── [id]/
│ │ └── route.ts → /api/users/:id二、基础
2.1 GET
ts
// app/api/hello/route.ts
export async function GET() {
return Response.json({ message: 'Hello' });
}2.2 POST
ts
// app/api/users/route.ts
export async function POST(request: Request) {
const body = await request.json();
// 验证 body...
const user = await db.user.create({ data: body });
return Response.json(user, { status: 201 });
}2.3 动态参数
ts
// app/api/users/[id]/route.ts
type Params = { params: Promise<{ id: string }> };
export async function GET(request: Request, { params }: Params) {
const { id } = await params;
const user = await db.user.findUnique({ where: { id } });
if (!user) return Response.json({ error: 'Not found' }, { status: 404 });
return Response.json(user);
}
export async function PUT(request: Request, { params }: Params) {
const { id } = await params;
const body = await request.json();
const user = await db.user.update({ where: { id }, data: body });
return Response.json(user);
}
export async function DELETE(request: Request, { params }: Params) {
const { id } = await params;
await db.user.delete({ where: { id } });
return new Response(null, { status: 204 });
}三、请求与响应
3.1 获取查询参数
ts
export async function GET(request: Request) {
const { searchParams } = new URL(request.url);
const page = searchParams.get('page') ?? '1';
const size = searchParams.get('size') ?? '10';
return Response.json({ page, size });
}3.2 获取 Headers
ts
export async function GET(request: Request) {
const auth = request.headers.get('authorization');
if (!auth) return Response.json({ error: 'Unauthorized' }, { status: 401 });
// ...
}3.3 设置 Cookies
ts
import { cookies } from 'next/headers';
export async function POST() {
cookies().set('token', 'xxx', {
httpOnly: true,
secure: true,
maxAge: 60 * 60 * 24,
path: '/',
});
return Response.json({ ok: true });
}四、完整 CRUD 示例
ts
// app/api/users/route.ts
import { z } from 'zod';
import { db } from '@/lib/db';
const UserSchema = z.object({
name: z.string().min(2),
email: z.string().email(),
});
export async function GET() {
const users = await db.user.findMany();
return Response.json(users);
}
export async function POST(request: Request) {
const body = await request.json();
const result = UserSchema.safeParse(body);
if (!result.success) {
return Response.json(
{ error: 'Validation failed', issues: result.error.issues },
{ status: 400 }
);
}
const user = await db.user.create({ data: result.data });
return Response.json(user, { status: 201 });
}五、流式响应
ts
// app/api/stream/route.ts
export async function GET() {
const encoder = new TextEncoder();
const stream = new ReadableStream({
async start(controller) {
for (let i = 0; i < 5; i++) {
controller.enqueue(encoder.encode(`data: ${i}\n\n`));
await new Promise(r => setTimeout(r, 1000));
}
controller.close();
},
});
return new Response(stream, {
headers: { 'Content-Type': 'text/event-stream' },
});
}六、CORS
ts
// app/api/public/route.ts
export async function GET(request: Request) {
// 处理预检
if (request.method === 'OPTIONS') {
return new Response(null, {
status: 204,
headers: {
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Methods': 'GET, POST, OPTIONS',
'Access-Control-Allow-Headers': 'Content-Type',
},
});
}
return Response.json(
{ message: 'CORS OK' },
{
headers: {
'Access-Control-Allow-Origin': '*',
},
}
);
}七、错误处理
ts
export async function POST(request: Request) {
try {
const body = await request.json();
const user = await db.user.create({ data: body });
return Response.json(user, { status: 201 });
} catch (error) {
console.error('Create user failed', error);
return Response.json(
{ error: 'Internal Server Error' },
{ status: 500 }
);
}
}八、Next.js vs 独立后端
| 维度 | Route Handlers | 独立 SpringBoot |
|---|---|---|
| 部署 | 一起 | 单独服务 |
| 适合 | 轻 BFF、SSR | 复杂业务 |
| 性能 | 边缘运行 | 长连接、复杂事务 |
| 复用 | 仅当前项目 | 多端共用 |
九、本章小结
| 方法 | 用途 |
|---|---|
| GET | 读取 |
| POST | 创建 |
| PUT | 更新 |
| DELETE | 删除 |
| OPTIONS | 预检 |
动手练习
- 实现 /api/hello,返回 JSON
- 实现 /api/users 完整 CRUD
- 用 Zod 校验请求体
- 实现流式响应(SSE)
- 实现一个需要鉴权的 API
推荐阅读
下一章:第 161 章:Middleware 与鉴权 →