⚠️ Alpha内测版本警告:此为早期内部构建版本,尚不完整且可能存在错误,欢迎大家提Issue反馈问题或建议
Skip to content

3.6.1 你的 API 长啥样——API Route 结构

一句话破题

在 App Router 中,route.ts 文件通过导出命名函数来定义 API 端点,函数名即 HTTP 方法。

核心价值

Next.js Route Handler 让你无需搭建独立的后端服务器,就能在同一个项目中实现 API。这对于全栈应用和快速原型开发非常便利。

创建 Route Handler

app 目录下创建 route.ts 文件:

app/
└── api/
    └── posts/
        ├── route.ts          # /api/posts
        └── [id]/
            └── route.ts      # /api/posts/:id

基础语法

tsx
// app/api/posts/route.ts

// GET /api/posts - 获取列表
export async function GET(request: Request) {
  const posts = await prisma.post.findMany()
  return Response.json(posts)
}

// POST /api/posts - 创建资源
export async function POST(request: Request) {
  const body = await request.json()
  const post = await prisma.post.create({ data: body })
  return Response.json(post, { status: 201 })
}
tsx
// app/api/posts/[id]/route.ts

// GET /api/posts/:id - 获取单个资源
export async function GET(
  request: Request,
  { params }: { params: { id: string } }
) {
  const post = await prisma.post.findUnique({
    where: { id: params.id }
  })
  
  if (!post) {
    return Response.json({ error: 'Not found' }, { status: 404 })
  }
  
  return Response.json(post)
}

// PUT /api/posts/:id - 更新资源
export async function PUT(
  request: Request,
  { params }: { params: { id: string } }
) {
  const body = await request.json()
  const post = await prisma.post.update({
    where: { id: params.id },
    data: body
  })
  return Response.json(post)
}

// DELETE /api/posts/:id - 删除资源
export async function DELETE(
  request: Request,
  { params }: { params: { id: string } }
) {
  await prisma.post.delete({ where: { id: params.id } })
  return new Response(null, { status: 204 })
}

HTTP 方法对照表

方法用途幂等性请求体
GET读取资源
POST创建资源
PUT完整更新
PATCH部分更新
DELETE删除资源

读取请求数据

获取 JSON 请求体

tsx
export async function POST(request: Request) {
  const body = await request.json()
  // body = { title: "Hello", content: "World" }
}

获取 URL 查询参数

tsx
export async function GET(request: Request) {
  const { searchParams } = new URL(request.url)
  const page = searchParams.get('page') || '1'
  const limit = searchParams.get('limit') || '10'
  // /api/posts?page=2&limit=20
}

获取请求头

tsx
export async function GET(request: Request) {
  const authHeader = request.headers.get('Authorization')
  const contentType = request.headers.get('Content-Type')
}

获取路由参数

tsx
export async function GET(
  request: Request,
  { params }: { params: { id: string; slug: string } }
) {
  // /api/posts/123/comments/abc
  // params = { id: '123', slug: 'abc' }
}

返回响应

JSON 响应

tsx
// 简写
return Response.json({ data: posts })

// 完整写法(可设置更多选项)
return new Response(JSON.stringify({ data: posts }), {
  status: 200,
  headers: {
    'Content-Type': 'application/json',
  },
})

状态码规范

状态码含义使用场景
200OKGET 成功、PUT/PATCH 成功
201CreatedPOST 创建成功
204No ContentDELETE 成功
400Bad Request请求参数错误
401Unauthorized未认证
403Forbidden无权限
404Not Found资源不存在
409Conflict资源冲突
500Internal Error服务器错误

配置路由行为

tsx
// 强制动态渲染(每次请求都执行)
export const dynamic = 'force-dynamic'

// 设置缓存时间
export const revalidate = 60 // 秒

// 允许的 HTTP 方法(其他方法返回 405)
export async function GET() { ... }
export async function POST() { ... }

RESTful 设计最佳实践

URL 设计

GET    /api/posts          # 列表
POST   /api/posts          # 创建
GET    /api/posts/:id      # 详情
PUT    /api/posts/:id      # 更新
DELETE /api/posts/:id      # 删除

GET    /api/posts/:id/comments    # 嵌套资源
POST   /api/posts/:id/comments

响应格式统一

tsx
// 成功响应
{
  "data": { ... },
  "meta": { "total": 100, "page": 1 }
}

// 错误响应
{
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "标题不能为空"
  }
}

AI 协作指南

核心意图:让 AI 生成符合 RESTful 规范的 API。

需求定义公式

  • 功能描述:创建 [资源名] 的 CRUD API
  • URL 规范:遵循 RESTful 设计
  • 响应格式:统一的 JSON 结构

关键术语Route HandlerparamssearchParamsResponse.json

示例 Prompt

请创建一个 /api/users 的 CRUD API:
- GET /api/users - 分页列表,支持 ?page 和 ?limit
- POST /api/users - 创建用户
- GET /api/users/:id - 获取用户详情
- PUT /api/users/:id - 更新用户
- DELETE /api/users/:id - 删除用户
使用统一的响应格式和错误处理

避坑指南

  1. route.ts 和 page.tsx 不能共存:同一目录下只能有其中一个
  2. 动态参数是字符串params.id 是字符串,需要时要转换类型
  3. 注意缓存行为:GET 请求默认可能被缓存,需要动态数据时设置 dynamic = 'force-dynamic'
  4. 处理 CORS:跨域请求需要设置响应头
tsx
const headers = {
  'Access-Control-Allow-Origin': '*',
  'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS',
}

验收清单

  • [ ] API 路径遵循 RESTful 规范
  • [ ] HTTP 方法使用正确
  • [ ] 状态码符合语义
  • [ ] 响应格式统一