什么是 RESTful API?从日常生活理解 REST 架构原理
2025年9月5日
我们每天的生活中,都会与数十甚至上百个网路服务互动,而在用不同的 App 的过程中,多数人可能没有意识到,自己在用的 App 背后正悄悄地与其他系统对话。事实上,如果 App 没有跟背后的系统沟通,我们将会无法拿到最新的资讯。但 App 是如何跟背后的系统沟通呢? 天气 App 如何取得即时资料?社群媒体的 App 拿到最新贴文?
在现代的应用程式开发中,这些之所以能够发生,是因为背后有 API 这个关键要素。而在众多的 API 撰写方式中,有一个特别热门的 REST 原则。理解 REST 是对前端与后端工程师来说,都必须要掌握的基本。在这篇文章中,我们将探讨什么是具有 REST 风格的 API (俗称 RESTful API),让读者能掌握 RESTful API 的基本原则。
什么是 API?
在谈 RESTful API 之前,先让我们回顾一下什么是 API。让我们用餐厅点餐来比喻,当今天到了某间餐厅,相信多数人不会直接走进厨房跟厨师说要做什么菜、怎么做,而是会透过服务生点餐。告诉服务生自己想要什么,服务生就会为我们送上餐点。在这个过程中,我们不需要知道厨房如何运作、使用的食材如何进口,只需要表达自己要什么菜 (例如「我要一份蛋炒饭」)。
API(Application Programming Interface,应用程式介面)的运作方式就像餐厅中的服务生。它是应用程式和其他系统之间的沟通桥梁,就像服务生是你与餐厅之间的桥梁。当 App 需要取得资料,例如使用者资讯、天气资料、社群贴文,就会向 API 发出请求 (这就像跟服务生点餐一样),而 API 负责取得资料并回传结果 (这就像服务生送餐来一样)。
举例来说,天气 App 本身不会在手机中存下全世界所有地方的天气资料,而是向气象服务的 API 查询「台北现在的气温是几度?」,API 回传资料后 App 再显示给使用者看。
API 如果没有统一规格会怎么样?
在理解什么是 API 后,接着让我们来谈实际在前后端开发的具体例子。假设今天要开发一个要跟 GitHub 沟通的 App,我们需要取得使用者资讯、建立专案库、管理议题。
这个 App 应该如何与 GitHub 的伺服器沟通? 要能跟 GitHub 的伺服器沟通,就要按照 GitHub 订定 API 的方式来拿资料。这时问题来了,如果这个 App 要串接其他服务的 API,这时如果不同公司的规范不同,使用不同的指令格式、回传不同的资料格式、用不同的方式处理错误。这就会导致开发者需要为每个服务学习不同的使用方式。
由于现在的 App 背后很可能同时串接各类不同服务,假如每一种的形式都不同,对开发者来说会非常困扰。而 REST 解决了这个问题。REST 提供的基本结构和规则,让所有 API 都有一致的使用方式,开发者学会 REST 的风格后,就能应用到其他 API 的开发与使用上。
什么是 REST?
具体来说,REST 是指 Representational State Transfer(表征状态转移),是 Roy Fielding 在 2000 年提出的概念。虽然名字听起来很复杂,但它其实是一套让 API 统一运作的简单规则。
就像交通号志在全世界都有相同意义(红灯停、绿灯行),REST 为 API 的运作方式提供了通用规范。这样所有开发者都能用相同的逻辑来设计和使用 API。而符合 REST 规范的 API 又会被称为 RESTful API,以下的六个核心原则,是 RESTful API 共用的特征。
REST 的六个核心原则
1. 统一介面 (Uniform Interface)
统一介面 (Uniform Interface) 是指所有 API 都要用一致的方式来设计。以 GitHub API 为例:
GET /users/explainthis # 取得使用者资讯
GET /users/explainthis/repos # 取得使用者的专案库
POST /user/repos # 建立新的专案库
PATCH /repos/explainthis/Hello-World # 更新专案库
DELETE /repos/explainthis/Hello-World # 删除专案库
相信大家能从上面这几个不同的 API 看出其中共有的规律,在 RESTful API 中,会有 URL 说明你要操作的资源 (例如 /users/explainthis
),同时搭配 HTTP 方法(GET、POST、PATCH、DELETE)说明你要做什么动作。
这些不同的 HTTP 方法分别代表:
- GET:取得资源(「给我看看某个东西」)
- POST:建立新资源(「帮我建立一个新的东西」)
- PATCH:部分更新资源(「帮我修改某个东西的部分内容」)
- DELETE:删除资源(「帮我删除某个东西」)
这些方法就像是我们在日常生活中的动作,GET 像「查看」,POST 像「新增」,PATCH 像「修改」,DELETE 像「删除」。透过这样的规范,要串接 API 的开发者,就能够一眼看出某个 API 是做什么用的。
2. 无状态 (Stateless)
无状态 (Stateless) 代表每个请求都包含伺服器处理所需的所有资讯,换句话说伺服器不会帮忙「记住」之前的请求。
你可能会问「无状态有什么好处?」,假设你有 10 台伺服器。无状态设计下,任何伺服器都能处理任何请求。但有状态设计下,小明的所有请求都要去找同一台伺服器。
这会造成如果某台伺服器当机,那台伺服器负责的特定使用者,就会被影响,因为其他台伺服器无法帮忙处理;同时,也可能会有某台伺服器超载时,其他伺服器却可能闲置 (同样地,因为没办法帮忙处理请求)。无状态设计让每个请求都独立且完整,任何伺服器都能处理。这让系统更好扩展,也更容易维护。
3. 客户端-伺服器分离 (Client-Server Separation)
客户端-伺服器分离 (Client-Server Separation) 的好处在于,客户端 (App) 和伺服器 (API) 完全独立。更新 App 不需要改伺服器,更新伺服器也不需要改 App。
因为没有互相绑死,要扩展也容易。以 GitHub 为例,同样地 API,可以用在网页、手机 App、桌面 App;假如伺服器跟客户端绑死,要支援不同的客户端,就要开发不同的 API,会让开发成本上升不少。
4. 可快取(Cacheable)
伺服器回应要明确说明资料可不可以快取,以及快取多久。下面这段,就像伺服器端对客户端说「这个资料在 1 小时 (3600 秒) 内都有效,这段时间内不用再向我请求。」。
HTTP/1.1 200 OK
Cache-Control: max-age=3600
Content-Type: application/json
{"name": "GitHub 使用者指南", "updated_at": "2023-01-15T10:30:00Z"}
当能够快取,伺服器整体回应速度就会变快,因为在快取仍有效的期间,不需用再去重复请求;因为不用重复请求,这对伺服器端的负担也能减少。
5. 分层系统(Layered System)
系统是分层的,每一层只需要知道直接下方的那一层。你不需要知道背后有多少台伺服器。
当你呼叫 api.github.com
时,请求可能会经过:
- 负载平衡器(分散流量)
- 快取伺服器(储存常用资料)
- 认证服务(验证身份)
- 资料库伺服器(储存资料)
每一层负责自己的事情,然后把请求传给下一层。你只需要对一个 URL 发出请求,其他的都交给分层系统处理。
这种分层架构的好处在于让整个系统变得更加灵活和可靠。当某一层出现问题时,其他层不会受到影响。同时,每一层都可以根据需要进行优化或扩展,例如在流量增加时增加更多负载平衡器,或是在快取伺服器容量不足时增加新的快取节点。对于开发者来说,这种设计让 API 的使用变得非常简单,不需要了解背后复杂的架构细节,只要知道一个统一的入口点就能存取所有功能。
6. 按需编码(Code on Demand)(可选)
伺服器可以传送程式码给客户端执行。最常见的例子就是当你浏览网页时,伺服器会传送 HTML、CSS 和 JavaScript 给你的浏览器,浏览器接收到这些程式码后就在浏览器中执行,产生使用者看到的网页效果。
这种做法的好处是让系统更有弹性,伺服器可以根据不同情况传送不同的程式码,而不需要预先在客户端安装所有可能用到的功能。不过在一般的 RESTful API 设计中,这个原则被标记为「可选」,因为大多数 API 只需要传送资料就足够。
具体来说,什么样的 API 算 RESTful?
在了解完 REST 的核心原则后,让我们用 GitHub API 为例,来看看这些原则在实务上如何应用:
首先,API 用资源导向的 URL,像下面这样
/users/123 # 使用者 123 的资源
/users/123/repositories # 使用者 123 的所有专案库
/repositories/456 # 专案库 456 的资源
/repositories/456/issues # 专案库 456 中的所有议题
接着,每个 API 的 HTTP 方法都明确定义,让人能一眼看出其功能为何
GET /users/123 # 取得使用者资料
POST /users # 建立新使用者
PUT /users/123 # 完整更新使用者资料
PATCH /users/123 # 部分更新使用者资料
DELETE /users/123 # 删除使用者
最后,所有 API 回应都有相同的格式:
{
"id": 583231,
"login": "octocat",
"avatar_url": "https://github.com/images/error/octocat_happy.gif",
"type": "User",
"created_at": "2011-01-25T18:44:36Z"
}
在这样的设计下,每支 API 的回应都是干净可预测的。如前面谈到,这种一致性让开发者不需要为每个 API 学习不同的使用方式,因为所有 RESTful API 都遵循相同的规范。当你熟悉了一个 RESTful API 的使用方式后,你就能快速上手其他遵循 REST 原则的 API。这不仅降低了学习成本,也减少了开发与维护的时间,让团队能更专注于业务逻辑的实现,而不是花时间适应各种不同的 API 格式。
HTTP 状态码的重要性
在 RESTful API 中,沟通不只是单纯的资料交换。除了回传你要的资料,伺服器还会透过 HTTP 状态码告诉客户端处理结果如何。这些状态码就像是一套通用的沟通语言,让 API 能够清楚表达「请求成功了」、「资料格式有问题」、「你没有权限」或「伺服器出错了」等不同情况。对开发者来说,这些标准化的状态码让错误处理变得更简单,因为开发者可以根据不同的状态码采取对应的处理方式,而不用猜测到底发生了什么问题。
以下是常见的 HTTP 状态码:
成功(2xx)
- 200 OK:请求成功,这就是你要的资料
- 201 Created:新资源建立成功
- 204 No Content:请求成功,但没有资料返回
客户端错误(4xx)
- 400 Bad Request:请求格式有问题
- 401 Unauthorized:需要先登入认证
- 403 Forbidden:已登入但没有权限
- 404 Not Found:找不到资源
- 409 Conflict:资源冲突或已存在
伺服器错误(5xx)
- 500 Internal Server Error:伺服器内部出错
- 503 Service Unavailable:伺服器暂时无法使用
总结
希望透过这篇文章,让读者们有更了解 RESTful API 是什么。REST 不是单纯的技术规格,而是一种系统沟通的思维方式。遵循 REST 原则能建立可预测、可扩展且易于使用的 API。
推荐读者们,如果想要更了解 RESTful,可以在未来使用不同 API 时,用上面提到的原则,来检视该 API 有多 RESTful,例如 URL 设计清楚吗?HTTP 方法用得合理吗?回应格式一致吗?理解这些模式也会让你成为更好的开发者。
加入 E+ 成长计划
如果你觉得这篇内容有帮助,喜欢我们的内容,欢迎加入 ExplainThis 筹办的 E+ 成长计划,透过每周的深度主题文,以及技术讨论社群,让读者在前端、后端、软体工程的领域上持续成长。