怎么设计 REST 资源的 URL

原文链接:How to Design URL to REST Resource - 原文作者:Ramesh Fadatare
本文采用意译的方式

本文,我们将学习怎么设计 REST API 资源的 URL,并且了解设计一个 URL 资源的最佳实践。最后,我们将以真实的案例来实践学习。

怎么设计 REST 资源的 URL

我们通过案例来深入讨论。

基本上, URL 被分配给提取的资源以便来识别它。我们推荐使用下面的 URL 格式。

bash 复制代码
http(s)://{Domain name (:Port number)}/{A value indicating REST API}/{API version}/{path for identifying a resource}
bash 复制代码
http(s)://{Domain name indicating REST API(:Port number)}/{API version}/{path for identifying a resource}

典型的例子如下:

bash 复制代码
http://example.com/api/v1/members/M000000001
http://api.example.com/v1/members/M000000001

我们拆分 URL 并深入讨论下。

分配 URL,其指示 APIREST API

推荐 URL 域名或者路径包含 API 关键字,来清晰地指示改 URL 是为了 RESTful Web Service (REST API)的。典型,如下 URL

bash 复制代码
http://example.com/api/...
http://api.example.com/...

分配 URL,识别 API 版本

我们可以通过在 URL 上添加版本号来进行版本控制。在引入非向后兼容的更改时特别有用。

典型的,URL 中版本控制如下:

bash 复制代码
http://example.com/api/{API version}/{path for identifying a resource}
http://api.example.com/{API version}/{path for identifying a resource}

分配路径来识别资源

RESTful URIs 中不应该有动词在里面。该操作应该从 HTTP 方法(GET, POST, PUT, DELETE, etc.)推断出来,比如:

  • GET /orders - 获取订单列表
  • POST /orders - 新增一条订单

你应该避免如下写法:

  • /getOrders
  • /createOrder

使用相关的子资源:如果一个资源关联另外一个资源,你可以使用子资源:

  • /users/123/orders - 获取用户 ID123 的订单列表

使用 RESTful URL 设计的备忘录

1. 使用名词,而非动词

bash 复制代码
✅ /users
❌ /getUser

2. 频繁使用复数名词

bash 复制代码
✅ /books
❌ /book

3. 避免 CURD 术语

bash 复制代码
✅ GET /orders (该接口获取订单)
❌ /getAllOrders

4. 使用 ID 识别唯一资源

bash 复制代码
✅ /employees/45 (ID 为 45 的员工)
❌ /employees?employeeId=45

5.嵌套关系的子资源

bash 复制代码
✅ /departments/3/employees (部门 ID 为 3 的员工)
❌ /employeesInDepartment/3

6. 过滤,排序和分页时使用查询参数

bash 复制代码
✅ /books?author=Rowling&sort=title
❌ /booksByRowlingSortedByTitle

7. 实施版本控制(可选的,但是很有用)

bash 复制代码
✅ /v1/products
❌ /productsVersion1

8. 保持命名一致的约定

命名要么全使用驼峰式(/userGroups),要么全使用下划线格式(/user_groups),别混合着使用。

9. 坚持标准的 HTTP 方法

正确做法✅👇

  • POST 是创建
  • GET 是读取
  • PUT 是更新(或者创建)
  • DELETE 是删除

10. 使用 HTTP 状态码来指示结果

正确做法✅👇

  • 200OK
  • 201 是创建
  • 400 是错误的请求
  • 404 是资源找不到
  • 等等

案例学习 1

我们来到实战,设计 REST APIURL。以有一些员工的公司为例,我们编写一些 APIs/getAllEmployees 是一个代表员工列表的 API。其他的 API 如下:

  • /addNewEmployee
  • /updateEmployee
  • /deleteEmployee
  • /deleteAllEmployees
  • /promoteEmployee
  • /promoteAllEmployees

并且,还会有大量类似的其他 API 端用于不同的操作。其中的很多都是很冗余的操作。因此,当 API 的数量增加时,所有的 API 端点的维护变得越来越繁重。

这有什么问题?

之前说过,URL 应该只包含资源(名词),而不应该包含动作或者动词/addNewEmployee 含有资源 Employee,但是包含了动作 addNew

正确应该是怎样?

/companies 的端点是个很不错的例子,其不包含动作。但是,问题是,我们怎么告诉服务器要关于公司 companies 执行的资源操作呢,不管是否添加、删除或更新?

HTTP 方法 GET, POST, DELETE, PUT 派上用场,这些方法也称为动词。

API 端点,资源应该总是复数名词,如果我们想获取其中一个资源,我们可以通过 IDURL 传参。

  • GET 路径 /companies 表示获取公司的列表
  • GET 路径 /companies/34 表示获取 id34 的公司信息
  • DELETE 路径 /companies/34 表示删除 id34 的公司

在其他的用例中,资源下面又有资源,比如 Company 下有 Employees,那么。一些 API 端点的案例如下:

  • GET 路径 /companies/3/employees 表示 id3 的公司下的员工列表
  • GET 路径 /companies/3/employees/45 表示 id3 的公司下员工 id45 的信息
  • DELETE 路径 /companies/3/employees/45 表示删除 id3 的公司下 id45 的员工
  • POST 路径 /companies 表示创建一个新公司,并返回创建的公司信息

案例学习 2

我们来练习下怎么从域名信息中提取不同的资源编写 URL。我们以 HelpDesk 应用程序的消息和票证为例。

如果一个资源和另一个资源相关,RESTful 原则提供了不错的指导。信息可以以 /tickets 端点为逻辑展开,如下:

  • GET /tickets/12/messages - 获取 #12 票证的所有信息
  • GET /tickets/12/messsages/5 - 获取 #12 票证的 #5 信息
  • POST /tickets/12/messages - 在 #12 票证中创建信息
  • PUT /tickets/12/messages/5 - 更新 #12 票证的 #5 信息
  • PATCH /tickets/12/messages/5 - 更新 #12 票证的 #5 信息的部分内容
  • DELETE /tickets/12/messages/5 - 删除 #12 票证的 #5 信息

案例学习 3

下面是来自 twitter API 文档。

策划推文集合

  • GET collections/entries
  • GET collections/list
  • GET collections/show
  • POST collections/create
  • POST collections/destroy
  • POST collections/entries/add
  • POST collections/entries/curate
  • POST collections/entries/move
  • POST collections/entries/remove
  • POST collections/update

查看一些广泛使用的 API 以掌握窍门,并与队友完善 API 资源 URL。一些 APIs 如下👇

总结

在这篇文章中,我们学习了怎么设计有效的 URL,来指明网络中独特的资源。

相关推荐
夜半被帅醒2 分钟前
MySQL 数据库优化详解【Java数据库调优】
java·数据库·mysql
万亿少女的梦1688 分钟前
基于Spring Boot的网络购物商城的设计与实现
java·spring boot·后端
潜意识起点15 分钟前
精通 CSS 阴影效果:从基础到高级应用
前端·css
奋斗吧程序媛20 分钟前
删除VSCode上 origin/分支名,但GitLab上实际上不存在的分支
前端·vscode
IT女孩儿30 分钟前
JavaScript--WebAPI查缺补漏(二)
开发语言·前端·javascript·html·ecmascript
醒了就刷牙36 分钟前
黑马Java面试教程_P9_MySQL
java·mysql·面试
m0_7482336442 分钟前
SQL数组常用函数记录(Map篇)
java·数据库·sql
编程爱好者熊浪2 小时前
JAVA HTTP压缩数据
java
吴冰_hogan2 小时前
JVM(Java虚拟机)的组成部分详解
java·开发语言·jvm
开心工作室_kaic2 小时前
springboot485基于springboot的宠物健康顾问系统(论文+源码)_kaic
spring boot·后端·宠物