綜合Twitter、Github等各大網站API設計經驗:RESTful API實用設計與最佳實踐 - Vinay Sahni

banq發表於2019-12-15

如果你的資料模型已經開始穩定,並且可以為Web應用程式建立公共API了,一旦釋出了API,就很難對其進行重大更改,並且想要儘可能早地獲得正確的解決方案。現在,網際網路上對API設計的意見不統一也不是很充足。但是,因為沒有一種在所有情況下都能有效使用的標準,你可能有很多選擇:應該接受哪種格式?您應該如何認證?是否應該對API進行版本控制?
在設計Enchant的API (Zendesk替代品)時,我嘗試提出了這些問題的實用答案。我的目標是Enchant API對於我們自己的使用者介面易於使用,易於採用,並足夠靈活的內部測試

API的關鍵要求
在網路上找到的許多API設計意見都是學術討論,圍繞模糊標準的主觀解釋,而不是現實世界中有意義的解釋。我的這篇文章的目的是描述為當今的Web應用程式設計的實用API的最佳實踐。如果感覺不對,我不會嘗試滿足一個標準。為了幫助指導決策過程,我寫下了API必須努力滿足的一些要求:

  • 它應該在有意義的地方使用網路標準
  • 它應該對開發人員友好並且可以透過瀏覽器位址列探索
  • 它應該簡單,直觀且一致,以使採用不僅容易而且愉快
  • 它應提供足夠的靈活性以增強大部分UI
  • 它應該是有效的,同時保持與其他要求的平衡

API是開發人員的UI,就像任何UI一樣,確保仔細考慮使用者的體驗也很重要!

使用RESTful URL和操作

REST的關鍵原理涉及將您的API分成邏輯資源。這些資源使用HTTP請求進行操作,其中方法(GET,POST,PUT,PATCH,DELETE)具有特定含義。

但是我可以做些什麼呢?好吧,這些應該是從API使用者角度講有意義的名詞(而不是動詞!)。雖然您的內部模型可以整齊地對映到資源,但不一定是一對一的對映。這裡的關鍵是不要將無關的實現細節洩漏給您的API,例如Enchant案例中這些名詞是ticket,user和group。

定義資源後,您需要確定哪些操作適用於它們以及這些操作將如何對映到您的API。RESTful原則提供了使用對映如下的HTTP方法來處理CRUD操作的策略:

  • GET /tickets-檢索門票列表
  • GET /tickets/12-檢索特定的票證
  • POST /ticket -建立新票證
  • PUT /ticket/ 12-更新票#12
  • PATCH /tickets12-部分更新ticket#12
  • DELETE /tickets/12-刪除故障單#12

REST的優點在於,您可以利用現有的HTTP方法在單個/ tickets端點上實現重要的功能。沒有要遵循的方法命名約定,URL結構清晰明瞭。REST FTW!

端點名稱應為單數還是複數?保持簡單規則在此處適用。儘管內部語法專家會告訴您使用複數形式描述資源的單個例項是錯誤的,但務實的答案是保持URL格式一致並始終使用複數形式。不必處理帶有複數概念的詞語((person/people, goose/geese) ,使API消費者的生活更美好,是對API提供商實現最現代化的框架將在本地處理更容易。

但是您如何處理關係?如果一個關係只能存在於另一個資源中,則RESTful原則將提供有用的指導。讓我們來看一個例子。Enchant中的ticket包含許多訊息。可以將這些訊息邏輯上對映到/ tickets端點,如下所示:

  • GET / tickets / 12 / messages-檢索ticket#12的訊息列表
  • GET / tickets / 12 / messages / 5-檢索ticket#12的訊息#5
  • POST / tickets / 12 / messages-在ticket#12中建立新訊息
  • PUT / tickets / 12 / messages / 5-更新ticket#12的訊息#5
  • PATCH / tickets / 12 / messages / 5-部分ticket#12的訊息#5
  • DELETE / tickets / 12 / messages / 5-刪除ticket#12的訊息#5


或者,如果一個關係可以獨立於資源而存在,則在資源的輸出表示中僅包括一個識別符號即可。然後,API使用者將不得不點選關係的端點。但是,如果通常隨資源一起請求該關係,則API可以提供自動嵌入該關係的表示的功能,並避免對該API造成第二次打擊。

那些不適合CRUD操作的操作又如何呢?
這是事情變得模糊的地方。有多種方法:

  1. 重組操作以使其看起來像資源的欄位。如果操作不使用引數,則此方法有效。例如,啟用動作可以對映到啟用activated布林欄位,並透過PATCH更新到資源。
  2. 使用RESTful原則將其視為子資源。例如,GitHub的API可以透過PUT /gists/:id/star讓打星星,DELETE /gists/:id/star去除打星。
  3. 有時候,您確實無法將操作對映到合理的RESTful結構。例如,將多資源搜尋應用於特定資源的端點並沒有任何意義。在這種情況下,/ search即使不是資源,也將是最有意義的。沒關係-只需從API使用者的角度進行正確的操作,並確保已對其進行了清晰記錄,以免造成混淆。
  4. banq注:從活動這個詞語考慮,將動詞操作名詞化,某某活動即代表是動作,又代表名詞。


隨時隨地使用SSL
始終使用SSL。沒有例外。如今,您可以從Internet上的任何地方(例如圖書館,咖啡店,機場等)訪問您的Web API。並非所有這些都是安全的。許多協議根本不加密通訊,如果劫持了身份驗證憑據,則可以輕鬆進行竊聽或模擬。
始終使用SSL的另一個優勢是,保證加密的通訊可簡化身份驗證工作-您可以使用簡單的訪問令牌來獲得成功,而不必簽署每個API請求。

文件
API僅與其文件一樣好。該文件應該易於查詢並且可以公開訪問。大多數開發人員會在嘗試任何整合工作之前先簽出文件。當文件隱藏在PDF檔案中或需要登入時,它們不僅很難找到而且也不容易搜尋。
文件應顯示完整的請求/響應週期的示例。應該是可貼上的示例-可以貼上到瀏覽器中的連結或可以貼上到終端中的curl示例。 GitHubStripe在這方面做得很好。
釋出公共API後,您承諾不會在沒有通知的情況下破壞內容。該文件必須包括所有棄用時間表以及有關外部可見API更新的詳細資訊。更新應透過部落格(例如,變更日誌)或郵件列表(最好同時使用兩者!)進行傳遞。

版本控制
始終對API進行版本控制。版本控制可幫助您更快地進行迭代,並防止無效請求到達更新的端點。由於您可以在一段時間內繼續提供舊的API版本,因此還可以幫助您平滑所有主要的API版本轉換。
關於是否應在URL或標頭中包含API版本,存在不同意見。從學術上講,它可能應該放在標題中。但是,該版本必須位於URL中,以確保瀏覽器可以跨版本使用資源(還記得這篇文章頂部指定的API要求嗎?)。
我非常喜歡Stripe進行API版本控制的方法-URL具有主要版本號(v1),但是API具有基於日期的子版本,可以使用自定義HTTP請求標頭進行選擇。在這種情況下,主要版本提供了整個API的結構穩定性,而子版本則說明了較小的更改(欄位棄用,端點更改等)。
API永遠不會完全穩定。變化是不可避免的。重要的是如何管理更改。有據可查並已宣佈的數月棄用時間表對於許多API來說都是可以接受的做法。對於API的行業和潛在消費者,這歸結為合理的選擇。

結果過濾,排序和搜尋
最好使基本資源URL儘可能精簡。複雜的結果過濾器,排序要求和高階搜尋(僅限於一種型別的資源時)都可以輕鬆地實現為基本URL上方的查詢引數。讓我們更詳細地看一下這些:
過濾:對實現過濾的每個欄位使用唯一的查詢引數。例如,當從/ tickets端點請求票證列表時,您可能希望將其限制為僅處於開啟狀態的票證。這可以透過GET /tickets?state=open之類的請求來完成。這裡,狀態是實現過濾器的查詢引數。
排序:類似於過濾,通用引數排序可用於描述排序規則。透過使sort引數接受逗號分隔的欄位列表,可以滿足複雜的排序要求,每個欄位都有可能的一元負數以暗示降序排列。讓我們看一些例子:

  • GET / tickets?sort=-priority-以優先順序降序檢索票證列表
  • GET / tickets?sort=-priority,created_at-按優先順序從高到低的順序檢索票證列表。在特定優先順序之內,優先訂購較舊的門票

搜尋:有時基本的過濾器還不夠,您需要全文搜尋的功能。也許您已經在使用ElasticSearch或其他基於Lucene的搜尋技術。當全文搜尋用作檢索特定型別資源的資源例項的機制時,可以在API上將其公開為資源端點上的查詢引數。假設 引數名為q。搜尋查詢應直接傳遞給搜尋引擎,API輸出應採用與普通列表結果相同的格式。
將這些結合在一起,我們可以構建查詢,例如:
  • GET/tickets?sort = -updated_at-檢索最近更新的票證
  • GET/tickets?state = closed&sort = -updated_at-檢索最近關閉的門票
  • GET/tickets?q = return&state = open&sort = -priority,created_at-檢索提及“ return”一詞的優先順序最高的公開票證

常見查詢的別名
為了使普通使用者對API的體驗更加愉快,請考慮將條件集打包到易於訪問的RESTful路徑中。例如,上面最近關閉的票查詢可以打包為GET / tickets / recently_closed

限制API返回哪些欄位
API使用者並不總是需要資源的完整表示。選擇和選擇返回的欄位的能力在讓API使用方最大程度地減少網路流量並加快他們自己對API的使用方面大有幫助。
使用field作為查詢引數名,該引數採用逗號分隔的欄位列表。例如,以下請求將僅檢索足夠的資訊以顯示未清票的排序列表:
GET / tickets?fields = id,subject,customer_name,updated_at&state = open&sort = -updated_at

更新和建立應返回資源表示形式
PUT,POST或PATCH呼叫可能會對不屬於所提供引數的基礎資源欄位進行修改(例如:created_at或updated_at時間戳)。為了避免API使用者必須再次點選API以獲得更新的表示形式,請讓API返回更新(或建立的)表示形式作為響應的一部分。
如果是POST導致建立,請使用HTTP 201狀態程式碼幷包含一個指向新資源URL的Location標頭

你應該HATEOAS嗎?
關於API使用者是否應該建立連結或是否應該向API提供連結,存在很多不同的意見。RESTful設計原則指定了HATEOAS,它粗略地指出與端點的互動應該在輸出表示形式附帶的後設資料中定義,而不是基於邊界外資訊。
儘管網路通常可以使用HATEOAS型別原則(我們可以轉到網站的首頁並根據頁面上的連結訪問連結),但我認為我們還不準備在API上使用HATEOAS。瀏覽網站時,將在執行時決定要單擊的連結。但是,使用API​​時,將在編寫API整合程式碼時(而不是在執行時)決定傳送什麼請求。可以將決定推遲到執行時間嗎?當然,沿著這條路線沒有太多收穫,因為程式碼仍將無法處理重要的API更改而不會中斷。就是說,我認為HATEOAS很有前途,但還沒有準備好迎接黃金時段。必須付出更多的努力來圍繞這些原則定義標準和工具,以充分發揮其潛力。
現在,最好假設使用者可以訪問文件並在輸出表示中包含資源識別符號,API使用者在製作連結時將使用該識別符號。儲存識別符號有兩個優點-網路上的資料流被最小化,API使用者儲存的資料也被最小化(因為他們儲存的是小的識別符號,而不是包含識別符號的URL)。
同樣,鑑於此文章主張在URL中使用版本號,從長遠來看,對於API使用者而言,儲存資源識別符號而不是URL更有意義。畢竟,識別符號在各個版本中都是穩定的,但表示它的URL不穩定!

僅JSON響應
現在是時候將XML留在API中了。它很冗長,很難解析,很難閱讀,它的資料模型與大多數程式語言對資料建模的方式不相容,並且當您的輸出表示形式的主要需求是從內部表示形式進行序列化時,它的可擴充套件性優點就無關緊要。

媒體型別應該基於“Accept”標頭還是基於URL進行更改? 為了確保瀏覽器的可瀏覽性,它應該在URL中。這裡最明智的選擇是將.json或.xml副檔名附加到端點URL。

 大小寫snake_case和camel_case
如果您使用JSON(JavaScript物件表示法)作為主要表示格式,則“正確”的事情就是遵循JavaScript命名約定-這意味著欄位名稱為camelCase!如果您隨後採用各種語言構建客戶端庫的方法,則最好在它們中使用慣用的命名約定-對於C#和Java,使用camelCase,對於python&ruby,使用snake_case。

值得深思:我一直覺得snake_case比JavaScript的camelCase約定更易於閱讀。直到現在,我還沒有任何證據可以證明我的直覺。根據對2010 年的camelCase和snake_casePDF)進行的眼動研究,snake_case比camelCase的閱讀容易20%!對可讀性的影響將影響API的可探索​​性和文件中的示例。
許多流行的JSON API使用snake_case。我懷疑這是由於序列化庫遵循了它們所使用的基礎語言的命名約定。也許我們需要讓JSON序列化庫處理命名約定轉換。
駝峰:johnSmith;蛇形:john_smith

預設情況下漂亮列印並確保支援gzip
從瀏覽器看,提供空格壓縮輸出的API並不是很有趣。儘管可以提供某種查詢引數(例如?pretty = true)來啟用漂亮列印,但是預設情況下漂亮列印的API更加易於使用。額外資料傳輸的成本可以忽略不計,尤其是與不實施gzip的成本相比時。
考慮一些用例:如果API使用者正在除錯並且將其程式碼列印出從API接收到的資料,該怎麼辦-預設情況下可讀。或者,如果使用者獲取了他們的程式碼生成的URL並直接從瀏覽器中將其命中-預設情況下它將可讀。這些都是小事。使API易於使用的小東西!

但是,所有額外的資料傳輸又如何呢?
讓我們以一個真實的例子來看一下。我從GitHub的API中提取了一些資料,該API預設情況下使用漂亮的列印。我還進行一些gzip比較:

$ curl https://api.github.com/users/veesahni > with-whitespace.txt
$ ruby -r json -e 'puts JSON JSON.parse(STDIN.read)' < with-whitespace.txt > without-whitespace.txt
$ gzip -c with-whitespace.txt > with-whitespace.txt.gz
$ gzip -c without-whitespace.txt > without-whitespace.txt.gz

輸出檔案具有以下大小:
  • 不帶whitespace.txt -1252位元組
  • with-whitespace.txt -1369位元組
  • 不帶whitespace.txt.gz -496個位元組
  • with-whitespace.txt.gz -509位元組

在此示例中,當不使用gzip時,空白將輸出大小增加8.5%,當使用gzip時,空白將輸出大小增加2.6%。另一方面,gzip壓縮本身可以節省60%以上的頻寬。由於漂亮列印的成本相對較小,因此預設情況下最好進行漂亮列印,並確保支援gzip壓縮!

為了進一步說明這一點,Twitter發現,在其Streaming API上啟用gzip壓縮後,在某些情況下節省80%。Stack Exchange甚至做到了永不返回未經壓縮的響應

預設情況下不使用envelope信封,但在需要時可以使用信封
許多API如下將其響應包裝在信封中:

{
  "data" : {
    "id" : 123,
    "name" : "John"
  }
}

這樣做有兩個理由-它使得新增其他後設資料或分頁資訊變得容易,某些REST客戶端不允許輕鬆訪問HTTP標頭,而JSONP請求無法訪問HTTP標頭。但是,隨著諸如CORSRFC 5988中Link標頭之類的標準被迅速採用,信封變得不再必要。
我們可以透過預設情況下不使用信封並僅在特殊情況下進行封裝來證明API的未來。

在特殊情況下應如何使用信封?
在兩種情況下,確實需要使用信封-如果API需要透過JSONP支援跨域請求,或者客戶端無法使用HTTP標頭。
JSONP請求帶有附加的查詢引數(通常稱為callback或jsonp),該引數代表回撥函式的名稱。如果存在此引數,則API應切換到信封模式,在該模式下,API始終以200 HTTP狀態程式碼進行響應,並在JSON有效負載中傳遞實際狀態程式碼。應與響應一起傳遞的所有其他HTTP標頭都應對映到JSON欄位,如下所示:

callback_function({
  status_code: 200,
  next_page: "https://..",
  response: {
    ... actual JSON response body ... 
  }
})

類似地,要支援有限的HTTP客戶端,請允許一個特殊的查詢引數?envelope = true,它將觸發完全信封包裝(不使用JSONP回撥函式)。

JSON編碼的POST,PUT和PATCH正文
如果您遵循本文中的方法,那麼您已經將JSON用於所有API輸出。讓我們考慮使用JSON作為API輸入。
許多API在其API請求正文中使用URL編碼。URL編碼確實聽起來像是-請求正文,其中鍵值對的編碼約定與URL編碼引數中用於編碼資料的約定相同。這很簡單,得到了廣泛的支援,並且可以完成工作。
但是,URL編碼存在一些使其成為問題的問題。它沒有資料型別的概念。這會強制API從字串中解析整數和布林值。此外,它沒有層次結構的實際概念。儘管有一些約定可以從鍵值對中構建某些結構(例如將附加到表示陣列的鍵上),但這與JSON的本機分層結構沒有可比性。
如果API很簡單,則URL編碼就足夠了。但是,複雜的API應該堅持使用JSON作為其API輸入。無論哪種方式,請選擇一個並在整個API中保持一致。
接受JSON編碼的POST,PUT和PATCH請求的API還應要求將Content-Type標頭設定為application / json或丟擲415不支援的媒體型別HTTP狀態程式碼。

分頁
喜愛信封的API通常在信封本身中包含分頁資料。而且我不怪他們-直到最近,還沒有很多更好的選擇。如今包括分頁詳細資訊的正確方法是使用RFC 5988引入Link標頭
使用Link標頭的API可以返回一組現成的連結,因此API使用者不必自己構造連結。當分頁基於游標時,這尤其重要。這是從GitHub的文件中獲取的正確使用Link標頭的示例:

Link: <https://api.github.com/user/repos?page=3&per_page=100>; rel="next", <https://api.github.com/user/repos?page=50&per_page=100>; rel="last"


但這不是一個完整的解決方案,因為許多API都想返回其他分頁資訊,例如對可用結果總數的計數。需要傳送計數的API可以使用自定義HTTP標頭,例如X-Total-Count。

自動載入相關的資源表示
在許多情況下,API使用者需要從請求的資源中載入與(或引用)相關的資料。與其要求消費者反覆訪問API來獲取此資訊,不如讓相關資料隨需返回並與原始資源一起載入,將會顯著提高效率。
但是,由於這確實違反了一些RESTful原則,因此我們僅基於embed(或expand)查詢引數就可以使偏差最小。
在這種情況下,embed是要用逗號分隔的要插入欄位的列表。點符號可以用來指代子欄位。例如:
GET /tickets/12?embed=customer.name,assigned_user
這將返回包含其他詳細資訊的票證,例如:

{
  "id" : 12,
  "subject" : "I have a question!",
  "summary" : "Hi, ....",
  "customer" : {
    "name" : "Bob"
  },
  assigned_user: {
   "id" : 42,
   "name" : "Jim",
  }
}

當然,實現類似功能的能力實際上取決於內部複雜性。這種嵌入很容易導致N + 1選擇問題

覆蓋HTTP方法
某些HTTP客戶端只能使用簡單的GET和POST請求。為了增加對這些受限客戶端的訪問能力,API需要一種方法來覆蓋HTTP方法。儘管這裡沒有硬性標準,但流行的約定是接受帶有包含PUT,PATCH或DELETE之一的字串值的請求標頭X-HTTP-Method-Override。
請注意,重寫標頭僅應在POST請求中接受。GET請求永遠不要更改伺服器上的資料

限速
為了防止濫用,通常的做法是向API新增某種速率限制。 RFC 6585引入了HTTP狀態程式碼429 Too Many Requests To請求太多
但是,在實際達到限制之前通知消費者其限制可能非常有用。這個區域目前缺乏標準,但是使用HTTP響應標頭有許多流行的約定
至少包括以下標頭(使用Twitter的命名約定,因為標頭通常沒有中間單詞大寫):

  • X-Rate-Limit-Limit-當前期間允許的請求數
  • X-Rate-Limit-Remaining-當前期間的剩餘請求數
  • X-Rate-Limit-Reset-當前時段剩餘的秒數

為什麼使用剩餘的秒數代替X-Rate-Limit-Reset的時間戳?
時間戳包含各種有用但不必要的資訊,例如日期和可能的時區。API使用者實際上只是想知道何時可以再次傳送請求,而秒數可以用最少的額外處理來回答此問題。它還避免了與時鐘偏斜有關的問題。
某些API使用UNIX時間戳實現X-Rate-Limit-Reset。不要這樣做!

為什麼將UNIX時間戳用於X-Rate-Limit-Reset是不好的做法?
HTTP規範已經指定使用RFC 1123的日期格式(目前正在使用的日期如果-Modified-Since的上次修改的HTTP頭)。如果我們要指定一個採用某種時間戳的新HTTP標頭,則應遵循RFC 1123約定,而不要使用UNIX時間戳。

認證方式
RESTful API應該是無狀態的。這意味著請求身份驗證不應依賴Cookie或會話。相反,每個請求都應帶有某種身份驗證憑據。
透過始終使用SSL,可以將身份驗證憑據簡化為隨機生成的訪問令牌,該令牌在HTTP基本身份驗證的使用者名稱欄位中提供。這樣做的好處是,它完全可以被瀏覽器使用-如果瀏覽器從伺服器接收到401未經授權的狀態程式碼,則瀏覽器將彈出一個詢問憑據的提示。
但是,只有在切實可行的情況下,讓使用者將令牌從管理介面複製到API使用者環境時,這種身份驗證方法才可以接受。如果無法做到這一點,則應使用OAuth 2向第三方提供安全的令牌傳輸。OAuth 2使用Bearer令牌,並且還依賴SSL進行基礎傳輸加密。
需要支援JSONP的API將需要第三種身份驗證方法,因為JSONP請求無法傳送HTTP Basic Auth憑證或Bearer令牌。在這種情況下,可以使用特殊的查詢引數access_token。注意:使用令牌的查詢引數存在一個固有的安全問題,因為大多數Web伺服器將查詢引數儲存在伺服器日誌中。
值得一提的是,以上所有三種方法只是跨API邊界傳輸令牌的方法。實際的基礎令牌本身可以是相同的。

快取
HTTP提供了一個內建的快取框架!您要做的就是包括一些其他出站響應標頭,並在收到一些入站請求標頭時進行一些驗證。
有2種方法:ETagLast-Modified
ETag:生成響應時,包括HTTP標頭ETag,其中包含表示形式的雜湊或校驗和。每當輸出表示更改時,此值應更改。現在,如果入站HTTP請求包含具有匹配的ETag值的If-None-Match標頭,則API應該返回304 Not Modified狀態碼,而不是資源的輸出表示。
Last-Modified:除了使用時間戳外,此方法基本上類似於ETag。響應標頭Last-Modified包含RFC 1123格式的時間戳,該時間戳已針對If-Modified-Since進行了驗證。請注意,HTTP規範具有3種不同的可接受日期格式,伺服器應準備接受其中任何一種。

錯誤資訊
就像HTML錯誤頁面向訪問者顯示有用的錯誤訊息一樣,API應該以已知的消耗格式提供有用的錯誤訊息。錯誤的表示形式應與任何資源的表示形式相同,只是具有其自己的欄位集。
API應該始終返回明智的HTTP狀態程式碼。API錯誤通常分為兩種型別:用於客戶端問題的400系列狀態程式碼和用於伺服器問題的500系列狀態程式碼。該API至少應標準化所有400系列錯誤以及可消耗的JSON錯誤表示形式。如果可能(例如,如果負載平衡器和反向代理可以建立自定義錯誤主體),則該範圍應擴充套件到500系列狀態程式碼。
JSON錯誤主體應為開發人員提供一些幫助-有用的錯誤訊息,唯一的錯誤程式碼(可以在文件中查詢更多詳細資訊)以及可能的詳細說明。JSON輸出表示如下所示:

{
  "code" : 1234,
  "message" : "Something bad happened :(",
  "description" : "More details about the error here"
}

PUT,PATCH和POST請求的驗證錯誤將需要進行欄位細分。透過使用固定的頂級錯誤程式碼進行驗證失敗並在其他error欄位中提供詳細的錯誤,可以最好地對此建模,例如:


{
  "code" : 1024,
  "message" : "Validation Failed",
  "errors" : [
    {
      "code" : 5432,
      "field" : "first_name",
      "message" : "First name cannot have fancy characters"
    },
    {
       "code" : 5622,
       "field" : "password",
       "message" : "Password cannot be blank"
    }
  ]
}


HTTP狀態碼
HTTP定義了可以從您的API返回的一堆有意義的狀態程式碼。可以利用這些來幫助API使用者相應地路由其響應。我整理了一些您絕對應該使用的列表:

  • 200 OK-響應成功的GET,PUT,PATCH或DELETE。也可以用於不建立的POST。
  • 201已建立 -對導致建立的POST的響應。應與指向新資源位置的Location標頭結合使用
  • 204無內容 -對不會返回正文的成功請求的響應(如DELETE請求)
  • 304 Not Modified-在播放HTTP快取頭時使用
  • 400錯誤的請求 -請求格式錯誤,例如正文沒有解析
  • 401未經授權 -不提供或提供無效的身份驗證詳細資訊時。如果從瀏覽器使用API​​,則也可用於觸發auth彈出視窗
  • 403禁止 -身份驗證成功但經過身份驗證的使用者無權訪問資源時
  • 404 Not Found-當請求不存在的資源時
  • 405不允許的方法 -當請求透過身份驗證的使用者不允許的HTTP方法時
  • 410 Gone-指示此端點上的資源不再可用。可用作舊API版本的總括響應
  • 415不支援的媒體型別 -如果作為請求的一部分提供了錯誤的內容型別
  • 422無法處理的實體 -用於驗證錯誤
  • 429請求太多 -由於速率限制而拒絕請求時


API設計反面教材:哪些API最佳實踐表示您很討厭客戶?

相關文章