路由处理器Skill route-handlers

Next.js路由处理器技能专注于使用Next.js框架的App Router创建和管理API端点。它涵盖了HTTP方法处理、请求和响应操作、流式响应、CORS配置、缓存和错误处理等关键功能,适用于构建RESTful API、Web服务和后端接口,提高开发效率和性能。关键词包括:Next.js、路由处理器、API开发、HTTP请求、响应处理、流式响应、CORS、缓存、错误处理。

后端开发 0 次安装 0 次浏览 更新于 3/8/2026

名称: 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示例