Appearance
REST 快速提示
IMPORTANT
无论它是否严格符合REST(根据前面提到的六大约束),以下是一些推荐的REST风格概念。这六个快速提示将帮助你构建更好、更易用的服务。
使用HTTP方法使请求更有意义
TIP
API消费者可以发送GET、POST、PUT、PATCH和DELETE方法(或动词),这大大增强了请求的清晰度。
因此,建议在URL中不要出现动词(行动词)。相反,应利用HTTP方法来提供动词。
通常,五种主要的HTTP方法使用如下:
方法 | 描述 |
---|---|
GET | 读取特定资源(通过标识符)或资源集合。 |
PUT | 替换特定资源(通过标识符)或资源集合。如果在事先已知资源标识符的情况下,也可用于创建特定资源。 |
PATCH | 更新特定资源(通过标识符)或资源集合。这可以被认为是“部分更新”,与PUT执行的替换操作不同。 |
DELETE | 删除特定资源,通过标识符进行。 |
POST | 创建新资源。也是用于不适合其他类别的操作的通用动词。 |
CAUTION
GET 请求不得更改任何底层资源数据。虽然可以进行度量和跟踪来更新数据,但由 URI 标识的资源不得发生更改。
提供合理的资源名称
TIP
制作一个出色的API是80%的艺术和20%的科学。创建一个表示合理资源的URL层次结构是艺术部分。拥有合理的资源名称(例如 /customers/12345/orders)能够提高请求的清晰度。由于人类需要理解API,这种清晰度非常重要。
适当的资源名称为服务请求提供了上下文,增加了API的可理解性。通过URI名称,资源以层次结构的方式呈现,为消费者提供了一个友好且易于理解的资源层次结构,便于他们在应用中使用。
以下是一些快速的URL路径(资源名称)设计规则:
在URL中使用标识符,而不是查询字符串中的参数。使用URL查询字符串参数非常适合过滤,但不适合资源名称。
- 好的:
/users/12345
- 不好的:
/api?type=user&id=23
- 好的:
利用URL的层次结构来暗示结构。
为您的客户端设计,而不是为您的数据设计。
资源名称应该是名词。避免使用动词作为资源名称,以提高清晰度。使用HTTP方法来指定请求的动词部分。
在URL段中使用复数形式,以保持API URI在所有HTTP方法中的一致性,采用集合的隐喻。
- 推荐:
/customers/33245/orders/8769/lineitems/1
- 不推荐:
/customer/33245/order/8769/lineitem/1
- 推荐:
避免在URL中使用集合表述。例如,避免使用‘customer_list’作为资源。使用复数形式来表示集合隐喻(例如,customers 而不是 customer_list)。
在URL段中使用小写字母,单词之间用下划线('_')或破折号('-')分隔。有些服务器会忽略大小写,所以最好明确清晰。
保持URL尽可能简短,段数尽量少且有意义。
使用HTTP响应代码来指示状态
响应状态代码是HTTP规范的一部分,它们涵盖了大多数常见情况。为了让我们的RESTful服务遵循HTTP规范,我们的Web API应该返回相关的HTTP状态代码。例如,当资源成功创建时(例如通过POST请求),API应该返回HTTP状态代码201。有效的HTTP状态代码列表可以在此处查看,详细描述了每个状态代码的含义。
以下是“前10名”HTTP响应状态代码的建议用法:
状态码 | 描述 |
---|---|
200 OK | 一般的成功状态码,这是最常见的代码。用于表示成功。 |
201 CREATED | 成功创建资源(通过POST或PUT)。设置Location头,包含指向新创建资源的链接(对于POST)。响应体内容可能有也可能没有。 |
204 NO CONTENT | 表示成功,但响应体为空,通常用于DELETE和PUT操作。 |
400 BAD REQUEST | 一般错误,表示执行请求会导致无效状态。例如,域验证错误、缺少数据等。 |
401 UNAUTHORIZED | 鉴权失败,缺失或无效的认证令牌。 |
403 FORBIDDEN | 错误代码,表示用户无权执行操作或资源由于某些原因不可用(如时间限制等)。 |
404 NOT FOUND | 当请求的资源未找到时使用,不管是不存在还是由于401或403,出于安全原因,服务想要隐藏此信息。 |
405 METHOD NOT ALLOWED | 表示请求的URL存在,但请求的HTTP方法不适用。例如,POST /users/12345,但API不支持这种方式创建资源(提供ID)。返回405时,必须设置Allow HTTP头,指示支持的HTTP方法。例如,允许的方法头为“Allow: GET, PUT, DELETE”。 |
409 CONFLICT | 当执行请求会导致资源冲突时。例如,尝试创建两个具有相同信息的客户,或在不支持级联删除时删除根对象。 |
500 INTERNAL SERVER ERROR | 永远不应故意返回此错误。表示服务器端抛出了异常的通用错误代码。仅用于客户端无法解决的问题。 |
支持JSON
除非您所在的是一个高度标准化和受监管的行业,要求使用XML、模式验证和命名空间,否则应优先支持JSON。如果必须同时提供JSON和XML,请让消费者通过HTTP的Accept
头在两种格式之间切换:application/json
或 application/xml
。
请注意,一旦开始讨论XML支持,就涉及到模式验证、命名空间等问题,并且测试范围会大大增加。除非行业要求,否则不建议一开始就支持这些复杂性,甚至永远不支持。JSON的设计是简单的,简洁而实用的。
创建细粒度资源
在开始时,最好创建模拟系统底层应用程序领域或数据库架构的API。最终,您可能需要聚合服务,利用多个底层资源来减少冗余通信。然而,从单个资源创建更大的资源比从较大的聚合中创建细粒度或单个资源要容易得多。为了简化设计,您可以从小而易于定义的资源开始,并为这些资源提供CRUD功能。之后,您可以根据用例需求创建那些面向用例、减少冗余通信的资源。
考虑资源的关联性
REST的原则之一是关联性——通过超媒体链接(搜索HATEOAS)。尽管没有这些链接服务仍然有用,但当响应中返回链接时,API变得更加自描述和可发现。至少,自身链接参考能告知客户端数据是如何被获取的,或者可以如何获取。此外,在通过POST(或PUT)创建资源时,利用HTTP Location头部包含资源的链接。对于响应中返回的支持分页的集合,至少提供“首页”、“末页”、“下一页”和“前一页”链接是非常有帮助的。
关于链接格式,有很多种。HTTP Web Linking 规范(RFC5988)解释了链接如下:
一个链接是两个资源之间的类型化连接,这些资源通过国际化资源标识符(IRIs)[RFC3987]进行标识,并由以下组成:
- 上下文 IRI,
- 链接关系类型,
- 目标 IRI,以及
- 可选的目标属性。
一个链接可以视为以下形式的声明:“{上下文 IRI} 在 {目标 IRI} 处具有一个 {关系类型} 资源,该资源具有 {目标属性}。”
至少,应根据规范的建议,将链接放置在 HTTP Link 头中,或在您的 JSON 表示中采用这种 HTTP 链接样式的 JSON 表现形式(例如 Atom 样式的链接,参见:RFC4287)。随着您的 REST API 变得更加成熟,您可以逐步加入更复杂的链接样式,例如 HAL+JSON、Siren、Collection+JSON 和/或 JSON-LD 等。