LESSON 5.3 / BACKEND & API

写出第一个后端接口

后端接收请求、执行可信逻辑并返回结构化响应。框架负责路由和协议细节,业务逻辑仍需要人来定义。

预计阅读15–20 分钟
完成结果可以从浏览器或命令行调用自己写的 API。
本课目标
  • 可以从浏览器或命令行调用自己写的 API。
  • 路由、处理函数、参数和响应模型
  • 实现 health 接口与一个接收文本、返回统计结果的 POST 接口。
开始之前
  • 完成 5.2「后端运行环境与依赖隔离」
01

FOUNDATION

必须理解

后端接收请求、执行可信逻辑并返回结构化响应。框架负责路由和协议细节,业务逻辑仍需要人来定义。

后端在可信环境接收请求、验证输入、执行规则并返回响应。第一个接口的重点不是框架语法,而是看清路由、处理函数和响应之间的关系。

先建立整体直觉

前端是柜台,后端处理函数是办事窗口。窗口先确认你要办什么、材料是否齐全,再按规则处理并给回执;不能因为柜台说“合法”就跳过检查。

贯穿本课的实际场景

在 Next.js App Router 中创建 /api/tasks Route Handler,GET 返回示例任务,POST 读取 JSON 标题并返回新任务。

概念 1

路由、处理函数、参数和响应模型

先用白话理解

路由会把某个 URL 和方法交给对应的处理函数。Next.js 的 Route Handler 放在 app/api/.../route.ts,同一个地址可以分别处理 GET 和 POST。

基础概念

路由把 HTTP 方法与 URL 匹配到处理函数;参数把请求中的路径、查询或正文数据交给函数;响应模型规定返回状态、头部和正文的结构。

进一步理解

同一个 `/api/tasks` 可以用 GET 读取、POST 创建。框架完成匹配和基础解析,处理函数仍要校验输入、执行规则并选择正确响应。

路径参数常标识资源,查询参数常描述筛选,正文承载复杂提交。来源不同不代表可信度不同,全部外部输入都要验证。

放进实际场景

POST `/api/tasks` 进入创建函数,读取 JSON 标题,校验后生成任务,返回 201 和任务对象。

容易混淆的地方

路由文件不是数据库表,响应模型也不是内部实体;入口契约应与存储实现保持可控距离。

这一小节记住:一个后端端点就是明确入口、可信处理和结构化响应。

概念 2

前端代码与服务端代码的信任边界

先用白话理解

请求里有方法、请求头和正文,响应里有状态码、响应头和正文。服务端可以读取秘密配置,但从浏览器传来的每一个值都得当成不可信输入。

基础概念

信任边界是数据从不受控制环境进入可信执行环境的位置。浏览器、URL、请求头和 JSON 都可被调用者修改,服务端必须重新验证身份、权限和业务规则。

进一步理解

前端校验改善体验,可以提前提示空标题;攻击者或其他程序却能绕过页面直接发请求,因此不能把前端结果当安全依据。

服务端能访问数据库和秘密配置,返回响应时要只挑选允许公开字段。日志与错误也不能泄露堆栈、路径和凭证。

放进实际场景

即使按钮只给管理员显示,POST 接口仍从服务端会话读取真实身份并检查角色,而不相信请求体中的 `role:'admin'`。

容易混淆的地方

TypeScript 类型只在开发和编译阶段提供检查,网络传来的 JSON 在运行时仍可能是任意形状。

这一小节记住:凡是跨过网络进入服务端的数据,都先当成不可信输入。

概念 3

开发服务器、端口和接口调试

先用白话理解

TypeScript 能在写代码时提醒你类型不对,却管不到网络上真正发来的 JSON。别人完全可以绕过你的页面直接调用接口,所以运行时还要再校验。

基础概念

开发服务器是在本机监听端口、提供快速调试能力的进程。接口调试是用浏览器 Network、命令行或客户端工具检查请求和响应,而不仅看页面提示。

进一步理解

服务启动后会打印绑定地址与端口。连接失败先确认进程仍在运行、地址正确、端口未被占用;接口错误再看状态码、正文和服务端日志。

日志应带时间、请求标识和必要上下文,不能记录秘密。一次调试只改变一个变量,修改后重发同一请求比较结果。

放进实际场景

用开发工具向 localhost 上的 POST 接口发送一个合法标题和一个空标题,对比 201 与 400,并在服务端日志找到两次请求。

容易混淆的地方

浏览器能打开首页不代表 API 端口和路径正确;同一应用也可能有页面路由与接口路由两套处理。

这一小节记住:调试后端要同时观察客户端响应与服务端处理证据。

最小 Route Handler
运行前先确认
  • 代码位于 Next.js App Router 的 `app/api/tasks/route.ts`。
  • 示例只演示输入校验与响应,尚未写入数据库或检查用户身份。
export async function POST(request: Request) {
  const body = await request.json();
  if (typeof body.title !== "string" || !body.title.trim()) {
    return Response.json({ error: "标题不能为空" }, { status: 400 });
  }
  return Response.json({ id: crypto.randomUUID(), title: body.title.trim(), done: false }, { status: 201 });
}
这段代码在做什么

即使 TypeScript 声明了类型,网络输入仍需在运行时检查。

  1. request.json 解析调用者提交的 JSON;解析本身也可能失败,生产实现需统一处理。
  2. 运行时检查 title 的类型和去空格结果,失败返回 400。
  3. 合法输入生成 id,并用 201 表示资源已创建。
你应该观察到

合法标题得到 201 与任务 JSON;空字符串或非字符串得到 400;刷新页面不会保留该任务,因为示例没有数据库。

02

AI COLLABORATION

AI 如何参与

让 AI 先写接口契约和示例响应,再实现处理逻辑,避免前端后端各自猜格式。

推荐协作顺序

  1. 1

    先让 AI 和你一起写 POST /api/tasks 的成功与失败响应。

  2. 2

    契约确认后再生成 Route Handler,而且一次只实现一个方法。

  3. 3

    不用前端,直接发送请求核对状态码和 JSON。

可直接使用的 Prompt
请用 Next.js App Router 和 TypeScript 实现最小 /api/tasks:GET 返回两条内存任务,POST 接收 { title: string } 并返回 201。先写接口契约和三种示例响应,再写 route.ts。暂时不接数据库。
应该得到什么

契约先于实现,GET/POST 职责分开,POST 对缺失标题返回明确 400,而不是永远 200。

人工检查清单

  • 确认服务端没有相信客户端提供的 id、userId 或权限,错误响应结构一致。
  • 让 AI 先写出方法、路径、输入、成功响应和失败响应,再生成处理函数。
  • 绕过页面直接发送无效 JSON,确认服务端仍会拒绝并且响应不泄露内部信息。
03

COMMON TRAPS

常见误区

错误不是需要隐藏的失败,而是帮助你看清系统边界的证据。下面三类问题在 AI 辅助学习中最常出现。

误区 1

先写代码,最后才猜接口格式

你会看到
前端期待 title,后端却返回 name,联调时双方不断改。
为什么发生
把前端数据当可信会让任何人通过自制请求伪造身份、越过限制或提交意外类型。
怎样纠正
实现前先写请求和响应示例,把字段名固定下来。
误区 2

相信 TypeScript 会校验网络输入

你会看到
请求传来数字或空值,服务端仍按字符串处理。
为什么发生
直接返回内部对象会把密码哈希、密钥字段或未来新增字段无意暴露给调用者。
怎样纠正
类型只帮助开发,收到 JSON 后仍要做运行时校验。
误区 3

所有情况都返回 200

你会看到
前端无法区分创建成功、输入错误和服务器故障。
为什么发生
只看页面报错会丢失真实状态码和服务端日志,路径、端口与业务异常无法区分。
怎样纠正
让 HTTP 状态码表达结果类别,正文再说明具体原因。
04

HANDS-ON

动手任务

实现 health 接口与一个接收文本、返回统计结果的 POST 接口。

准备条件
  • 完成 5.2「后端运行环境与依赖隔离」

跟着做

  1. 01

    写出 GET 与 POST 的请求响应契约。

  2. 02

    创建 app/api/tasks/route.ts。

  3. 03

    实现 GET 返回内存数组。

  4. 04

    实现 POST 读取 JSON、校验标题并返回 201。

  5. 05

    分别发送正常、空标题和错误 JSON 请求,记录状态码。

完成标志

可以从浏览器或命令行调用自己写的 API。

加餐挑战

为 GET 增加 ?done=true 查询条件,并说明过滤属于哪一层。

离开本课前,自问四件事

  • 路由、处理函数、请求参数和响应模型怎样连接?
  • 为什么前端已经校验后,后端仍必须再次校验?
  • TypeScript 为什么不能保证网络 JSON 真实符合类型?
  • 接口调试时应同时收集客户端与服务端哪些证据?
完成本课了吗?

确认完成后,会同步更新学习中心的课程学习进度。