15%

全场主机优惠15%

测试技能,享折扣

使用代码:

Skills
开始使用
29.10.2024
1 +1

REST API:它是什么以及如何工作——开发者完整指南

简介:REST API 为何在现代 Web 开发中至关重要

REST API 是几乎所有现代 Web 应用程序的隐形支柱。从您滑动社交媒体信息流的那一刻,到电商网站完成支付的瞬间,REST API 都在默默协调客户端与服务器之间的数据交换。理解其工作原理——以及如何有效部署它们——是 2024 年及以后每位开发者必备的核心技能。

本指南涵盖您需要了解的一切:REST API 背后的核心概念、HTTP 方法如何映射到实际操作、您今天就能运行的 curl 实用示例,以及构建安全、可扩展 API 的行业最佳实践。我们还将介绍如何在可靠的高性能基础设施上托管您的 REST API,使您的应用程序在真实负载下保持快速和高可用性。

什么是 REST API?

REST API(表述性状态转移应用程序编程接口)是一种标准化的架构方法,允许应用程序通过 HTTP 进行通信。REST 不是一种协议——它是一套架构约束和原则,遵循这些原则可以构建出可预测、可扩展且具有互操作性的 Web 服务。

REST API 使用普遍认可的 Web 标准——HTTP、URL、JSON 和 XML——使其可供每种编程语言和平台的开发者访问。当客户端(如浏览器、移动应用或其他服务器)需要数据或想要触发某个操作时,它会向 REST API 端点发送 HTTP 请求。服务器处理该请求并返回结构化响应,通常为 JSON 格式。

REST 架构的六大约束

REST 由 Roy Fielding 在其 2000 年的博士论文中正式定义。当一个 API 遵循以下架构约束时,即被认为是”RESTful”的:

  1. 客户端-服务器架构——客户端与服务器解耦。客户端负责用户界面;服务器负责数据存储和业务逻辑。它们仅通过定义良好的接口进行通信。
  2. 无状态性——客户端发出的每个 HTTP 请求必须包含服务器处理该请求所需的全部信息。服务器在请求之间不存储任何会话状态。这是可扩展性的基础。
  3. 可缓存性——响应必须声明自身是否可缓存,允许客户端和中间层复用响应,从而降低服务器负载。
  4. 统一接口——资源通过 URL 标识。与资源的交互通过标准化的 HTTP 方法进行。响应具有自描述性。
  5. 分层系统——客户端无法判断自己是在直接与源服务器通信,还是与中间层(如负载均衡器或 CDN)通信。这使得可扩展架构成为可能。
  6. 按需代码(可选)——服务器可以选择性地向客户端发送可执行代码(如 JavaScript),以扩展其功能。

您必须理解的关键概念

资源

在 REST 中,一切皆为资源。资源是您的 API 所暴露的任何数据或对象——用户、产品、博客文章、订单、图片。每个资源由唯一的 URL(统一资源定位符,也称 URI,即统一资源标识符)标识。

https://api.example.com/users
https://api.example.com/users/42
https://api.example.com/posts/7/comments

资源通常以 JSON 格式表示,但也支持 XML。由于 JSON 语法轻量且与 JavaScript 原生兼容,它已成为主流格式。

HTTP 方法(动词)

REST API 使用标准 HTTP 方法来定义对资源应执行的操作。这些方法直接映射到 CRUD 操作:

HTTP 方法CRUD 操作描述
GET读取检索一个资源或资源列表
POST创建创建新资源
PUT更新(完整)完整替换现有资源
PATCH更新(部分)修改现有资源的特定字段
DELETE删除移除资源

端点

端点是可以访问资源的特定 URL 路径。它由 API 的基础 URL 与资源路径组合而成:

Base URL:  https://api.example.com
Endpoint:  /posts
Full URL:  https://api.example.com/posts

请求头

HTTP 请求头携带关于请求或响应的元数据。REST API 交互中常见的请求头包括:

Content-Type: application/json
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
Accept: application/json
Cache-Control: no-cache
  • Content-Type——告知服务器请求体的格式。
  • Authorization——携带身份验证凭据(API 密钥、JWT 令牌、OAuth 令牌)。
  • Accept——告知服务器客户端期望的响应格式。

HTTP 状态码

状态码是服务器传达请求结果的方式。每个 REST API 响应都包含一个三位数状态码:

状态码含义使用场景
200 OK成功标准成功的 GET、PUT、PATCH、DELETE 请求
201 Created资源已创建成功创建新资源的 POST 请求
204 No Content成功,无响应体无响应体的成功 DELETE 请求
400 Bad Request客户端错误请求语法格式错误或参数无效
401 Unauthorized需要身份验证缺少或无效的身份验证凭据
403 Forbidden授权被拒绝已通过身份验证但无权访问该资源
404 Not Found资源不存在请求的资源不存在
429 Too Many Requests超出速率限制客户端发送请求过于频繁
500 Internal Server Error服务器错误意外的服务器端故障

REST API 如何工作?逐步详解

让我们以一个博客平台为例,追踪 REST API 请求的完整生命周期。

第一步——客户端发送 HTTP 请求

用户的浏览器(或移动应用)向 API 服务器发送 HTTP 请求。请求包含:

  • HTTP 方法(GET、POST 等)
  • 端点 URL
  • 请求头(身份验证、内容类型)
  • 可选的请求体(用于 POST、PUT、PATCH)

第二步——服务器处理请求

API 服务器接收请求,验证身份,检查授权,处理业务逻辑,并在必要时查询数据库。

第三步——服务器返回 HTTP 响应

服务器返回包含以下内容的响应:

  • 表示成功或失败的 HTTP 状态码
  • 响应头
  • 包含请求数据或确认信息的响应体(通常为 JSON)

第四步——客户端处理响应

客户端解析 JSON 响应,并使用数据更新用户界面、触发后续操作或显示结果。

使用 curl 的 REST API 实用示例

curl 命令行工具是直接从终端测试和与 REST API 交互的最有效方式之一。以下是涵盖所有主要操作的真实示例。

GET——获取博客文章列表

curl -X GET "https://api.example.com/posts" 
  -H "Authorization: Bearer your-access-token" 
  -H "Accept: application/json"

响应示例:

[
  {
    "id": 1,
    "title": "Understanding REST APIs",
    "author": "Jane Doe",
    "published_at": "2024-01-15T10:30:00Z"
  },
  {
    "id": 2,
    "title": "Building Scalable APIs with Node.js",
    "author": "John Smith",
    "published_at": "2024-01-20T14:00:00Z"
  }
]

GET——通过 ID 获取单个资源

curl -X GET "https://api.example.com/posts/1" 
  -H "Authorization: Bearer your-access-token"

响应示例:

{
  "id": 1,
  "title": "Understanding REST APIs",
  "content": "REST APIs are the backbone of modern web applications...",
  "author": "Jane Doe",
  "tags": ["api", "rest", "web-development"],
  "published_at": "2024-01-15T10:30:00Z"
}

POST——创建新资源

curl -X POST "https://api.example.com/posts" 
  -H "Authorization: Bearer your-access-token" 
  -H "Content-Type: application/json" 
  -d '{
    "title": "Deploying REST APIs on VPS",
    "content": "This guide covers deploying REST APIs on a high-performance VPS...",
    "author": "Jane Doe",
    "tags": ["api", "vps", "deployment"]
  }'

响应示例(201 Created):

{
  "id": 3,
  "title": "Deploying REST APIs on VPS",
  "author": "Jane Doe",
  "created_at": "2024-02-01T09:15:00Z"
}

PUT——更新现有资源(完整替换)

curl -X PUT "https://api.example.com/posts/3" 
  -H "Authorization: Bearer your-access-token" 
  -H "Content-Type: application/json" 
  -d '{
    "title": "Deploying REST APIs on High-Performance VPS",
    "content": "Updated content with new deployment steps...",
    "author": "Jane Doe",
    "tags": ["api", "vps", "deployment", "performance"]
  }'

PATCH——部分更新资源

curl -X PATCH "https://api.example.com/posts/3" 
  -H "Authorization: Bearer your-access-token" 
  -H "Content-Type: application/json" 
  -d '{"title": "The Definitive Guide to Deploying REST APIs"}'

DELETE——删除资源

curl -X DELETE "https://api.example.com/posts/3" 
  -H "Authorization: Bearer your-access-token"

预期响应:204 No Content(空响应体,确认删除成功)

REST API URL 设计:命名规范与最佳实践

良好的 URL 设计使您的 API 直观且具有自文档化特性。请始终遵循以下规范:

资源集合使用复数名词

✅ GET /users
✅ GET /posts
✅ GET /products

❌ GET /user
❌ GET /getPost
❌ GET /fetchAllProducts

嵌套资源使用层级 URL

GET /users/42/orders          → All orders for user 42
GET /users/42/orders/7        → Specific order 7 for user 42
GET /posts/1/comments         → All comments on post 1
POST /posts/1/comments        → Create a new comment on post 1

过滤、排序和分页使用查询参数

GET /posts?status=published
GET /posts?author=jane-doe&limit=10&page=2
GET /products?category=electronics&sort=price_asc&min_price=100

对 API 进行版本控制

始终对 API 进行版本控制,以避免对现有使用者造成破坏性变更:

https://api.example.com/v1/posts
https://api.example.com/v2/posts

为什么使用 REST API?五大有力理由

1. 通用跨平台兼容性

任何能够发送 HTTP 请求的设备或应用程序都可以使用 REST API——Web 浏览器、iOS 应用、Android 应用、桌面应用、IoT 设备以及其他服务器。REST 对 HTTP(Web 的通用语言)的依赖,使其成为互操作性最强的 API 风格。

2. 水平可扩展性

由于 REST API 是无状态的,每个请求都完全自包含。服务器无需在请求之间维护会话状态,这意味着您可以通过在负载均衡器后面添加更多服务器实例来实现水平扩展。这种架构非常适合高流量应用程序。将您的 API 托管在配备 NVMe 存储的 VPS 托管方案上,可为您提供高效处理并发请求所需的原始 I/O 性能。

3. 清晰的关注点分离

REST 强制执行的客户端-服务器分离意味着您的前端团队和后端团队可以独立工作。前端只需了解 API 契约(端点、请求格式、响应模式)。只要 API 契约保持一致,后端可以完全重建或迁移而不影响客户端。

4. 灵活的数据格式

REST API 支持多种数据格式。虽然 JSON 因其轻量特性和 JavaScript 兼容性而成为主流选择,但 REST API 也可以根据客户端发送的 Accept 请求头提供 XML、CSV 甚至二进制数据。

5. 广泛的行业采用与生态系统

REST API 为几乎所有主要科技公司的服务提供支持:GitHub、Stripe、Twilio、Google Maps、Twitter/X、Shopify 等数千家公司。这种广泛采用意味着丰富的工具支持、文档标准(OpenAPI/Swagger)、客户端库以及开发者的高度熟悉度。

REST API 安全:保护您的端点

安全不是可选项。一个安全性差的 API 可能暴露敏感用户数据、允许未授权操作,并带来严重的法律和声誉后果。从第一天起就实施以下安全措施。

身份验证与授权

API 密钥——包含在请求头中的简单令牌。适用于服务器间通信。

Authorization: ApiKey sk_live_abc123xyz789

JWT(JSON Web 令牌)——编码用户身份和声明的签名令牌。适用于面向用户的 API。

Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...

OAuth 2.0——委托授权的行业标准。当第三方应用程序需要访问您平台上的用户资源时使用。

始终使用 HTTPS

切勿通过纯 HTTP 提供 REST API 服务。所有 API 流量必须使用 TLS/SSL 加密。SSL 证书确保客户端与服务器之间传输的数据经过加密,无法被拦截或篡改。现代浏览器和 API 客户端将拒绝或警告未加密的连接。

实施速率限制

速率限制保护您的 API 免受滥用、暴力破解攻击以及失控客户端意外造成的拒绝服务。按 API 密钥、IP 地址或用户账户定义限制。

速率限制响应头示例:

X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 847
X-RateLimit-Reset: 1706745600

当超出限制时,返回 429 Too Many Requests 并附带 Retry-After 响应头。

验证并清理所有输入

永远不要信任客户端提供的数据。验证请求体和查询参数中的每个字段。清理输入以防止 SQL 注入、NoSQL 注入及其他注入攻击。使用模式验证库(如 Node.js 的 Joi 或 Python 的 Pydantic)来强制执行严格的输入契约。

正确配置 CORS

跨源资源共享(CORS)请求头控制哪些来源被允许向您的 API 发出请求。请谨慎配置 CORS——在生产环境中,对于需要身份验证的端点,避免使用通配符(*)来源。

Access-Control-Allow-Origin: https://yourapp.com
Access-Control-Allow-Methods: GET, POST, PUT, DELETE
Access-Control-Allow-Headers: Authorization, Content-Type

REST API 最佳实践:生产就绪检查清单

设计

  • [ ] 资源名称使用复数名词(/users,而非 /user
  • [ ] 从一开始就对 API 进行版本控制(/v1//v2/
  • [ ] 嵌套资源使用层级 URL
  • [ ] 过滤、排序和分页使用查询参数
  • [ ] 返回一致、可预测的 JSON 响应结构

错误处理

  • [ ] 每个响应返回适当的 HTTP 状态码
  • [ ] 在响应体中包含描述性错误信息
  • [ ] 错误响应中绝不暴露堆栈跟踪或内部系统详情
{
  "error": {
    "code": "RESOURCE_NOT_FOUND",
    "message": "The post with ID 99 does not exist.",
    "documentation_url": "https://api.example.com/docs/errors#RESOURCE_NOT_FOUND"
  }
}

性能

  • [ ] 使用适当的 Cache-Control 请求头实现响应缓存
  • [ ] 所有集合端点支持分页
  • [ ] 对响应体使用压缩(gzip/brotli)
  • [ ] 考虑为条件请求实现 ETags

安全

  • [ ] 所有端点强制使用 HTTPS
  • [ ] 实施身份验证(JWT、OAuth 2.0 或 API 密钥)
  • [ ] 对每个客户端应用速率限制
  • [ ] 验证并清理所有输入
  • [ ] 记录所有 API 请求并监控异常

文档

  • [ ] 使用 OpenAPI/Swagger 记录每个端点
  • [ ] 为每个操作提供请求/响应示例
  • [ ] 维护 API 版本变更日志
  • [ ] 提供交互式 API 浏览器(Swagger UI 或 Redoc)

REST API 与其他 API 风格对比:何时选择 REST

特性RESTGraphQLgRPCSOAP
协议HTTPHTTPHTTP/2HTTP/SMTP
数据格式JSON/XMLJSONProtocol BuffersXML
学习曲线
灵活性非常高
性能良好良好优秀
浏览器支持原生支持原生支持有限有限
最适用于公共 API、CRUD 应用复杂数据图微服务企业遗留系统

在以下情况选择 REST:

  • 您正在构建供多种不同客户端使用的公共 API
  • 您的数据模型自然映射到资源和 CRUD 操作
  • 您需要跨平台和语言的最大兼容性
  • 您希望获得广泛的工具支持和开发者熟悉度

在高性能基础设施上托管 REST API

API 基础设施的质量直接影响其可靠性、延迟和可扩展性。以下是为生产 REST API 选择托管环境时需要关注的要点。

您的 API 托管环境需要什么

低延迟存储——NVMe SSD 显著缩短数据库查询时间和文件 I/O,直接提升 API 响应速度。

完整 root 访问权限——您需要安装运行时环境(Node.js、Python、PHP、Go),配置 Web 服务器(Nginx、Apache),设置进程管理器(PM2、systemd),并调整内核参数以优化网络性能。

DDoS 防护——API 是大流量攻击的常见目标。基础设施级别的 DDoS 缓解措施可在无需您自行实施的情况下保护您的服务。

可扩展资源——随着 API 流量增长,您需要能够在不迁移服务器的情况下升级 CPU、RAM 和带宽。

可靠的正常运行时间——99.9% 以上的正常运行时间 SLA 是生产 API 的最低要求。

对于大多数 API 工作负载,VPS 托管方案提供了性能、控制和成本之间的理想平衡。您可以获得专用资源、完整 root 访问权限,以及按需配置环境的能力。对于计算需求高、要求最大性能的高流量 API,独立服务器完全消除了资源争用,提供最稳定的最高性能。

如果您的 API 为带有控制面板的 Web 应用提供服务,带 cPanel 的 VPS 可以在保留 VPS 环境性能优势的同时简化服务器管理。

部署 Node.js REST API:快速入门

以下是使用 Express 的最小化但面向生产的 Node.js REST API 设置:

安装依赖:

npm init -y
npm install express helmet cors express-rate-limit dotenv

server.js

const express = require('express');
const helmet = require('helmet');
const cors = require('cors');
const rateLimit = require('express-rate-limit');
require('dotenv').config();

const app = express();

// Security middleware
app.use(helmet());
app.use(cors({
  origin: process.env.ALLOWED_ORIGIN || 'https://yourapp.com',
  methods: ['GET', 'POST', 'PUT', 'PATCH', 'DELETE'],
  allowedHeaders: ['Authorization', 'Content-Type']
}));

// Rate limiting
const limiter = rateLimit({
  windowMs: 15 * 60 * 1000, // 15 minutes
  max: 100,                  // 100 requests per window
  standardHeaders: true,
  legacyHeaders: false,
  message: { error: 'Too many requests. Please try again later.' }
});
app.use('/api/', limiter);

// Body parsing
app.use(express.json({ limit: '10kb' }));

// Sample resource: posts
const posts = [
  { id: 1, title: 'Understanding REST APIs', author: 'Jane Doe' },
  { id: 2, title: 'Building Scalable APIs', author: 'John Smith' }
];

// Routes
app.get('/api/v1/posts', (req, res) => {
  res.status(200).json({ status: 'success', data: posts });
});

app.get('/api/v1/posts/:id', (req, res) => {
  const post = posts.find(p => p.id === parseInt(req.params.id));
  if (!post) {
    return res.status(404).json({
      error: { code: 'RESOURCE_NOT_FOUND', message: `Post with ID ${req.params.id} not found.` }
    });
  }
  res.status(200).json({ status: 'success', data: post });
});

app.post('/api/v1/posts', (req, res) => {
  const { title, author } = req.body;
  if (!title || !author) {
    return res.status(400).json({
      error: { code: 'VALIDATION_ERROR', message: 'Title and author are required.' }
    });
  }
  const newPost = { id: posts.length + 1, title, author };
  posts.push(newPost);
  res.status(201).json({ status: 'success', data: newPost });
});

app.delete('/api/v1/posts/:id', (req, res) => {
  const index = posts.findIndex(p => p.id === parseInt(req.params.id));
  if (index === -1) {
    return res.status(404).json({
      error: { code: 'RESOURCE_NOT_FOUND', message: `Post with ID ${req.params.id} not found.` }
    });
  }
  posts.splice(index, 1);
  res.status(204).send();
});

// 404 handler for undefined routes
app.use('*', (req, res) => {
  res.status(404).json({ error: { code: 'ENDPOINT_NOT_FOUND', message: 'This endpoint does not exist.' } });
});

const PORT = process.env.PORT || 3000;
app.listen(PORT, () => console.log(`API server running on port ${PORT}`));

使用 PM2 进行生产进程管理并运行:

npm install -g pm2
pm2 start server.js --name "rest-api"
pm2 startup
pm2 save

将 Nginx 配置为反向代理

在 Node.js API 前面部署 Nginx,以处理 SSL 终止、压缩和请求缓冲:

server {
    listen 80;
    server_name api.yourdomain.com;
    return 301 https://$server_name$request_uri;
}

server {
    listen 443 ssl http2;
    server_name api.yourdomain.com;

    ssl_certificate /etc/letsencrypt/live/api.yourdomain.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/api.yourdomain.com/privkey.pem;
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers ECDHE-RSA-AES256-GCM-SHA512:DHE-RSA-AES256-GCM-SHA512;

    gzip on;
    gzip_types application/json;

    location /api/ {
        proxy_pass http://localhost:3000;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection 'upgrade';
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_cache_bypass $http_upgrade;
    }
}

使用 OpenAPI 和 Swagger 为您的 REST API 编写文档

良好的文档不是奢侈品——对于任何面向其他开发者的 API 来说,它是必要条件。OpenAPI 规范(前身为 Swagger)是以机器可读格式描述 REST API 的行业标准。

我们博客文章 API 的最小 OpenAPI 3.0 规范:

openapi: 3.0.3
info:
  title: Blog Posts API
  description: A REST API for managing blog posts
  version: 1.0.0
servers:
  - url: https://api.yourdomain.com/api/v1
paths:
  /posts:
    get:
      summary: Retrieve all posts
      security:
        - bearerAuth: []
      responses:
        '200':
          description: A list of blog posts
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/Post'
    post:
      summary: Create a new post
      security:
        - bearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/NewPost'
      responses:
        '201':
          description: Post created successfully
components:
  schemas:
    Post:
      type: object
      properties:
        id:
          type: integer
        title:
          type: string
        author:
          type: string
    NewPost:
      type: object
      required: [title, author]
      properties:
        title:
          type: string
        author:
          type: string
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT

使用 Swagger UI 提供此规范,为开发者提供基于浏览器的交互式 API 浏览器,他们可以在其中阅读文档并发起实时测试请求。

REST API 常见问题解答

REST 和 RESTful 有什么区别?

REST 是架构风格;RESTful 描述符合 REST 原则的 API。这两个术语在实践中通常可以互换使用。

REST 和 HTTP 是同一回事吗?

不是。REST 是一种使用 HTTP 作为传输协议的架构风格。HTTP 是底层通信协议;REST 定义了如何使用它。

PUT 和 PATCH 有什么区别?

PUT 用请求体中提供的数据替换整个资源。PATCH 执行部分更新,仅修改指定的字段。当您只需要更新一两个字段时,使用 PATCH 可避免意外清除其他字段。

我应该使用 REST 还是 GraphQL?

对于大多数标准 CRUD API、公共 API 以及注重简洁性和广泛兼容性的应用程序,REST 是更好的选择。当客户端需要查询复杂的互联数据图,并希望在单个请求中精确指定所需字段时,GraphQL 更具优势。

如何处理 API 版本控制?

最常见的方法是 URL 路径版本控制(/v1//v2/)。您也可以使用请求头(Accept: application/vnd.api+json;version=2)或查询参数(?version=2),但 URL 版本控制最为直观且最易于实现。

结语:自信地构建和部署 REST API

REST API 是现代 Web 的连接组织。无论您是在构建简单的博客后端、复杂的电商平台,还是服务数百万用户的微服务架构,掌握 REST API 的设计和部署都是贯穿整个职业生涯的基础技能。

总结我们所涵盖的内容:

  • REST 是基于 HTTP 的无状态客户端-服务器架构风格
  • HTTP 方法(GET、POST、PUT、PATCH、DELETE)映射到资源上的 CRUD 操作
  • 状态码传达每个请求的结果
  • 安全需要 HTTPS、身份验证、速率限制和输入验证
  • 良好的设计意味着一致的命名、版本控制、适当的错误处理和完善的文档

在生产环境中托管 REST API 时,基础设施质量直接影响性能、可靠性和安全性。VPS 托管提供您的 API 在负载下快速响应所需的专用资源、完整 root 访问权限和 NVMe 存储支持。对于要求最高性能和零资源争用的企业级工作负载,独立服务器是正确的选择。别忘了使用受信任的 SSL 证书保护每个 API 端点——对于任何处理真实用户数据的生产 API 而言,加密连接是不可妥协的要求。

开始构建。自信部署。连接世界。

15%

全场主机优惠15%

测试技能,享折扣

使用代码:

Skills
开始使用