RESTful API - fantasy0107/notes GitHub Wiki

開發流程

  1. 先看看有沒有可以用的api - 要有 api 文件查詢
  2. api 要有版本
  3. 判斷要用的 http method
  4. 成功和失敗所要回傳的狀態碼
  5. 回傳格式 ex: json api

是一種設計風格或者規範也就是說不遵守也可以

為什麼要重視 API 設計

改動 API 需要同時改動前端跟後端, 現實上會有極大的困難

應該有看到我剛才的 URL 是v1

錯誤的 API 設計可以引起

  1. 嚴重的效能問題
  2. 扭曲程式邏輯和數據結構

API 設計重點

統一介面(uniform interface)是相對上最死不了人的, 別為這吵架太久

  1. 例如 : 以下兩派都有人喜歡
/v1/pets/12

/v1/users/987/pets/12

好的 API 永不限制前端設計, 即使要輕度違反 uniform interface 原則, 一切以使用者感受度為最大優先

  1. 像是在頁面中, 用戶能同時建立其用戶資料, 還有其他貓群的, 所以需要建立特殊的 post - UserAndPet
  2. 所有的 API一定是名詞或動名詞

傳統網頁 與 前後端分離架構

傳統

  1. data 與 presentation 混和, presentation 無法單獨 cache , 只要 data 變動就必須重新產生
  2. 無法徹底分割 presentation, business logic, 和 data 影響開發, 測試和除錯
  3. 伺服器將 data 和 presentation 整合(data binding), 消耗伺服器資源

前後端分離

優點1. 客戶端快取節省流量

  1. 表面上, 原本只需要 1 次 request 增加為 2次似乎更花時間與網路流量
  2. 但是, 只要負責美工的同事不改變網頁外表, 第一個 request 伺服器會回答 http 304 not modified
  3. 網頁 presentation 不用每次重傳, 可以節省不少網路流量($$$$$)

優點2. 資料與介面分離

  1. presentation 和 data 徹底分離
  2. 開發和測試 presentation 的 data mocking 可以使用專門的 mock api 伺服器
  3. 只要準備好 api 與測試資料, 前後端工程是就能專心工作, 前端開發延誤和後端工程師無關
  4. 可在將執行架構改為 presentation 在 apache/cdn, api 為 Tomcat

優點3. 節省伺服器資源

  1. 可以不再伺服器做的東西, 就不要放在伺服器
  2. data binding 交給瀏覽器處理, 不再是伺服器的工作, 省下伺服器的 cpu

優點4. 能重用伺服器的程式

  1. 即使未來要支援 ios, android 只要背後邏輯不變, 這些 API 能全部重複使用, 節省開發時間

RESTful

只是回歸最初 HTTP 時代的設計哲學 雖然大部分人都是使用 HTTP 來實現 RESTful, 但 RESTful 是設計哲學, 不強制用甚麼方式來實現

謬誤

server side 需要 stateless

  1. 正解1 : HTTP 只要求 protocol 是 stateless, 從未要求伺服器是 stateless
  2. 正解2 : RESTful 只要求 application server 是 stateless,server side 其他部分可以是stateful

一定需要用上 HTTP 的 GET, POST, PUT/PATCH, DELETE

  1. 正解: 統一介面(uniform interface)只建議使用 HTTP, 使用其他技術實作的統一介面也能滿足 RESTful 要求

要求

client-server 客戶和伺服器架構

  1. RESTful 只規範伺服器, 和客戶端與伺服器之間的通訊協定

cacheable 能利用快取機制增進效能

  1. 系統內所有的東西都必須定義能否使用快取
  2. 客戶端建立本地快取
  3. 下次請求時, 客戶端會把本地快取版本告訴伺服器, 如果伺服器發現資源沒有沒有改動, 返回 304
  4. 可以省下伺服器 CPU資源和網路流量
  5. 不常變動的物件適合設定為快取, 如網頁介面
  6. 詳見 HTTP conditional GET

layered system 分層式系統

網路的不穩定性

  1. 隨時會斷線
  2. 使用 API, 連線可能在信號送達伺服器前斷線
  3. 更可能用戶端以為斷線, 卻早已經傳訊成功
  4. 除非使用 TCP/IP 否則當客戶端先發出 指令1, 然後再發出指令2, 在次序錯亂的情況下, 伺服器可能先收到指令2
  5. 任何可以錯的東西, 都有機會出錯

stateless protocol 通訊協定無狀態性

通訊協定具有無狀態性

  1. Restful 伺服器端是被允許有狀態性的
  2. Application Server 和 connection 必須是無狀態的
  3. RESTful 准許把狀態儲存到資料庫中, 例如將登入狀態的短期資訊放到短期資料庫Redis
  4. 最簡單的程式寫法: RESTful 禁止使用 HttpSession(Java), session_start(PHP)

atomic (原子性)

  • atomic 是由商業邏輯定意的
    • 從用戶 A 轉帳到用戶 B
    • 付錢買火車票
  • 每一個動作都比須是 atomic, 一個完整執行後的 API 呼叫不能讓伺服器數據停留在不一致的狀態
  • 另一個說法 : 你不能使用兩個或以上的 API 呼叫去完成一個動作

足夠的完整的資料

idempotence (重新呼叫)

uniform interface 統一介面

所有 URL都應該基於物件, 而不是行動
一個物件正常應該有4種行動 查詢, 更改, 誕生, 刪除

  • 查詢 : 一般使用 HTTP GET
  • 更改 : 一般使用 HTTP PUT/PATCH
  • 誕生 : 一般使用 HTTP POST
  • 刪除 : 一般使用 HTTP DELETE

範例

GET - 得到檔案 POST - 新增檔案 PUT - 更新檔案 DELETE - 刪除檔案
Restful GET - /api/files/ POST - /api/files/ PUT - /api/files/ DELETE - /api/files/
一般 /api/get_file/ /api/upload_file/ /api/update_file/ /api/delete_file/

概念

REST = Resource Representational State Transfer

  1. Resource => 資源
  2. Representational => 像是 JSON,XML,YAML 等等...
  3. State Transfer => 狀態傳輸 ,透過 HTTP 動詞實現 ( GET,POST,PUT,DELETE)

優點

  1. 單一接口利用 HTTP method
  2. 可讀性

缺點

  1. 安全性 - 從 URL 判斷出 CRUD 進而操作

Safe and Method Idempotent

safe

是指該操作不會改變伺服器端的資源狀態(而且結果可以被cache)

Method Idempotent

是指該操作不管做1遍或做n遍,都會得到同樣的資源狀態結果

HTTP Method Idempotent Safe
OPTIONS yes yes
GET yes yes
HEAD yes yes
PUT yes no
POST no no
DELETE yes no
PATCH no no

狀態碼

2XX 成功

200 OK 用於請求成功, 並且把結果回傳 。GET 檔案成功,PUT, PATCH 更新成功

201 Created 用於請求 POST 成功建立資料

202 Accepted

  1. 伺服器收到請求, 並且確定請求沒有問題, 但尚在處理中
  2. 不過, 這請求需要很多時間來工作, 為了避免客戶白白等待, 即使工作還沒完成, 先回答客戶 工作收到了
  3. 沒事別亂用

204 No Content

  1. 與 200 相似, 不過沒有結果須要回傳
  2. 一般來說 delete 和 put 會用到

3XX 重新導向

301 Moved Permanently: 資源已移至它處

303 See Other: 回傳的內容可在它處取得(例如在用戶端發送了一個POST請求之後)

304 Not Modified

  1. 請求的資源並未修改(通常是用戶端發送了帶有If-Modified-Since或If-None-Match表頭的請求)
  2. 如果客戶端已經有了某一個物件的副本. 但是不知道這物件是否是最新版
  3. 客戶端會發出 conditional get, 在 http header 中加入 if-modified-since:<某時間>
  4. 如果客戶端是最新版, 就回答304否則200

4XX 用戶端錯誤

400 Bad Request

  1. 用於請求 API 參數不正確的情況,例如傳入的 JSON 格式錯誤。通用狀態碼
  2. 請求內容有誤伺服器拒絕執行 ex age應該是 integer 但傳來 abc315

401 Unauthorized

  1. 用於表示請求的 API 缺少身份驗證資訊。
  2. 最簡單請登入系統
  3. 請檢察 HTTP header 的 authorization

403 Forbidden

  1. 用於表示該資源不允許特定用戶訪問。
  2. 跟 400 不同, 伺服器明白請求內容
  3. 不過, 其請求內容與商業邏輯矛盾, 伺服器拒絕執行

404 Not Found

  1. 用於表示請求一個不存在的資源
  2. 如果 get collection 而沒有搜查到滿足條件的物件, 應該是返回 200 而不是 404

405 Method Not Allowed: 不支援請求的HTTP方法

406 Not Acceptable: 不支援請求所要求的內容類型*(Accept表頭)

409 - conflict

  1. 用戶正在改動的物件, 已經被別人先改動過了

415 Unsupported Media Type: 不支援請求所用的內容類型*(Content-Type表頭)

5XX 伺服器錯誤

500 Internal Server Error

  1. 工程師要找bug了, 或是某部分像是資料庫掛了

501 Not Implemented

  1. 用戶端的請求目前未支援(也就是將來有可能支援)

502 Bad Gateway

  1. 上游的伺服器未回傳正確結果,一般是gateway或proxy server才會回傳此狀態碼
  2. 伺服器分流層( load balancing tier ) 出現問題

503 Service Unavailable

  1. 暫停服務(也就是過不久就會恢復服務──如果一切順利的話)
  2. 伺服器沒當掉, 只是太多人使用而繁忙中, 所以直接拒絕這個請求

504 Gateway Timeout: 上游的伺服器逾時,一般是gateway或proxy server才會回傳此狀態碼

HTTP

通訊協定

基於 HTTP 建立的東西

  • Restful 後端
  • SOAP
  • 支持 REST 介面的資料庫
  • HTML

理念

  1. 資源(Resource) + 方法(Method) 1.非狀態通訊 (stateless protocol)

HTTP 資源

  • 資源一定是名詞
  • 動名詞也是名詞

HTTP method

  • 常用就 get 和 post 但還有很多其他的
  • 一些資源可能只支持部分 method
    • /v1/TopSecretReport 應該只有 get

HTTP method - Get

  1. 讀取資源 (Readonly)
  2. 只有 get 才用 queryString
  3. 以 id 結尾通常是讀取單一物件 ex: /v1/users/987
  4. 沒有以 id 為結尾的讀取 collection
  5. 可以有 include 去取得主要資源的關聯資源
  6. 可以有 sort
GET /people?sort=age  // 單一 (asc)
GET /people?sort=age,name //多個 (asc)
GET /articles?sort=-created,title  (desc)
  1. 可以有 Pagination - 分頁
  2. 可以有 Fieldsets - 只取得特定資源和相關關聯資源的欄位
GET /articles?include=author&fields[articles]=title,body&fields[people]=name
  1. Provide filtering, sorting, field selection and paging for collections

HTTP method - Delete

  1. 刪掉特定資源
  2. EX: /v1/users/987 - 刪掉使用者987

HTTP method - POST

  1. 建立資源 ex /v1/users
  2. 一般會把資源 ID 返回給用戶
  3. 延伸思考 : 在穩定定網路底下, 用戶建立一份資源時卻發出兩次 post 怎麼辦
  4. HTTP post 定義為 non-idempotent, 但是他沒有禁止你自行解決 idempotent 的問題
  5. 自己的觀點 - 也可以用在搜尋和一個商業邏輯的行為(url用動名詞)

HTTP method - Patch

  • 改動資源的部分內容
  • id 是 987 的 user 的內容是: name = susan, age=30, 現在要把 age 改成31 所以
url = /v1/users/987
method = patch
request body = { "age" : 31 }
  • 是否是 idempotent 要看你的改動
//idempotent
set age = 31

//non idempotent
set age = age +1 

HTTP method - put

  • 傳統 HTTP 定義 : 以新上傳的內容, 覆蓋掉本來的資源
  • 不過還多很人會在 put 中支援部分改動 (partial update), 而不再另外開 patch method

HTTP method - options

  1. 用來查詢某一資源, 使其能使用的methods
  2. cross domain request 時, 用戶端會先發出 options 查詢

參考資源

認識 RESTful API
簡明RESTful API設計要點
淺談 RESTful api

json api 教學

⚠️ **GitHub.com Fallback** ⚠️