Skip to content

API 基础与 RESTful 接口

后端核心 REST API Axios

一、什么是 API

1.1 定义

API = Application Programming Interface — 定义不同软件之间如何交互的 规则和协议

1.2 类比

API 就像两个说不同语言的人之间的 翻译官

你的网站 (JS) ←── API ──→ 天气服务 (Python)
  Program A        桥梁        Program B

1.3 三个真实场景

场景你的软件API 提供方数据流
天气日记网站日记应用OpenWeatherGET ← 获取天气数据
邮件收集注册表单MailChimpPOST → 发送邮箱数据
智能浇花电脑程序IoT 设备POST → 触发浇水

1.4 API 架构风格

类型特点使用场景
REST基于 HTTP,最流行Web 开发首选
GraphQL客户端定义返回数据结构复杂前端查询
SOAPXML 格式,严格规范企业级/金融系统
gRPC高性能二进制协议微服务通信

💡 Web 开发中,REST API 是必学的。它使用我们已掌握的 HTTP 方法(GET/POST/PUT/PATCH/DELETE)。


二、请求结构

2.1 三大组成部分

https://bored-api.com/filter?type=social&participants=2
└──────── 基础 URL ──────┘└ 端点 ┘└──── 查询参数 ────────┘

2.2 端点(Endpoint)

API 服务器上的 固定路由,代表不同功能:

/random    → 获取随机活动
/filter    → 按条件筛选活动
/activity  → 获取特定活动

2.3 查询参数(Query Parameters)

用于 筛选、排序、搜索

?type=social&participants=2
 ↑           ↑
 第一个参数    后续用 & 连接
 以 ? 开始
格式:?key1=value1&key2=value2&key3=value3

2.4 路径参数(Path Parameters)

用于 识别特定资源(ID、用户名等):

/activity/5914292
          └── 路径参数(唯一标识)

2.5 查询参数 vs 路径参数

特征查询参数路径参数
用途筛选、排序标识特定资源
位置?key=value/resource/id
可选性通常可选通常必需
示例?type=social/user/angela

三、JSON

3.1 什么是 JSON

JSON = JavaScript Object Notation — 轻量级数据交换格式。

3.2 JSON vs JavaScript 对象

javascript
// JavaScript 对象 — key 无需引号
const wardrobe = {
  doors: 2,
  drawers: 4,
  color: "white"
};

// JSON — key 必须是字符串(双引号)
{
  "doors": 2,
  "drawers": 4,
  "color": "white"
}

3.3 宜家类比

概念类比
JS 对象完整的大衣柜(占空间,不便运输)
JSON宜家平板包装(最小化体积,便于运输)
序列化拆解衣柜 → 装成平板包
反序列化打开平板包 → 组装衣柜

3.4 序列化与反序列化

javascript
// JS 对象 → JSON 字符串(序列化 / 打平)
const jsonString = JSON.stringify(jsObject);

// JSON 字符串 → JS 对象(反序列化 / 组装)
const jsObject = JSON.parse(jsonString);

3.5 JSON 查看器

复杂 JSON 难以阅读时,使用在线工具可视化:


四、Axios — 服务端 API 请求

4.1 为什么用 Axios

方式代码量特点
原生 Node(https 模块)~20 行需手动处理数据块、解析 JSON
Axios~5 行自动解析 JSON、简洁的错误处理
bash
npm i axios

4.2 GET 请求

javascript
import axios from "axios";

app.get("/", async (req, res) => {
  try {
    const response = await axios.get("https://bored-api.com/random");
    // response.data 已自动解析为 JS 对象!
    res.render("index.ejs", { data: response.data });
  } catch (error) {
    res.render("index.ejs", { error: error.message });
  }
});

4.3 POST 请求

javascript
const result = await axios.post("https://api.example.com/register", {
  username: "jack",
  password: "secret123"
});

4.4 PUT / PATCH / DELETE

javascript
// PUT — 完整替换资源
await axios.put(url, { name: "Hugo", age: 25 });

// PATCH — 部分更新
await axios.patch(url, { name: "Hugo" });

// DELETE — 删除资源
await axios.delete(url);

4.5 Axios 方法签名

javascript
// GET / DELETE — 两个参数
axios.get(url, [config])
axios.delete(url, [config])

// POST / PUT / PATCH — 三个参数
axios.post(url, [data], [config])
axios.put(url, [data], [config])
axios.patch(url, [data], [config])

4.6 async/await vs .then()

javascript
// ✅ 推荐:async/await(现代语法,更清晰)
async function getData() {
  const response = await axios.get(url);
  console.log(response.data);
}

// 也可以:.then() 链(旧语法)
axios.get(url).then(response => {
  console.log(response.data);
}).catch(error => {
  console.log(error);
});

五、API 认证(四个等级)

5.1 认证 vs 授权

概念含义类比
认证(Authentication)证明你是谁出示身份证
授权(Authorization)证明你有权限出示门禁卡

5.2 四种认证方式

安全性递增 →
┌───────────┐  ┌───────────┐  ┌───────────┐  ┌───────────┐
│ 无认证     │  │ Basic     │  │ API Key   │  │ Token     │
│           │  │ Auth      │  │           │  │ (OAuth)   │
└───────────┘  └───────────┘  └───────────┘  └───────────┘
防护方式:       用户名+密码     可重置的密钥    临时令牌
Rate Limit     Base64编码      查询参数/Header  不暴露密码

5.3 Level 0:无认证

javascript
// 任何人都可以请求,通过 Rate Limit 防止滥用
const response = await axios.get("https://bored-api.com/random");

5.4 Level 1:Basic Auth

javascript
// 用户名+密码 → Base64 编码 → Authorization Header
const response = await axios.get(url, {
  auth: {
    username: "jack",
    password: "secret123"
  }
});

Base64 编码

jack:secret123 → Base64 → amFjazpzZWNyZXQxMjM=

发送的 Header:Authorization: Basic amFjazpzZWNyZXQxMjM=

5.5 Level 2:API Key

javascript
// 方式 1:作为查询参数
const response = await axios.get(url, {
  params: {
    score: 7,
    apiKey: "your-api-key-here"
  }
});

// 方式 2:放在 URL 中
const response = await axios.get(
  `${url}?score=7&apiKey=your-api-key-here`
);

API Key 的用途:

  • 追踪每个用户的请求量
  • 按使用量计费
  • 可以随时重新生成(不暴露密码)

5.6 Level 3:Bearer Token (OAuth)

javascript
// 第一步:用用户名密码获取 Token
const tokenRes = await axios.post(authUrl, {
  username: "jack",
  password: "secret123"
});
const token = tokenRes.data.token;

// 第二步:用 Token 请求 API
const response = await axios.get(url, {
  headers: {
    Authorization: `Bearer ${token}`
  }
});

OAuth 流程(第三方应用):

1. 用户在 API 提供方(如 Google)登录
2. API 提供方生成 Token
3. Token 返回给第三方应用
4. 第三方用 Token 代表用户操作
→ 用户密码始终不会暴露给第三方!

六、REST API 的 CRUD 操作

6.1 完整 CRUD 示例

javascript
const API_URL = "https://api.example.com";

// CREATE — 创建资源
app.post("/create", async (req, res) => {
  const response = await axios.post(`${API_URL}/secrets`, {
    secret: req.body.secret,
    score: req.body.score
  }, {
    headers: { Authorization: `Bearer ${token}` }
  });
  res.redirect("/");
});

// READ — 读取资源
app.get("/", async (req, res) => {
  const response = await axios.get(`${API_URL}/secrets/42`, {
    headers: { Authorization: `Bearer ${token}` }
  });
  res.render("index.ejs", { data: response.data });
});

// UPDATE (PUT) — 完整替换
app.post("/update-put", async (req, res) => {
  const response = await axios.put(`${API_URL}/secrets/42`, {
    secret: req.body.secret,
    score: req.body.score
  }, {
    headers: { Authorization: `Bearer ${token}` }
  });
  res.redirect("/");
});

// UPDATE (PATCH) — 部分更新
app.post("/update-patch", async (req, res) => {
  const response = await axios.patch(`${API_URL}/secrets/42`, {
    score: req.body.score  // 只更新分数
  }, {
    headers: { Authorization: `Bearer ${token}` }
  });
  res.redirect("/");
});

// DELETE — 删除资源
app.post("/delete", async (req, res) => {
  await axios.delete(`${API_URL}/secrets/42`, {
    headers: { Authorization: `Bearer ${token}` }
  });
  res.redirect("/");
});

6.2 PUT vs PATCH 对比

javascript
// 原始数据:{ id: 42, secret: "My secret", score: 5 }

// PUT — 必须提供完整数据(缺少的字段会被清空)
await axios.put(url, { secret: "New secret", score: 8 });
// 结果:{ id: 42, secret: "New secret", score: 8 }

// PATCH — 只提供要修改的字段
await axios.patch(url, { score: 8 });
// 结果:{ id: 42, secret: "My secret", score: 8 }

七、API 使用流程总结

1. 阅读文档 📖
   ├── 了解可用端点
   ├── 了解认证方式
   └── 了解数据结构

2. Postman 测试 🧪
   ├── 尝试各个端点
   ├── 配置认证
   └── 确认响应格式

3. 代码实现 💻
   ├── 安装 Axios
   ├── 构建请求
   ├── 处理响应数据
   └── 错误处理

4. 集成到网站 🌐
   ├── 从前端表单获取用户输入
   ├── 服务端发起 API 请求
   ├── 将数据传递给 EJS 模板
   └── 渲染到页面

← 返回 Web 开发研究