本文描述了識別一個接口是否真的是 RESTful 接口的基本方法。符合 REST 架構風格的接口,稱爲 RESTful 接口。本文不打算從架構風格的推導方面描述,而是從 HTTP 標準的方面描述。識別的方法同時也是指導實踐的原則。html
1、是否使用了正確(合適)的方法git
目前對於 HTTP 標準濫用較多的,就是方法。談起 RESTful 接口的方法,不少資料告訴你們,說 GET、POST、PUT、DELETE,分別對應數據庫操做的 SELECT、INSERT、UPDATE、DELETE。其實這種理解是不正確的。github
方法有兩個性質:安全性與冪等性;以及一個語義:動做自己的意思。RESTful 接口爲各類數據抽象爲資源,對資源的操做,主要是依據方法的兩個性質,其次纔是語義。數據庫
GET 方法的語義是獲取資源,性質是安全、冪等。也就是說,對資源進行安全冪等的操做,應該用 GET 或 HEAD,當目的是獲取資源時,選用 GET,目的是獲取資源的元數據時,使用 HEAD。使用安全冪等的方法執行不安全或不冪等的操做,都是錯誤的。一個典型的例子是:json
GET /book/357?op=delete
這個例子的意圖是刪除 ID 爲 357 的 book,DELETE 是不安全的操做,卻使用了 GET 這個安全冪等的操做。這做法的反作用是可能被緩存,全部組件(包括搜索引擎)都認爲它是安全的,從而可能不加任何限制地對它進行訪問。
api
POST 方法的語義是提交資源。「提交」自己就是一個比較抽象的動詞,即它的語義是能夠根據環境變化的,若是將它與 INSERT 對應起來,是以偏概全的。它的性質是不安全、不冪等。這意味着全部組件對它都不緩存,不重複發送請求。執行不安全、不冪等的操做,惟有選擇 POST 方法(標準未規定的全部自定義方法,在性質上等同於 POST)。瀏覽器
一個不安全、不冪等的方法,能夠執行安全、冪等的操做,前提是須要犧牲緩存等屬性。好比提交一個不少參數的查詢,可使用 POST。緩存
HTTP/1.1標準那麼多年,HTML標準到5了,爲何HTML的 form 只有 GET 和 POST 兩種 action ?爲沒有不把 PUT、DELETE、PATCH 等方法加進去?實際上是有緣由的。安全
首先,form 元素的提交表單的按鈕是 submit,與 POST 的語義是等同的。服務器
其次,當瀏覽器得到一個資源時,form 只是資源的一部分,不能表示整個資源,根據 PUT/DELETE/PATCH 的定義,它沒法表示它們。
因爲 POST 的性質與抽象的語義,在沒有合適的方法時,均可以使用 POST 代替。所以,將 POST 等同於新增/插入的那些文章或教材,都在誤導人。
篇幅有限,其它方法不說了,網上基於其它方法的文章基本正確的。
2、是否支使媒體協商
媒體協商是指客戶端和服務器對某種媒體類型的處理能力。通常狀況下,客戶端並不知道服務器能處理哪一種媒體。瀏覽器就是典型表明,它在無先驗知識的狀況下,會進行媒體探測:
GET / HTTP/1.1 Host: example.com Accept: text/html; q=1.0, image/*; q=0.8, */*; q=0.1
這是告訴服務器,我能很是有效地處理 HTML 類型的資源,圖片也是頗有效的,其它的資源類型,我也能接受。因而服務器就優先按 HTML 返回資源,若是沒有 HTML 或 Image,就返回服務器自身最合適的,如 application/json。
假設服務器僅支持 application/json,當客戶端要求一個 application/xml 時,應當返回 415 Unsupported Media Type,並在正文中說明支持哪一種媒體類型。
舉個值得學習的案例,Github:https://api.github.com/ ,你們能夠本身試試。
3、是否可以進行狀態轉移
這一點很是重要,也是 REST 的本意,狀態轉移!HTTP 標準實現的 REST 中,鏈接(Link)是實現狀態轉移的重要組件(HTML 的超連接和表單也是)。
在無先驗知識的前提下,客戶端請求資源 / ,這個資源及其元數據,要可以爲應用程序的下一個狀態的轉移提供必要的鏈接。有時候甚至要提供文檔說明的鏈接。
例如,當咱們訪問 https://api.github.com/ 時,咱們看到一個鏈接的列表。經過這些鏈接,咱們的客戶端就能夠跳轉到另外一個狀態,從而實現整個應用程序的狀態轉移。狀態如何更好的轉移(甚至是自動化的狀態轉移),就要依賴於鏈接的關係(rel)以及鏈接的媒體類型(type)和可選的文檔。
這種狀態轉移的能力,正是 REST 的魅力。誠然,最成功的 REST 客戶端是瀏覽器,最成功的媒體類型是 text/html,最成功的 REST 是 HTTP,經過 URI 標準構建的鏈接,進化成咱們今天沒法量化的巨大的分佈式系統:Web。
額外一點,一個 RESTful 的接口是不需在路徑或頭部字段中使用接口的版本號的。RESTful 接口這種說法,也有誤。REST有統一接口的概念,但這個概念通常是指 HTTP 標準。在一個 RESTful 的環境中,一切事物都是資源,資源是沒有版本號的。版本號是 API 的概念,API 是 RPC 的事物。
資源一旦發佈,其結構就基本上再也不發生變化。惟一可以變化的資源結構是在對舊資源無反作用的前提下,新增資源的字段或屬性。當新增或刪除的屬性與當前資源的結構不兼容時,則須要增長一個或一類新的資源。所以,在 RESTful 實踐中,是不須要使用版本號來標識資源的。
固然,RESTful 內容的豐富,遠遠不止以上所提到的三點。但這三點是很是基本的要求。