RESTful

警告
本文最后更新于 2023-07-07,文中内容可能已过时。

RESTful 是一种系统开发设计风格、原则。可视情况调整,以下参考来源 RFC5789

Noun

  • 一般资源 通用于一律使用复数名词 例如:/books 或 /books/123。但有部分人认为应该使用单数名词,因为: /book/123 看似比 /books/123 合理。但想想文件系统的目录命名(例如 /Users 或 /Documents),其实用复数也没问题。复数可以保持 API endpoint 的一致性,所以一般资源建议用复数。
  • 唯一资源:对 client 而言只有一份的资源 通用于单数名词 例如:user 是指目前验证的使用者,使用者永远只能同时登入一个使用者

Http Method

MethodIdempotentSafeCRUDOO生活动词用途
GETYYReadgetget取得资料
list列出资料
POSTCreateaddcreate建立一个可以完全独立存在的实体
add增加一个必须依赖于某个实体的实体
PUTYUpdatesetreplace取代一个关系,已存在时先删除后建立,不存在时直接建立
add附加唯一关系,两个关系实体可以互相独立存在,且已经存在
PATCHedit编辑某个实体
DELETEDeleteremoveremove
delete
删除某个实体
  • Safe:该操作不会改变伺服器端的资源状态(而且结果可以被 cache),属于 Safe 的操作必定属于 Idempotent
  • Idempotent (幂等性):该操作不管做 1 遍或做 n 遍,都会得到同样的资源状态结果(但不一定得到同样的返回值,例如第 2 次 DELETE 请求可能回传 404),因此 client 端可以放心 retry

GET

Safe:每次执行操作时,GET 只有读取 Resource,不会改变到任何的 Resource (资源,资料)
Idempotent:每次执行操作时,GET 只有读取 Resource,不会改变到任何的 Resource (资源,资料),所以任何资源的任何状态都是一样的

POST

每次执行操作时,POST 都会建立一个 Resource (资源,资料)

  • Create:建立一个可以完全独立存在的实体

    范例:建立使用者

    执行第一次时:建立一个 name = “李四” 的 user,但其 id = 1,执行第二次时:建立一个 name = “李四” 的 user,但其 id = 2,发送同样的请求,可每次都是不同的 Resource

    建立使用者前不需要建立任何的东西,就可以建立使用者了,使用者是可以完全独立的存在

    1
    2
    3
    4
    5
    6
    
    POST /users HTTP/1.1
    Host: 127.0.0.1
    
    {
     "name": "李四"
    }
  • Add:增加一个必须依赖于某个实体的实体

    资料结构:一对多的关系

    范例:Add a public key on behalf of a user 增加一个代表使用者的公钥 (Gitea API)

    增加这个公钥之前,使用者必须存在,公钥必须归属于某个使用者之下,公钥跟姓名一样,使用相同电脑的公钥就会相同,但不表示是同一个使用者,故公钥也会有自己的 ID 我每次增加公钥时,都将生成不同的公钥 ID

    1
    2
    3
    4
    5
    6
    7
    8
    
    POST /api/v1/admin/users/{username}/keys HTTP/1.1
    Host: gitea.com
    
    {
      "key": "string",
      "read_only": true,
      "title": "string"
    }

PUT

Idempotent:每次执行操作时,PUT 都会取代 Resource,不管操作几次,使用者获取得 Resource 结果都是一样的

Replace:不论资源如何,最终的资源状态都是一样的,Resource 已存在时,或许不理会、或许先删除后建立(取代)Resource 不存在时,直接建立

Add:添加唯一关系,建立这个唯一关系前,两个关连实体都必须存在。在没有建立关系前,两个关连实体都可以互相独立存在 资料结构:多对多,且两个关连实体的 PK,同时也是关系实体的 PK、FK

  • 范例:增加使用者与角色的关系

    增加使用者跟角色的关系前,使用者跟角色都必须存在;增加使用者跟角色的关系前,使用者跟角色可以独立存在, 使用者 12262 跟 角色 2 的关系最多只能有一条关系( 使用者 12262 有 角色 2),最少没有关系(使用者 12262 没有 角色 2 ) ,执行第二次操作时,使用者 12262 跟 角色 2 的从属关系仍然存在,也不会跑出第二条 使用者 12262 跟 角色 2 的从属关系

    1
    2
    3
    4
    5
    6
    
    PUT user/{account}/roles HTTP/1.1
    Host: 127.0.0.1
    
    {
      "role_id": "2"
    }
  • 范例:Follow a user 关注一个使用者 (Gitea API)

    增加关注关系时,关注者与被关注者(都是使用者) 都必须存在;关注者 12262 跟被关注者 12231 的关系最多只能有一条关系(12262 关注 12231),最少没有关系(12262 不关注 12231),执行第二次操作时,关注者 12262 跟被关注者 12231 的关注关系仍然存在,也不会跑出第二条关注者 12262 跟被关注者 12231 的关注关系

    1
    2
    
    PUT /api/v1/user/following/{username} HTTP/1.1
    Host: gitea.com

PATCH

Edit:编辑可独立存在、且已经存在的实体,也就是产生新版本的实体,可能会影响其他 Resource

  • 范例:编辑使用者

    编辑使用者,使用者已经存在,且我们可能有纪录编辑时间、编辑人、编辑 IP,所以每次的编辑都会造成不一样的结果 第一次编辑使用者,更新时间变为 08:00,编辑人 12262,IP 172.18.0.66 第二次编辑使用者,更新时间变为 09:00,编辑人 12263,IP 172.18.0.67

    1
    2
    3
    4
    5
    6
    7
    8
    
    PATCH /users/{account} HTTP/1.1
    Host: 127.0.0.1
    
    {
    	"username": "李四",
    	"age": "18",
    	"gender": "male"
    }

DELETE

Idempotent:每次执行操作时,DELETE 都会删除相同的东西

  • 范例:删除使用者

    第一次删除使用者 12262,删除使用者 12262, 第二次删除使用者 12262,还是删除使用者 12262,只不过使用者 12262 不存在了

    1
    2
    
    DELETE /users/{account} HTTP/1.1
    Host: 127.0.0.1

HTTP Status Code

HTTP 状态码(HTTP Status Code)是用以表示网页服务器 HTTP 响应状态的 3 位数字代码。所有状态码的第一个数字代表了响应的五种状态之一。除非另有说明,状态码是 HTTP/1.1 标准RFC 7231)的一部分。

而关于 RESTful API 的请求状态,通常有以下两种设计方案:

  • 方案一:使用 HTTP 状态码来表示请求状态,200 时返回的内容就是数据
  • 方案二:所有接口都返回 200 ,在响应内容里约定错误码或错误信息

在实际应用中,应据具体情景及需要进行选择与调整。

方案优劣比较
方案一优点对服务端来说较为简单方便
缺点客户端难以根据状态码处理复杂问题
方案二优点方便对返回资料进行统一处理和细微性的控制
缺点相当于放弃了 HTTP 状态码的语义

常用 HTTP 状态码

CodeMessage用途
1XXInformational response此类状态码通常代表的响应都是信息性的,告诉客户端可以进行下一步操作。
100Continue表示服务端已接收到请求头,客户端可以继续发送请求体(如 POST 请求)。
101Switching Protocols表示服务端支持更优协议,让客户端在服务端更换协议后重新访问。
2XXSuccessful此类状态码通常代表请求已成功被服务端接收、理解并接受。
200OK表示请求成功。
201Created表示请求已被实现,通常是在成功创建了某个资源。
202Accepted表示请求已被服务端接收,但尚未进行处理。
204No Content表示请求成功,但不会返回任何内容。
205Reset Content表示请求成功,但不会返回任何内容,并且要求客户端重置表单。
3XXRedirect此类状态码通常代表本次请求需要客户端采取进一步操作才能完成。通常用于重定向。
300Multiple Choices表示请求的资源有多个供可选择,客户端可自行选择一个进行请求的重定向。
301Moved Permanently表示请求的资源已经永久地移动到了新位置,并且将在 Location 域中携带该资源新的 URI。
304Not Modified表示请求的资源无发生修改,将不会返回任何资源。
4XXClient Error此类状态码通常代表客户端可能出现了错误。
400Bad Request表示客户端发出的请求有误(格式、大小、无效的…),服务端不能/ 不会处理该请求。
401Unauthorized表示客户端未能提供必要的验证,服务端拒绝提供资源。
403Forbidden表示服务端理解了该请求,但客户端没有足够权限以访问,遂拒绝提供该资源。
404Not Found表示服务端无法找到请求的资源,其可能已经暂时(永久)失效。
408Request Timeout表示请求超时。
409Conflict表示请求的资源发送了冲突,通常是 PUT 请求。
410Gone表示请求的资源已经永久失效,客户端不应再次请求。
411Length Required表示服务端拒绝在没有定义 Content-Length 头的情况下接收该请求。
5XXServer Error此类状态码通常代表由于服务端的原因,导致无法完成请求。
500Internal Server Error表示由于服务端遇到意料之外的变故,导致无法完成请求。
501Not Implemented表示服务端不支持完成请求所需的功能,导致无法完成请求。
502Bad Gateway表示作为网关或代理的服务段在执行请求时,从上游服务器获得了无效的响应。
503Service Unavailable表示由于某些原因(服务器超载或系统维护等),导致暂时无法完成请求。
504Gatewy Timeout表示作为网关或代理的服务段在执行请求时,未能及时从上游服务器获得响应。
505HTTP Version Not Supported表示服务端不支持请求的 HTTP 协议版本,导致无法完成请求。

以上内容参考自https://zh.wikipedia.org/zh-cn/HTTP状态码, 需要查看完整 HTTP 状态码请点击 https://www.rfc-editor.org/rfc/rfc9110.html#name-status-codes

Buy me a coffee~
支付宝
微信
0%