RESTful 是一種系統開發設計風格、原則。可視情況調整,以下參考來源 RFC5789 (https://tools.ietf.org/html/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 (資源, 資料)
  • 範例:建立使用者
    • 執行第一次時:建立一個 name = “帥小慶” 的 user,但其 id = 1
    • 執行第二次時:建立一個 name = “帥小慶” 的 user,但其 id = 2,發送同樣的請求,可每次都是不同的 Resource
  POST /users
  Data:
    {
      "name": "帥小慶"
    }
  • Create:建立一個可以完全獨立存在的實體
  • 範例:建立使用者 ​ 建立使用者前不需要建立任何的東西,就可以建立使用者了,使用者是可以完全獨立的存在
POST /users
Data:
  {
    "name": "帥小慶"
  }
  • Add:增加一個必須依賴於某個實體的實體 ​ 資料結構:1對多的關係
  • 範例:Add a public key on behalf of a user 增加一個代表使用者的公鑰 (Gitea API) ​ 增加這個公鑰之前,使用者必須存在,公鑰必須歸屬於某個使用者之下 ​ 公鑰跟姓名一樣,使用相同電腦的公鑰就會相同,但不表示是同一個使用者,故公鑰也會有自己的 ID ​ 我每次增加公鑰時,都將生成不同的公鑰 ID
  POST/admin/users/{username}/keys

PUT

  • Idempotent:每次執行操作時,PUT 都會取代 Resource,不管操作幾次,使用者獲取得 Resource 結果都是一樣的
  • Replace:不論資源如何,最終的資源狀態都是一樣的 ​ Resource 已存在時,或許不理會、或許先刪除後建立 (取代) ​ Resource 不存在時,直接建立
  • Add:添加唯一關係,建立這個唯一關係前,兩個關連實體都必須存在。在沒有建立關係前,兩個關連實體都可以互相獨立存在
  • 資料結構應為:多對多,且兩個關連實體的 PK,同時也是關係實體的 PK、FK
  • 範例:增加使用者與角色的關係 ​ 增加使用者跟角色的關係前,使用者跟角色都必須存在;增加使用者跟角色的關係前,使用者跟角色可以獨立存在 ​ 使用者 23240,跟角色 2,的關係最多只能有一條關係 (使用者 23240 有角色 2 ),最少沒有關係 (使用者 23240 沒有角色 2 ) ​ 執行第二次操作時,使用者 23240 跟角色 2 的從屬關係仍然存在,也不會跑出第二條使用者 23240 跟角色 2 的從屬關係
  PUT user/{account}/roles
  Data
    {
      "role_id": "2"
    }
  • 範例:Follow a user 關注一個使用者 (Gitea) ​ 增加關注關係時,關注者與被關注者 (都是使用者) 都必須存在;增加關注關係時,關注者與被關注者 (都是使用者) 都必須存在 ​ 關注者使用者 23240,跟被關注者使用者 F3860056,的關係最多只能有一條關係 (23240 關注 F3860056),最少沒有關係 (23240 不關注 F3860056) ​ 執行第二次操作時,關注者 23240 跟被關注者 F3860056 的關注關係仍然存在,也不會跑出第二條關注者 23240 跟被關注者 F3860056 的關注關係
  PUT/user/following/{username}

#### PATCH

  • Edit:編輯可獨立存在、且已經存在的實體,也就是產生新版本的實體,可能會影響其他 Resource
  • 範例:編輯使用者 ​ 編輯使用者,使用者已經存在,且我們可能有紀錄編輯時間、編輯人、編輯IP,所以每次的編輯都會造成不一樣的結果 ​ 第一次編輯使用者,更新時間變為 08:00,編輯人 23240,IP 10.151.110.165 ​ 第二次編輯使用者,更新時間變為 09:00,編輯人 23241,IP 10.151.110.144
  PATCH /users/{account}

DELETE

  • Idempotent:每次執行操作時,DELETE 都會刪除相同的東西
  • 範例:刪除使用者 ​ 第一次刪除使用者23240,刪除使用者23240 ​ 第二次刪除使用者23240,還是刪除使用者23240,只不過使用者 23240 不存在了
  DELETE /users/{account}

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協議版本,導致無法完成請求。