Next.js API路由基础 #

一、API路由概述 #

1.1 什么是API路由 #

API路由允许在Next.js应用中创建API端点:

text
app/
└── api/
    └── hello/
        └── route.ts    → /api/hello

1.2 创建API路由 #

tsx
import { NextResponse } from 'next/server'

export async function GET() {
    return NextResponse.json({ message: 'Hello World' })
}

1.3 HTTP方法 #

方法 函数名 说明
GET GET() 获取资源
POST POST() 创建资源
PUT PUT() 更新资源
PATCH PATCH() 部分更新
DELETE DELETE() 删除资源
HEAD HEAD() 获取头信息
OPTIONS OPTIONS() 获取支持的方法

二、请求处理 #

2.1 请求对象 #

tsx
import { NextRequest, NextResponse } from 'next/server'

export async function GET(request: NextRequest) {
    const url = request.url
    const method = request.method
    const headers = request.headers
    const cookies = request.cookies
    
    const searchParams = request.nextUrl.searchParams
    const query = searchParams.get('q')
    
    return NextResponse.json({ url, method, query })
}

2.2 读取请求体 #

tsx
import { NextRequest, NextResponse } from 'next/server'

export async function POST(request: NextRequest) {
    const body = await request.json()
    
    return NextResponse.json({ received: body })
}

2.3 读取表单数据 #

tsx
import { NextRequest, NextResponse } from 'next/server'

export async function POST(request: NextRequest) {
    const formData = await request.formData()
    const name = formData.get('name')
    const file = formData.get('file') as File
    
    return NextResponse.json({ name, filename: file?.name })
}

2.4 读取Cookie #

tsx
import { NextRequest, NextResponse } from 'next/server'

export async function GET(request: NextRequest) {
    const token = request.cookies.get('token')
    
    return NextResponse.json({ token: token?.value })
}

2.5 读取Header #

tsx
import { NextRequest, NextResponse } from 'next/server'

export async function GET(request: NextRequest) {
    const authorization = request.headers.get('authorization')
    const userAgent = request.headers.get('user-agent')
    
    return NextResponse.json({ authorization, userAgent })
}

三、响应处理 #

3.1 JSON响应 #

tsx
import { NextResponse } from 'next/server'

export async function GET() {
    return NextResponse.json(
        { message: 'Success', data: { id: 1, name: 'Test' } },
        { status: 200 }
    )
}

3.2 自定义响应 #

tsx
import { NextResponse } from 'next/server'

export async function GET() {
    return new NextResponse('Hello World', {
        status: 200,
        headers: {
            'Content-Type': 'text/plain',
            'X-Custom-Header': 'value',
        },
    })
}

3.3 设置Cookie #

tsx
import { NextResponse } from 'next/server'

export async function POST() {
    const response = NextResponse.json({ success: true })
    
    response.cookies.set('token', 'jwt-token', {
        httpOnly: true,
        secure: true,
        sameSite: 'strict',
        maxAge: 60 * 60 * 24 * 7,
    })
    
    return response
}

3.4 设置Header #

tsx
import { NextResponse } from 'next/server'

export async function GET() {
    const response = NextResponse.json({ data: 'test' })
    
    response.headers.set('X-Custom-Header', 'value')
    response.headers.set('Cache-Control', 'public, max-age=3600')
    
    return response
}

3.5 重定向 #

tsx
import { NextResponse } from 'next/server'

export async function GET() {
    return NextResponse.redirect(new URL('/login', 'https://example.com'))
}

四、动态路由 #

4.1 动态参数 #

tsx
interface RouteContext {
    params: Promise<{ id: string }>
}

export async function GET(request: Request, { params }: RouteContext) {
    const { id } = await params
    
    return NextResponse.json({ id })
}

4.2 捕获所有路由 #

tsx
interface RouteContext {
    params: Promise<{ slug: string[] }>
}

export async function GET(request: Request, { params }: RouteContext) {
    const { slug } = await params
    
    return NextResponse.json({ path: slug.join('/') })
}

五、错误处理 #

5.1 错误响应 #

tsx
import { NextResponse } from 'next/server'

export async function GET() {
    try {
        const data = await getData()
        return NextResponse.json(data)
    } catch (error) {
        return NextResponse.json(
            { error: 'Internal Server Error' },
            { status: 500 }
        )
    }
}

5.2 验证错误 #

tsx
import { NextResponse } from 'next/server'
import { z } from 'zod'

const schema = z.object({
    name: z.string().min(1),
    email: z.string().email(),
})

export async function POST(request: Request) {
    const body = await request.json()
    const result = schema.safeParse(body)
    
    if (!result.success) {
        return NextResponse.json(
            { error: 'Validation Error', details: result.error.flatten() },
            { status: 400 }
        )
    }
    
    return NextResponse.json({ success: true, data: result.data })
}

六、中间件 #

6.1 CORS #

tsx
import { NextResponse } from 'next/server'

const corsHeaders = {
    'Access-Control-Allow-Origin': '*',
    'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS',
    'Access-Control-Allow-Headers': 'Content-Type, Authorization',
}

export async function OPTIONS() {
    return NextResponse.json({}, { headers: corsHeaders })
}

export async function GET() {
    return NextResponse.json(
        { data: 'test' },
        { headers: corsHeaders }
    )
}

6.2 认证 #

tsx
import { NextRequest, NextResponse } from 'next/server'

export async function GET(request: NextRequest) {
    const token = request.headers.get('authorization')?.replace('Bearer ', '')
    
    if (!token) {
        return NextResponse.json(
            { error: 'Unauthorized' },
            { status: 401 }
        )
    }
    
    const user = await verifyToken(token)
    
    if (!user) {
        return NextResponse.json(
            { error: 'Invalid token' },
            { status: 401 }
        )
    }
    
    return NextResponse.json({ user })
}

七、最佳实践 #

7.1 类型安全 #

tsx
interface User {
    id: string
    name: string
    email: string
}

interface ApiResponse<T> {
    data: T
    message: string
}

export async function GET(): Promise<NextResponse<ApiResponse<User>>> {
    const user = await getUser()
    
    return NextResponse.json({
        data: user,
        message: 'Success',
    })
}

7.2 错误处理封装 #

tsx
import { NextResponse } from 'next/server'

class ApiError extends Error {
    constructor(public message: string, public status: number) {
        super(message)
    }
}

export function handleError(error: unknown) {
    if (error instanceof ApiError) {
        return NextResponse.json(
            { error: error.message },
            { status: error.status }
        )
    }
    
    console.error('API Error:', error)
    
    return NextResponse.json(
        { error: 'Internal Server Error' },
        { status: 500 }
    )
}

八、总结 #

API路由基础要点:

要点 说明
路由文件 route.ts
HTTP方法 GET/POST/PUT/DELETE
请求对象 NextRequest
响应对象 NextResponse
动态路由 [id]/route.ts
错误处理 try/catch

下一步,让我们学习Route Handlers!

最后更新:2026-03-28