RESTful API Design: Best Practices for Creating APIs t
作者:禅与计算机程序设计艺术
1.简介
RESTful API(基于表示的状态转移)是一种软件开发的架构风格。它通过客户端与服务器之间的HTTP方法交换数据来实现核心功能。这种架构以其良好的可扩展性和灵活性著称,并且在分布式系统间通信中表现出色。其优势主要体现在以下几个方面:首先,该架构采用标准化协议简化了通信逻辑,从而提高了系统的运行效率;其次,通过一致的状态更新机制保证了系统的可靠性;再次,基于标准协议的设计使得系统的安全性得到了充分保障;此外,该架构支持多种组件之间的灵活集成,从而提升了系统的扩展性;最后,由于采用了标准化设计原则,系统的维护成本显著降低
- 该方案具有便捷性,并且便于掌握使用方法。
- 该方案适用于多样的应用场景包括但不限于移动端终端PC端应用网络网页以及与特定服务交互的网络场景。
- 支持基于 HTTP 方法的 CRUD(Create, Read, Update, Delete)操作流程。
伴随着互联网技术的迅速发展,在过去几年中Web-based 服务日益普及,并且用户对这些服务的需求也不断增长。所有基于 Web 的服务都必须遵循 RESTful 设计规范来构建,在RESTful 设计体系中最关键的是在接口设计阶段需要遵循哪些原则:
- 客户端与服务器应完全分离。
- 所有的会话数据均需零状态处理。
- URI(Uniform Resource Identifier)是唯一的资源标志符。
- 在每次请求中都需要包含缓存控制信息以便在本地缓存数据以减少网络请求次数。
- 支持异步通信机制使得客户端能够发送请求同时还能响应其他客户端发出的请求
本文将围绕以下5个核心原则展开讨论,并结合丰富的实践经验探讨如何遵循RESTful API 标准构建高效的网络接口服务系统。旨在为开发者提供实践参考。
2.核心概念说明
(1)URI
RESTful API 所使用的 URI ,其主要特征如下:
- 唯一标识:每个 URI 为资源提供唯一标识符,避免重复;
- 层级分明:URI 格式中以 "/" 分隔层级结构;
- 操作类型:URI 后缀指示对资源的操作类型(GET、POST 等);
- 资源集合:采用复数名词表示一组相关资源。
例如,一个博客网站 API,它的 URI 可以按下面的方式定义:
GET /posts // 获取所有文章
GET /posts/:id // 根据ID获取单个文章
POST /posts // 创建新文章
PUT /posts/:id // 更新单篇文章
DELETE /posts/:id // 删除单篇文章
代码解读
(2)HTTP Methods
HTTP(HyperText Transfer Protocol)是一种建立在 TCP/IP 协议族之上的协议,并采用多线程技术实现对网络资源的高效管理。该方法通过 Web 服务器将客户端提交的内容解析为网页展示页面,并支持同时处理多个并发请求以及实现异步通信机制。
- GET用于从服务器获取指定的数据或资源。
- POST常用于向目标系统提交请求并创建新的数据或对象。
- PUT则用于对远程存储的数据或对象进行修改、补充或优化。
- DELETE操作通常用于删除远程存储的数据或记录。
- PATCH常被用来对远程对象执行部分更新操作。
为了开发RESTful API ,API 设计者必须严格遵守HTTP和REST标准规范。
(3)CRUD Operations
CRUD操作包括新增(Create)、获取(Retrieve)、修改(Update)和删除(Delete)数据库记录的基本操作。(英文:Create, Retrieve, Update and Delete)RESTful API基于HTTP方法实现了这四种操作,分别采用POST, GET, PUT, DELETE方法。
比如,在博客网站上使用HTTP方法时...
(4)Request Body
Request body 是 HTTP 请求的一部分数据,并用于建立或更新资源的信息。在 RESTful API 中,通常使用 JSON 或 XML 作为数据格式。
3.RESTful API Design Principles
(1)单一职责原则(SRP)
单一职责原则(SRP):该原则表明一个类应仅承担单一职责,在面向对象编程领域被视为SOLID原则之一。
一个类的设计宗旨应当是完成一项核心任务,并且确保精确无误, 以简洁高效著称. 例如, 应当专注于单一职责, 而不是承担多个责任. 它专注于实现基础转换. 验证功能或其他简单功能.
例子 :假设有一个订单模块,包含几个子模块:
- 下单操作:包括生成订单编号、核查商品库存情况以及记录订单信息等具体内容;
- 支付处理:主要涉及配置并准备好多种支付方式、发起并执行支付操作以及处理交易成功的回调;
- 物流配送管理:负责获取并分析物流数据、根据地址自动生成配送路径以及核实配送员的联系方式等环节;
- 收货确认流程:包括更新库存记录、扣除积分奖励以及调整用户数据等多个步骤。
这样的设计可能导致该类过于复杂并难以维护 建议按照职责划分订单模块 并独立开发每个子模块 例如
- OrderService主要处理订单创建及记录相关信息;
- PaymentService主要完成支付方式的选择与配置,并协调相关支付流程;
- DeliveryService则会实时追踪物流动态,并根据配送地址自动生成相应的派送指令;
- ConfirmationService则会及时更新订单状态,并确保库存数据的一致性。同时还会处理用户的积分调整以及账户信息的变更。
这样,单一职责原则更贴近实际业务逻辑,易于管理和维护。
(2)关注点分离原则(CoC)
Coupling Coupling :互相关联的模块必须被拆分以减少耦合度, 否则会导致整个系统变得冗杂.
遵循关注点分离原则,可以把多个模块分散到不同的项目中进行开发;随后采用某种集成机制将它们连接起来。例如 RPC 和 消息队列等。
在电商网站开发过程中, 电商网站中的不同功能模块通常包括订单管理模块、商品管理模块以及搜索功能模块等. 如果未能实现功能分离, 这些功能模块可能会相互影响, 导致系统的高耦合度. 为了实现系统的可扩展性目标, 我们应当将这些功能模块拆分成独立的功能模块, 并通过AOP(面向切面编程)技术和消息传递机制等技术手段进行整合.
(3)简化依赖关系
Simplify Dependencies :不应该存在依赖关系。
当两个模块之间存在依赖关系时,则表示这两个模块之间具有紧密耦合的状态;这种状态违背了关注点分离准则。
为了解决关注点分离的问题,我们可以采用事件总线、共享数据库或微服务架构以消除系统之间的耦合关系。
(4)无状态
Stateless :服务器不存储客户端的状态信息;每次请求都需携带完整的身份认证信息。
零状态的特性直接导致服务端不存储客户端的数据。这种特性常见于基于 RESTful 的 web 服务中,并且也限制了一些特殊场景下的需求。例如:
- 高频访问的数据可被存储至Redis或Memcached中以优化运行效率;
- 首先将数据加载至内存空间并随后通过消息队列实现前端更新。
然而无状态的特性可能导致一些潜在的安全隐患。例如攻击者可能通过 cookie 漏洞获取 session id从而获取敏感信息因此为了防止这些潜在风险可采用 SSL 加密 JWT 加密等方式进行数据传输
(5)统一资源标识符
URI标识符:每个URI代表的是一个资源,并且其具有唯一的标识符。
Unique Uniform Resource Identifiers (URIs) are considered a fundamental concept in the context of resource location. Within the RESTful API framework, URLs must contain sufficient information to be unambiguous, enabling determination of request resource types and positioning.
例如:
GET /users/123 // 查看用户123的详情
PATCH /users/123 // 修改用户123的信息
DELETE /users/123 // 删除用户123
代码解读
4.Design Considerations in Practice
在设计过程中有几个注意事项,在这些过程中有一些事项可以帮助我们按照RESTful遵循API设计标准来构建API。
(1)资源命名
RESTful API 的核心要素就是资源名称标识系统,在这一架构中,必须使用名词来表示各类资源的名称,并且为了标识多个同类资源,则采用复数形式作为它们的名字。
例如以下几种情况:API请求路径包括GET /users/{userId}、GET /orders/{orderId}以及POST /comments等请求方式;而此类API请求路径不包括以下这些情况:如仅支持简单的获取操作如用户端的访问信息等
(2)统一接口风格
RESTful API 有很多的接口风格,它们分别是:
- 基于路径的方式:路径参数用于标识资源。
- 基于查询字符串的方式:请求中的参数通过查询字符串传输。
- 基于表单提交的方式:通过表单上传文件或文本。
- 基于请求头的方式:通常用于指示数据格式及语言。
为了避免混淆,建议统一接口风格,比如使用路径参数的风格。
(3)资源处理器与路由映射
每个 URI 应当明确对应一个具体处理程序,并且该处理程序应具备明确的功能以管理特定类型的数据存储或网络流量
路由映射器能够迅速地定位到对应的处理器,并提供相应的HTTP响应码HTTP200。
例如,下面是一个简单的 Node.js 路由映射器:
const router = require('express').Router();
router.get('/users', getAllUsers);
router.post('/users', createUser);
router.get('/users/:id', getUserById);
router.patch('/users/:id', updateUser);
router.delete('/users/:id', deleteUser);
function getAllUsers() {
return 'This is a response to get all users';
}
function createUser() {
return 'This is a response to create user';
}
function getUserById(req, res) {
const userId = req.params.id;
console.log(`Get user ${userId}`);
if (!isValidId(userId)) {
res.status(404).send('Invalid user ID');
} else {
res.send(`This is the detail of user ${userId}`);
}
}
function updateUser() {
return 'This is a response to update user';
}
function deleteUser() {
return 'This is a response to delete user';
}
function isValidId(id) {
//...
return true;
}
代码解读
(4)统一错误处理
所有RESTful APIs都应该配备一致性的错误处理机制以便让API调用者迅速识别问题
一个典型的错误处理机制,可以参照 HTTP 协议中的状态码,比如:
- 400 Bad Request:表示请求出现语法错误或无法被满足;
- 401 Unauthorized:表示当前请求需要用户认证;
- 403 Forbidden:表示服务器理解请求但是拒绝执行;
- 404 Not Found:表示请求失败的原因是资源不存在;
- 405 Method Not Allowed:表示请求行中的方法被禁止;
- 409 Conflict:表示请求与资源的当前状态冲突;
- 500 Internal Server Error:表示服务器内部发生了错误;
- 503 Service Unavailable:表示服务器超载或停机维护暂时无法处理请求。
(5)版本控制
版本控制可以让 API 更好地适应变化,并兼顾兼容性和演进。
RESTful API 可以通过 URI 的前缀来表示版本,比如 /v1/users、v2/users。
(6)分页与排序
RESTful API 通常会使用 URI 参数的方式来实现分页和排序等功能;使用的参数包括 limit、offset 和 sort 等。
例如,GET /users?page=2&size=10、GET /users?sort=age,-created_at。
(7)缓存机制
RESTful API 采用 Cache-Control 标签或自定义缓存头来配置缓存机制,在制定缓存策略时应当综合考虑数据敏感性、更新频率及实时度等多个关键因素
(8)身份认证与授权
身份认证和授权是保证 RESTful API 安全的关键环节。
身份认证是指客户端如何验证其身份信息以完成验证流程,在线服务通常会依据该过程来确认用户的合法性;而权限授予则指的是在用户获得许可后系统是否会赋予相应的操作权限确保其能完成指定的任务。
通常情况下,身份认证可采用OAuth 2.0、JSON Web Tokens(JWT)等多种技术手段进行操作;而权限管理则主要依赖于基于访问控制列表(ACL)和基于角色的访问控制(RBAC)等方法来实现。
(9)测试用例
RESTful APIs 应具备全面且详尽的测试用例,并以此为基础确保其兼容性、准确性和可靠性。
5.未来发展方向
RESTful APIs 被视为构建现代 Web 应用程序的关键组件。
随着云计算的演进、移动互联网的增长以及 WebAssembly 的普及趋势日益明显,
RESTful APIs 正在迈向下一代。
需要注意的是,在RESTful API体系中存在许多潜在的优势和特点。只要遵循相应的规范,并且采用合适的技术手段,在方便灵活地应用于各种场合时会更加高效。
如今,在开发过程中使用RESTful API时有多个不同种类的开源解决方案可用,并且这些解决方案都已经成为了实现RESTful API的最佳实践
与此同时,在伴随着前端技术的革新过程中(...),浏览器正逐步迈向更加智能化的方向(富交互)。这一趋势使得越来越多的传统Web应用开始向移动端迁移(部署到浏览器中运行)。与此同时,在移动互联网快速发展的背景下(...),移动端Web应用正逐渐兴起(并成为主流趋势)。在这过程中(...),越来越多原本采用RESTful API进行服务通信的应用程序开始转向移动设备平台(即RESTful API将被广泛部署在移动端平台上)。
未来 RESTful APIs的发展进程中,我们有理由期待其能够持续跟进Web技术的趋势,并不断提升性能和用户体验;同时进一步探索新兴技术和应用场景。
