名称: route-handlers 描述: 当用户要求“创建API路由”、“添加端点”、“构建REST API”、“处理POST请求”、“创建路由处理器”、“流式响应”,或需要有关App Router中Next.js API开发的指导时,应使用此技能。 版本: 1.0.0
Next.js 路由处理器
概述
路由处理器允许您使用Web请求和响应API创建API端点。它们在app目录内的route.ts文件中定义。
基本结构
文件约定
路由处理器使用route.ts(或route.js):
app/
├── api/
│ ├── users/
│ │ └── route.ts # /api/users
│ └── posts/
│ ├── route.ts # /api/posts
│ └── [id]/
│ └── route.ts # /api/posts/:id
HTTP 方法
导出以HTTP方法命名的函数:
// app/api/users/route.ts
import { NextResponse } from 'next/server'
export async function GET() {
const users = await db.user.findMany()
return NextResponse.json(users)
}
export async function POST(request: Request) {
const body = await request.json()
const user = await db.user.create({ data: body })
return NextResponse.json(user, { status: 201 })
}
支持的方法:GET, POST, PUT, PATCH, DELETE, HEAD, OPTIONS
请求处理
读取请求体
export async function POST(request: Request) {
// JSON 体
const json = await request.json()
// 表单数据
const formData = await request.formData()
const name = formData.get('name')
// 文本体
const text = await request.text()
return NextResponse.json({ received: true })
}
URL 参数
动态路由参数:
// app/api/posts/[id]/route.ts
interface RouteContext {
params: Promise<{ id: string }>
}
export async function GET(
request: Request,
context: RouteContext
) {
const { id } = await context.params
const post = await db.post.findUnique({ where: { id } })
if (!post) {
return NextResponse.json(
{ error: '未找到' },
{ status: 404 }
)
}
return NextResponse.json(post)
}
查询参数
export async function GET(request: Request) {
const { searchParams } = new URL(request.url)
const page = searchParams.get('page') ?? '1'
const limit = searchParams.get('limit') ?? '10'
const posts = await db.post.findMany({
skip: (parseInt(page) - 1) * parseInt(limit),
take: parseInt(limit),
})
return NextResponse.json(posts)
}
请求头
export async function GET(request: Request) {
const authHeader = request.headers.get('authorization')
if (!authHeader?.startsWith('Bearer ')) {
return NextResponse.json(
{ error: '未授权' },
{ status: 401 }
)
}
const token = authHeader.split(' ')[1]
// 验证令牌...
return NextResponse.json({ authenticated: true })
}
响应处理
JSON 响应
import { NextResponse } from 'next/server'
export async function GET() {
return NextResponse.json(
{ message: '你好' },
{ status: 200 }
)
}
设置头
export async function GET() {
return NextResponse.json(
{ data: '值' },
{
headers: {
'Cache-Control': 'max-age=3600',
'X-Custom-Header': '自定义值',
},
}
)
}
设置 Cookie
import { cookies } from 'next/headers'
export async function POST(request: Request) {
const cookieStore = await cookies()
// 设置 Cookie
cookieStore.set('session', 'abc123', {
httpOnly: true,
secure: process.env.NODE_ENV === 'production',
sameSite: 'lax',
maxAge: 60 * 60 * 24 * 7, // 1 周
})
return NextResponse.json({ success: true })
}
重定向
import { redirect } from 'next/navigation'
import { NextResponse } from 'next/server'
export async function GET() {
// 选项 1: redirect 函数(抛出)
redirect('/login')
// 选项 2: NextResponse.redirect
return NextResponse.redirect(new URL('/login', request.url))
}
流式响应
文本流
export async function GET() {
const encoder = new TextEncoder()
const stream = new ReadableStream({
async start(controller) {
for (let i = 0; i < 10; i++) {
controller.enqueue(encoder.encode(`data: ${i}
`))
await new Promise(resolve => setTimeout(resolve, 100))
}
controller.close()
},
})
return new Response(stream, {
headers: {
'Content-Type': 'text/event-stream',
'Cache-Control': 'no-cache',
'Connection': 'keep-alive',
},
})
}
AI/LLM 流
export async function POST(request: Request) {
const { prompt } = await request.json()
const response = await openai.chat.completions.create({
model: 'gpt-4',
messages: [{ role: 'user', content: prompt }],
stream: true,
})
const stream = new ReadableStream({
async start(controller) {
for await (const chunk of response) {
const text = chunk.choices[0]?.delta?.content || ''
controller.enqueue(new TextEncoder().encode(text))
}
controller.close()
},
})
return new Response(stream, {
headers: { 'Content-Type': 'text/plain' },
})
}
CORS 配置
export async function OPTIONS() {
return new Response(null, {
status: 204,
headers: {
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE',
'Access-Control-Allow-Headers': 'Content-Type, Authorization',
},
})
}
export async function GET() {
return NextResponse.json(
{ data: '值' },
{
headers: {
'Access-Control-Allow-Origin': '*',
},
}
)
}
缓存
静态(默认用于 GET)
// 默认缓存
export async function GET() {
const data = await fetch('https://api.example.com/data')
return NextResponse.json(await data.json())
}
退出缓存
export const dynamic = 'force-dynamic'
export async function GET() {
// 总是新鲜
}
// 或使用 Cookie/头(自动退出)
import { cookies } from 'next/headers'
export async function GET() {
const cookieStore = await cookies()
// 现在动态
}
错误处理
export async function GET(request: Request) {
try {
const data = await riskyOperation()
return NextResponse.json(data)
} catch (error) {
console.error('API 错误:', error)
if (error instanceof ValidationError) {
return NextResponse.json(
{ error: error.message },
{ status: 400 }
)
}
return NextResponse.json(
{ error: '内部服务器错误' },
{ status: 500 }
)
}
}
资源
详细模式,请参阅:
references/http-methods.md- 完整的HTTP方法指南references/streaming-responses.md- 高级流模式examples/crud-api.md- 完整的CRUD API示例