Next.js 教程系列(十二)API Routes:构建轻量级后端服务

前言

大家好,我是鲫小鱼。是一名不写前端代码的前端工程师,热衷于分享非前端的知识,带领切图仔逃离切图圈子,欢迎关注我,微信公众号:《鲫小鱼不正经》。欢迎点赞、收藏、关注,一键三连!!


第十二章 API Routes:构建轻量级后端服务

一、理论讲解

1. API Routes 的原理

API Routes 是 Next.js 提供的内置后端能力,允许你在 pages/api 目录下直接编写 Node.js 风格的 API 接口。每个文件自动映射为一个 HTTP 路由,无需额外配置。

  • 文件系统路由:如 pages/api/user.ts 自动映射为 /api/user。
  • 与传统后端区别:无需单独部署后端服务,前后端同构,开发体验极佳。
  • 支持多种 HTTP 方法:GET、POST、PUT、DELETE、PATCH 等。
  • 请求体解析:自动解析 JSON、表单、multipart 等。
  • 与 App Router/Server Actions 的关系:API Routes 适合 RESTful/文件上传/第三方集成,Server Actions 适合表单、组件内服务端逻辑。
API Routes 文件结构与路由映射
text 复制代码
/pages/api/
  user.ts    -> /api/user
  posts/[id].ts -> /api/posts/123
支持的 HTTP 方法

API Routes 通过 req.method 区分不同请求类型。

ts 复制代码
export default function handler(req, res) {
  if (req.method === 'GET') { /* 查询 */ }
  if (req.method === 'POST') { /* 新增 */ }
  if (req.method === 'PUT') { /* 更新 */ }
  if (req.method === 'DELETE') { /* 删除 */ }
}
请求体解析
  • JSON 自动解析为 req.body
  • multipart/form-data 需自定义解析(如用 formidable)
API 中间件

可自定义中间件实现日志、权限、CORS、限流等。

ts 复制代码
function withAuth(handler) {
  return (req, res) => {
    if (!req.headers['x-token']) return res.status(401).json({ message: '未授权' });
    return handler(req, res);
  };
}
export default withAuth((req, res) => { /* ... */ });
权限校验
  • 建议所有敏感 API 均做 token/session 校验
  • 可结合 JWT、Session、OAuth 等
文件上传
  • 需关闭 bodyParser,使用第三方库(如 formidable、multer)解析文件流
ts 复制代码
// pages/api/upload.ts
import formidable from 'formidable';
export const config = { api: { bodyParser: false } };
export default function handler(req, res) {
  const form = new formidable.IncomingForm();
  form.parse(req, (err, fields, files) => {
    if (err) return res.status(500).json({ message: '上传失败' });
    // 处理 files
    res.json({ url: '/uploads/' + files.file.newFilename });
  });
}
流式响应
  • 可用 res.write/res.end 实现大文件下载、实时推送
ts 复制代码
export default function handler(req, res) {
  res.setHeader('Content-Type', 'text/plain');
  res.write('Hello, ');
  setTimeout(() => {
    res.write('World!');
    res.end();
  }, 1000);
}
常见误区
  • 忽略权限校验,易被攻击
  • 忽略 CORS,导致跨域失败
  • 请求体过大未限制,易被刷爆
  • 错误处理不规范,影响前端体验

二、代码示例

1. 多种 HTTP 方法的 API

ts 复制代码
// pages/api/todo.ts
let todos = [];
export default function handler(req, res) {
  if (req.method === 'GET') return res.json(todos);
  if (req.method === 'POST') {
    const { text } = req.body;
    todos.push({ id: Date.now(), text });
    return res.status(201).json({ success: true });
  }
  if (req.method === 'DELETE') {
    const { id } = req.body;
    todos = todos.filter(t => t.id !== id);
    return res.json({ success: true });
  }
  res.status(405).end();
}

2. Zod 校验参数

ts 复制代码
import { z } from 'zod';
const schema = z.object({ text: z.string().min(1) });
export default function handler(req, res) {
  if (req.method === 'POST') {
    const result = schema.safeParse(req.body);
    if (!result.success) return res.status(400).json({ error: result.error.errors });
    // ...业务逻辑
  }
}

3. 文件上传

ts 复制代码
// pages/api/upload.ts
import formidable from 'formidable';
export const config = { api: { bodyParser: false } };
export default function handler(req, res) {
  const form = new formidable.IncomingForm();
  form.parse(req, (err, fields, files) => {
    if (err) return res.status(500).json({ message: '上传失败' });
    res.json({ url: '/uploads/' + files.file.newFilename });
  });
}

4. 流式响应

ts 复制代码
export default function handler(req, res) {
  res.setHeader('Content-Type', 'text/plain');
  res.write('Hello, ');
  setTimeout(() => {
    res.write('World!');
    res.end();
  }, 1000);
}

5. API 路由安全与错误处理

ts 复制代码
function withAuth(handler) {
  return (req, res) => {
    if (!req.headers['x-token']) return res.status(401).json({ message: '未授权' });
    return handler(req, res);
  };
}
export default withAuth((req, res) => {
  try {
    // ...业务逻辑
  } catch (err) {
    res.status(500).json({ message: '服务异常' });
  }
});

6. 移动端适配与 API 日志埋点

js 复制代码
// pages/api/log.ts
export default function handler(req, res) {
  const { event, userAgent } = req.body;
  // 记录日志
  res.json({ success: true });
}

三、实战项目:图片分享应用 API 设计

1. 项目需求

  • 支持图片上传、图片列表获取
  • 文件存储可本地或模拟
  • 权限校验,防止未授权上传
  • 错误兜底、性能监控、移动端友好

2. 技术选型

  • Next.js API Routes
  • formidable 文件上传
  • JWT/Token 权限校验
  • Sentry/自研埋点

3. 目录结构

text 复制代码
/pic-share-demo
  |-- pages/
      |-- api/
          |-- upload.ts
          |-- images.ts
          |-- log.ts
  |-- uploads/
  |-- components/
      |-- UploadForm.tsx
      |-- ImageList.tsx
  |-- styles/
      |-- globals.css

4. 图片上传 API

ts 复制代码
// pages/api/upload.ts
import formidable from 'formidable';
export const config = { api: { bodyParser: false } };
function withAuth(handler) {
  return (req, res) => {
    if (!req.headers['x-token']) return res.status(401).json({ message: '未授权' });
    return handler(req, res);
  };
}
export default withAuth(function handler(req, res) {
  const form = new formidable.IncomingForm({ uploadDir: './uploads', keepExtensions: true });
  form.parse(req, (err, fields, files) => {
    if (err) return res.status(500).json({ message: '上传失败' });
    res.json({ url: '/uploads/' + files.file.newFilename });
  });
});

5. 图片列表 API

ts 复制代码
// pages/api/images.ts
import fs from 'fs';
export default function handler(req, res) {
  const files = fs.readdirSync('./uploads');
  res.json({ images: files.map(f => '/uploads/' + f) });
}

6. 错误兜底与性能监控

js 复制代码
// pages/api/log.ts
export default function handler(req, res) {
  const { event, userAgent } = req.body;
  // 上报日志
  res.json({ success: true });
}

四、最佳实践

  1. API 设计规范:RESTful 路径、动词明确、状态码规范。
  2. 参数校验:用 Zod/Joi 校验所有输入,防止脏数据。
ts 复制代码
import { z } from 'zod';
const schema = z.object({ text: z.string().min(1) });
const result = schema.safeParse(req.body);
if (!result.success) return res.status(400).json({ error: result.error.errors });
  1. 权限安全:所有敏感操作都要鉴权。
  2. 错误处理:try/catch 包裹业务逻辑,返回规范错误。
  3. 团队协作:接口文档同步、mock 数据、自动化测试。
  4. 监控报警:API 异常自动上报。
  5. 极端场景降级:接口超时、上传失败时前端兜底提示。
tsx 复制代码
if (error) return <div>图片上传失败,请稍后重试</div>;

五、常见问题与解决方案

  • Q: 跨域(CORS)问题?
    • A: 设置响应头 res.setHeader('Access-Control-Allow-Origin', '*'),或用中间件统一处理。
  • Q: 请求体过大?
    • A: 限制文件大小,formidable/multer 支持 maxFileSize。
  • Q: 文件上传失败?
    • A: 检查目录权限、磁盘空间、bodyParser 配置。
  • Q: 权限绕过?
    • A: 所有敏感 API 都要鉴权,token/session 校验。
  • Q: API 性能瓶颈?
    • A: 静态资源用 CDN,接口限流,异步处理。
  • Q: 接口幂等性?
    • A: 关键操作加唯一标识,防止重复提交。

最后感谢阅读!欢迎关注我,微信公众号:《鲫小鱼不正经》。欢迎点赞、收藏、关注,一键三连!!!

相关推荐
崔庆才丨静觅10 小时前
hCaptcha 验证码图像识别 API 对接教程
前端
passerby606111 小时前
完成前端时间处理的另一块版图
前端·github·web components
掘了11 小时前
「2025 年终总结」在所有失去的人中,我最怀念我自己
前端·后端·年终总结
崔庆才丨静觅11 小时前
实用免费的 Short URL 短链接 API 对接说明
前端
崔庆才丨静觅11 小时前
5分钟快速搭建 AI 平台并用它赚钱!
前端
崔庆才丨静觅11 小时前
比官方便宜一半以上!Midjourney API 申请及使用
前端
Moment12 小时前
富文本编辑器在 AI 时代为什么这么受欢迎
前端·javascript·后端
崔庆才丨静觅12 小时前
刷屏全网的“nano-banana”API接入指南!0.1元/张量产高清创意图,开发者必藏
前端
剪刀石头布啊12 小时前
jwt介绍
前端
爱敲代码的小鱼12 小时前
AJAX(异步交互的技术来实现从服务端中获取数据):
前端·javascript·ajax