Next.js 提供了强大的 API Routes 功能,允许开发者创建 API 端点来处理服务器端逻辑。API Routes 可以处理数据库查询、身份验证、表单提交等服务器端操作。
API Routes 基础
创建 API Route
在 pages/api 目录下创建文件,每个文件都会成为一个 API 端点。
shellpages/ api/ hello.js → /api/hello users/ index.js → /api/users [id].js → /api/users/123
基本示例
javascript// pages/api/hello.js export default function handler(req, res) { res.status(200).json({ message: 'Hello from Next.js API!' }); }
请求和响应对象
请求对象 (req)
req 对象包含以下属性:
req.method:HTTP 方法(GET、POST、PUT、DELETE 等)req.query:查询参数req.body:请求体(POST、PUT 等)req.headers:请求头req.cookies:Cookie
响应对象 (res)
res 对象提供以下方法:
res.status(code):设置状态码res.json(data):发送 JSON 响应res.send(data):发送响应res.redirect(url):重定向res.setHeader(name, value):设置响应头
处理不同的 HTTP 方法
javascript// pages/api/users/[id].js export default async function handler(req, res) { const { id } = req.query; switch (req.method) { case 'GET': const user = await getUserById(id); res.status(200).json(user); break; case 'PUT': const updatedUser = await updateUser(id, req.body); res.status(200).json(updatedUser); break; case 'DELETE': await deleteUser(id); res.status(204).end(); break; default: res.setHeader('Allow', ['GET', 'PUT', 'DELETE']); res.status(405).end(`Method ${req.method} Not Allowed`); } }
中间件
自定义中间件
javascript// lib/middleware.js export function authMiddleware(req, res, next) { const token = req.headers.authorization; if (!token) { return res.status(401).json({ error: 'Unauthorized' }); } // 验证 token const user = verifyToken(token); if (!user) { return res.status(401).json({ error: 'Invalid token' }); } req.user = user; next(); }
使用中间件
javascript// pages/api/protected.js import { authMiddleware } from '@/lib/middleware'; export default function handler(req, res) { // 受保护的路由 res.status(200).json({ user: req.user }); } // 应用中间件 export const config = { api: { bodyParser: false, externalResolver: true, }, }; // 在实际使用中,需要手动调用中间件
数据库集成
使用 Prisma
javascript// pages/api/posts/index.js import { PrismaClient } from '@prisma/client'; const prisma = new PrismaClient(); export default async function handler(req, res) { if (req.method === 'GET') { const posts = await prisma.post.findMany(); res.status(200).json(posts); } else if (req.method === 'POST') { const post = await prisma.post.create({ data: req.body, }); res.status(201).json(post); } else { res.status(405).end(); } }
使用 MongoDB
javascript// pages/api/users/index.js import clientPromise from '@/lib/mongodb'; export default async function handler(req, res) { const client = await clientPromise; const db = client.db(); if (req.method === 'GET') { const users = await db.collection('users').find({}).toArray(); res.status(200).json(users); } else if (req.method === 'POST') { const result = await db.collection('users').insertOne(req.body); res.status(201).json(result); } else { res.status(405).end(); } }
身份验证
使用 NextAuth.js
javascript// pages/api/auth/[...nextauth].js import NextAuth from 'next-auth'; import Providers from 'next-auth/providers'; export default NextAuth({ providers: [ Providers.Google({ clientId: process.env.GOOGLE_CLIENT_ID, clientSecret: process.env.GOOGLE_CLIENT_SECRET, }), Providers.Credentials({ name: 'Credentials', credentials: { username: { label: "Username", type: "text" }, password: { label: "Password", type: "password" } }, authorize: async (credentials) => { // 验证用户 const user = await authenticate(credentials); if (user) { return user; } return null; } }), ], database: process.env.DATABASE_URL, });
JWT 验证
javascript// lib/auth.js import jwt from 'jsonwebtoken'; export function verifyToken(token) { try { return jwt.verify(token, process.env.JWT_SECRET); } catch (error) { return null; } } export function createToken(payload) { return jwt.sign(payload, process.env.JWT_SECRET, { expiresIn: '1d' }); }
文件上传
javascript// pages/api/upload.js import formidable from 'formidable'; import fs from 'fs'; import path from 'path'; export const config = { api: { bodyParser: false, }, }; export default async function handler(req, res) { if (req.method !== 'POST') { return res.status(405).end(); } const form = formidable({ uploadDir: path.join(process.cwd(), '/public/uploads'), keepExtensions: true, }); form.parse(req, (err, fields, files) => { if (err) { return res.status(500).json({ error: 'File upload failed' }); } const file = files.file[0]; res.status(200).json({ url: `/uploads/${path.basename(file.filepath)}` }); }); }
错误处理
javascript// pages/api/error.js export default function handler(req, res) { try { // 业务逻辑 const data = processData(req.body); res.status(200).json(data); } catch (error) { console.error('API Error:', error); if (error.name === 'ValidationError') { res.status(400).json({ error: error.message }); } else if (error.name === 'UnauthorizedError') { res.status(401).json({ error: 'Unauthorized' }); } else { res.status(500).json({ error: 'Internal server error' }); } } }
CORS 配置
javascript// pages/api/cors.js export default function handler(req, res) { res.setHeader('Access-Control-Allow-Credentials', true); res.setHeader('Access-Control-Allow-Origin', '*'); res.setHeader('Access-Control-Allow-Methods', 'GET,OPTIONS,PATCH,DELETE,POST,PUT'); res.setHeader( 'Access-Control-Allow-Headers', 'X-CSRF-Token, X-Requested-With, Accept, Accept-Version, Content-Length, Content-MD5, Content-Type, Date, X-Api-Version' ); if (req.method === 'OPTIONS') { res.status(200).end(); return; } res.status(200).json({ message: 'CORS enabled' }); }
最佳实践
- 使用环境变量:敏感信息存储在
.env文件中 - 验证输入:使用验证库如 Zod 或 Yup
- 错误处理:统一错误处理格式
- 日志记录:记录请求和错误信息
- 速率限制:防止 API 滥用
- 缓存:对频繁访问的数据进行缓存
- 文档化:使用 Swagger 或 OpenAPI 文档化 API
Next.js API Routes 提供了简单而强大的方式来构建服务器端 API,无需单独的后端服务器,使全栈开发变得更加便捷。