REST API 设计
动机
本文主要针对后端开发人员而写,他们正在寻找一些“如何”设计 REST API 的实际示例,以便为其他开发人员和 API 消费者提供参考。
端点路径的剖析
HTTP 方法
每个端点都属于 HTTP 方法。这些方法使开发人员和用户能够基本了解对该路径上的资源执行的“操作”。需要为每个端点使用正确的 HTTP 方法。以下列出的每个方法的详细信息可在RFC2616中找到:
GET
如果端点返回有关给定资源的信息(“列出项”、“获取 ID=5 的项”、“获取 ID=5 的项的所有子项”等) ,则应使用;POST
如果端点在请求期间创建资源或以某种方式改变资源的状态(“创建新项目”,“执行身份验证”) ,则应使用;PUT
用于需要用更新版本完全替换资源的情况。它主要用于更新操作(“更新项目”);PATCH
类似于PUT
但主要用于当您想要指示资源可以部分更新时(“将用户状态更改为活动状态”,“授予用户权限/访问权限”);DELETE
顾名思义,它表示端点执行资源删除(“删除项目”、“删除所有项目”);
其他 HTTPS 方法不太常用,您可能知道是否需要使用它们。
端点路径
我们已经知道,HTTP 方法是一个动词,因此要描述端点路径,我们需要使用名词(换句话说,“域名”)。
例如,要创建用户,我们这样写:
POST /users // GOOD
POST /create-user // BAD
我们已经指定了POST
一种方法,所以我们知道“它将创建一个用户”。
更新用户状态的另一个示例:
PATCH /users/status // GOOD
PATCH /users/set-status // BAD do not use verbs in paths
PUT /users/status // BAD use proper HTTP method
大多数情况下,您将面临带有一些附加端点的 CRUD 路线,以便与子实体协同工作:
GET /users // Get list of users
GET /users/${userID} // Get single user details
POST /users // Create a new user
PUT /users/${userID} // Update user
DELETE /users/${userID} // Delete user
PATCH /users/access // Partly update user
GET /users/${userID}/photos // Get sub-entity
POST /users/${userID}/photos // Create sub-entity
DELETE /users/${userID}/photos/${photoID} // Delete sub-entity
查询参数
通常您需要为分页或服务器提供的某种过滤指定附加参数。
分页
如果您没有在返回项目列表的终端上使用分页功能,那么您应该考虑这样做,因为数据库请求的增长会持续很长时间,并突然阻塞您的服务器或数据库运行。用户也不会愿意为了不想看到的数字项目等待15秒。
带分页的查询字符串示例:
GET /users?page=1&pageSize=25 // "Classic" pagination
GET /users?fromId=1232142 // Cursor pagination
过滤
如果您需要指定一些额外的搜索参数或仅返回特定的实体字段,您还可以将它们添加到查询字符串中并在服务器端进行解析:
GET /users?search=John // Search for user with name John
GET /users?status=active,banned&age=18-21,22-27,40-49 // Return only active or banned users within the specified age groups. If you want to specify few filters you separate them by ","
GET /users?online=2021-12-01,2022-01-01 // Fetch users that were online in range of dates
排序
用户通常希望查看“最近”的项目或更新,但有时他们希望应用其他排序选项:
GET /users?sort=last_online // Sort by last online ASC
GET /users?sort=last_online,status // Sort by 2 fields
GET /users?sort=name&desc=true // Sort by name in descending order
GET /users?sort=+name,-status // Multisort with specifying "+"/"-" as ASC/DESC
响应 HTTP 状态代码
根据请求的结果,服务器应返回适当的状态代码来指示请求是否成功完成或出现错误而无法完成。
对所有端点使用定义的代码集并在响应或文档中提供附加消息也是一种很好的做法。
这些状态代码在RFC 2616、RFC 4918、RFC 6585和其他文件中进行了描述。
大多数情况下,您会使用以下状态代码:
2xx
200 OK
- 仅仅意味着请求已成功执行并且资源可作为响应。201 Created
- 主要用于POST
请求中,表示资源已成功创建并存储在服务器中。204 No Content
- 主要用于DELETE
请求中,表示资源不再存在。
4xx:
400 Bad Request
- 请求不符合验证规则,服务器拒绝处理。可以在响应正文中指定更多错误详情。-401 Unautorized
用户无权使用此端点。大多数情况下,这是一个状态代码,用于用户会话超时或未在授权标头或 Cookie 中提供访问令牌/会话令牌的情况。-403 Forbidden
如果是对登录端点请求的响应,则仅表示“没有具有该用户名和密码组合的用户”或用户无权执行该请求。-404 Not Found
资源不存在或此地址上没有端点。应在响应正文中提供有关错误的附加消息。-409 Conflict
主要用于由于服务器限制(例如,具有指定昵称的用户已存在)而无法执行请求,或者在用户发送请求之前给定实体已被修改的情况。-422 Unprocessable Entity
表示请求模式正确且通过了验证规则,但服务器无法处理该请求或处理该查询。429 Too Many Requests
- 只是意味着用户向服务器发送了太多请求(例如,如果用户在 1 分钟内尝试登录的次数太多)。
5xx
500 Internal Server Error
- 您的服务器应该有一个处理意外错误的处理程序,如果在关闭服务器之前出现问题,则向用户发送响应。
结论
重要的是要按照设计初衷使用,并提供直观易用的界面。
此外,别忘了使用 Swagger 等常用工具来记录你的 API。当你想解释“这个状态码是什么意思”或“如何在这个端点使用过滤器”时,这会很有帮助。只有
亲自动手才能积累经验。掌握了所有基本规则,在遇到一些具体情况之前,你应该不会遇到任何问题。