RESTful API 是常常看到的一種 API 風格。不管是手上有一批資料要讓別人存取,或是要設計前後端分離的系統,好的 API 讓你事半功倍。

雖然 RESTful API 或許已稍稍退流行,你可能聽聞許多大公司都已經改用 GraphQL 等等。但風向雖然這樣吹,許多服務仍然是使用傳統的 RESTful API,相信學會設計 RESTful API 後,在使用 API 上也會比較輕鬆。

這篇文章大概會介紹 RESTful API 常用的規範,並指出一些可能有爭議的部分和我慣用的做法。之後這一系列會再介紹怎麼撰寫 API 服務。

RESTful API 是什麼?

RESTful API 是一種設計規範,並沒有規定 Web API 都必須使用 RESTful 風格,而是比較常被使用而已。畢竟前後端都使用同一種風格,這樣就不用花太多時間猜測怎麼使用。(當然更好的做法是做出詳細的 API 文件。)

網址要長怎樣

首先要決定這個 API 放哪裡。通常如果我們要架設新的服務,例如 kangaroo.noob.tw 的話,我們的 API 網址可能會是:

https://api.kangaroo.noob.tw

https://kangaroo.noob.tw/api

而我通常會使用第二種,不使用子網域的方式。這樣就算某些內部系統只用 IP 而不用網域也不會出問題。

另外為了方便未來 API 改版時不同版本的 Client 可以同時使用,我會習慣在 URL 後面加上 API 版本:

https://kangaroo.noob.tw/api/v1

Endpoints

決定了 API 的網址後,要先規劃一下 API 大概會分幾個部分。假設我們要做一個簡單的部落格系統,可能會分成 使用者 部分和 文章 的部分。Endpoints 可以說是 RESTful 的「名詞」。

那使用者的部分可能就會放在 /user 底下、文章的部分可能會放在 /post 底下。原則上這些名詞不使用大寫,若是由多個字組成,通常會使用底線(_)隔開。

HTTP Method

RESTful API 使用了 HTTP Method 來當作「動詞」。這些動詞分別代表幾個意思:

  • POST:新增
  • GET:讀取
  • PUT:修改(修改整份文件)
  • PATCH:修改(修改其中幾個欄位)
  • DELETE:刪除

同為 HTTP Method 的 OPTIONS 和 HEAD 不太會在 RESTful API 中用到。

透過這些動詞,我們就可以做不同的動作。像是新增使用者會使用 POST /user 而不會是 POST /user/new

正確範例:

  • 新增使用者:POST /user
  • 查所有帳號:GET /users
  • 查詢使用者:GET /user/1
  • 修改使用者:PUT /user/1
  • 刪除使用者:DELETE /user/1

錯誤範例:

  • 新增使用者:POST /user/new
  • 查所有帳號:GET /users/all
  • 查詢使用者:GET /user/query/1
  • 修改使用者:PUT /user_edit/1
  • 刪除使用者:DELETE /user/delete/1

有的人會通通使用 /users,例如取得 uid=2 的使用者會使用 GET /users/2 而不是 /user/2,我個人是習慣單數資源不加 s。

API 回傳資料

回傳資料時,也要注意幾件事情。首先由於 API 大多由 Ajax 的方式去呼叫,也就是說 Client 端(如網頁)是在背景再乎叫一次這個 API,得到資料後再顯示在前景,所以要回應不同的狀態讓 Client 知道狀況再去決定要幹麻,設計 API 時不要轉址

舉個例子,註冊成功要轉到登入頁面應該是在 POST /user 後回傳成功,讓前端自己去決定失敗的話要顯示什麼訊息、成功的話要轉址到哪。畢竟設計 API 的時候你不知道前端工程師會不會想要顯示個五秒的動畫再震動之類的。

而資料格式我們會採用 XML 或 JSON 等格式,不會使用純文字。

除了善用 HTTP Method 以外,API 也應該優先採用 HTTP Status Code 來表達狀態,而不是採用 {success: true}{result: ok} 的狀態來回傳。原則上成功的話使用 2XX、失敗看情況,如果是使用者做錯就使用 4XX、伺服器出錯就使用 5XX,以下是幾個常用的狀態:

  • 200 OK:成功。通常我用在查詢(GET)的部分。

  • 201 Created:資源新增成功。通常我用在新增(POST)的部分。

  • 202 Accepted:請求已接受,但還在處理中。(換句話說可能失敗)

  • 204 No Content:請求成功,沒有返回內容。通常我用在刪除(DELETE)或修改(PUT)的部分。
    也有人會把修改成功放在 201。

  • 400 Bad Request:使用者做錯的通用狀態。通常我用在有必填欄位未填或資料錯誤的狀況。

  • 401 Unauthorized:使用者沒有進行驗證。

  • 403 Forbidden:使用者已經登入,但沒有權限進行操作。

  • 404 Not Found:請求的資源不存在。

  • 410 Gone:資源已經過期。

  • 500 Internal Server Error:伺服器端錯誤。

  • 502 Bad Gateway:通常是伺服器的某個服務沒有正確執行。

  • 503 Service Unavailable:伺服器臨時維護或是快掛了,暫時無法處理請求。

  • 504 Gateway Timeout:伺服器上的服務沒有回應。

結語

以上是我覺得設計 API 比較重要的部分。另外像是錯誤處理的 HATEOAS、跟狀態有關的 stateful/stateless、驗證該採用 OAuth 還是 JWT 等等,甚至是 Content-Type 要用 JSON 還是 XML,我個人覺得比較偏向團隊說好怎麼開發就可以,比較不是一個「基本」的 RESTful API 要顧慮的事情。總之先把這些關鍵字打下來,之後再花篇幅來討論這些東西。

延伸閱讀