设计实用的RESTful API的最佳实践
關于REST API設計的文章。《星際戰士》游戲中暴露API的部分
API是開發人員的用戶界面——所以要努力讓它變得令人愉快
使用RESTful url和操作
在任何地方都使用SSL,沒有異常
一個API的好壞取決于它的文檔——所以要有優秀的文檔
版本通過URL,而不是通過頭
使用查詢參數進行高級過濾、排序和搜索
提供一種方法來限制從API返回哪些字段
從POST, PATCH和PUT請求返回一些有用的東西
HATEOAS目前還不實用
盡可能使用JSON,必要時只使用XML
你應該在JSON中使用camelCase,但是snake_case要容易閱讀20%
默認為漂亮的打印&確保支持gzip
默認情況下不要使用回復信封
考慮將JSON用于POST、PUT和PATCH請求體
使用鏈接標頭進行分頁
提供一種自動加載相關資源表示的方法
提供一種重寫HTTP方法的方法
為速率限制提供有用的響應標頭
使用基于令牌的身份驗證,在需要委托的地方通過OAuth2傳輸
包括響應頭以方便緩存
定義一個可消耗的錯誤有效負載
有效地使用HTTP狀態碼
API的關鍵需求
為了幫助指導決策過程,我寫下了API必須達到的一些要求:
- 它應該在有意義的地方使用網絡標準
- 它應該對開發人員友好,并且可以通過瀏覽器地址欄進行探索
- 它應該簡單,直觀和一致,使采用不僅容易,而且令人愉快
- 它應該為大多數Enchant UI提供足夠的靈活性
- 它應該是高效的,同時保持與其他需求的平衡
API是開發人員的UI——就像任何UI一樣,確保用戶的體驗是經過仔細考慮的很重要!
使用RESTful url和操作
REST的關鍵原則包括將API分離為邏輯資源。使用HTTP請求操作這些資源,其中方法(GET、POST、PUT、PATCH、DELETE)具有特定的含義。
但是我能做什么資源呢?從API使用者的角度來看,這些應該是有意義的名詞,而不是動詞。Enchant的一些名詞是ticket, user和customer。
注意:盡管您的內部模型可以整齊地映射到資源,但這并不一定是一對一的映射。這里的關鍵是不要將無關的實現細節泄露給API!你的API資源需要從API使用者的角度來看是有意義的。
一旦定義了資源,就需要確定哪些操作應用于它們,以及這些操作如何映射到API。RESTful原則提供了使用映射如下的HTTP方法處理CRUD操作的策略:
- GET /tickets—檢索一個票的列表
- GET /tickets/12 -檢索一個特定的票
- POST /tickets -創建一個新票
- PUT /tickets/12 -更新票號12
- PATCH /tickets/12 -部分更新12號票
- DELETE /tickets/12 -刪除票號12
REST的優點是利用現有的HTTP方法在單個/tickets端點上實現重要的功能。沒有方法命名約定,URL結構干凈清晰。其他增值!
端點名稱應該是單數還是復數?保持簡單的原則也適用于此。實用的答案是保持URL格式一致并始終使用復數。不必處理奇復數(person/people, goose/geese)使API使用者的生活變得更好
但是你如何處理關系呢?如果一個關系只能存在于另一個資源中,RESTful原則提供了有用的指導。讓我們看一個例子。《Enchant》中的一張票由許多消息組成。這些消息可以邏輯上映射到/tickets端點,如下所示:
GET /tickets/12/messages -檢索票號12的消息列表
GET /tickets/12/messages/5 -檢索票號12的消息#5
POST /tickets/12/messages -在ticket #12中創建一個新消息
PUT /tickets/12/messages/5 -更新票號12的消息#5
PATCH /tickets/12/messages/5 -部分更新了票號12的消息#5
DELETE /tickets/12/messages/5 -刪除票號12的消息#5
替代方案1:如果關系可以獨立于資源而存在,那么在資源的輸出表示中只包含它的標識符是有意義的。然后,API使用者必須到達關系的端點。
替代方案2:如果一個獨立存在的關系通常與資源一起被請求,那么API可以提供自動嵌入關系表示的功能,并避免對API的第二次攻擊。干凈的API和一個命中服務器。
不適合CRUD操作的操作怎么辦?
這就是事情可能變得模糊的地方。有很多方法:
重新構造操作,使其看起來像資源的字段。如果操作不帶參數,這是有效的。例如,一個激活操作可以映射到一個布爾激活字段,并通過補丁更新到資源。
將其視為具有RESTful原則的子資源。例如,GitHub的API允許你用PUT /gist /:id/星號標記gist,用DELETE /gist /:id/星號標記非星號。
有時確實沒有辦法將操作映射到合理的RESTful結構。例如,將多資源搜索應用于特定資源的端點實際上沒有意義。在這種情況下,/search最有意義,即使它不是資源。這是可以的-只要從API使用者的角度做正確的事情,并確保清楚地記錄以避免混淆。
https://www.vinaysahni.com/best-practices-for-a-pragmatic-restful-api#requirements
在任何地方都使用SSL,沒有異常
始終使用SSL。沒有例外。今天,您的web api可以從任何有互聯網的地方訪問(如圖書館、咖啡店、機場等)。并非所有這些都是安全的。許多人根本不加密通信,如果身份驗證憑證被劫持,就很容易被竊聽或模仿。
始終使用SSL的另一個優點是,有保證的加密通信簡化了身份驗證工作——您可以使用簡單的訪問令牌,而不必為每個API請求簽名。
要注意的一件事是對API url的非ssl訪問。不要將它們重定向到對應的SSL。而是拋出一個嚴重的錯誤!當自動重定向到位時,配置不良的客戶端可能會在未加密的端點上不知不覺地泄漏請求參數。硬錯誤可確保及早捕獲此錯誤并正確配置客戶端。
文檔
API的好壞取決于它的文檔。文檔應該很容易找到,并且公眾可以訪問。大多數開發人員在嘗試任何集成工作之前都會檢查文檔。當文檔隱藏在PDF文件中或需要登錄時,它們不僅很難找到,而且也不容易搜索。
文檔應該展示完整的請求/響應周期示例。請求最好是可粘貼的示例——可以粘貼到瀏覽器的鏈接或可以粘貼到終端的curl示例。GitHub和Stripe在這方面做得很好。
一旦你發布了一個公共API,你已經承諾不會在沒有通知的情況下破壞它。文檔必須包括任何棄用計劃和外部可見的API更新的細節。更新應該通過博客(即更新日志)或郵件列表(最好兩者都有!)
版本
一定要對API進行版本化。版本控制可以幫助您更快地迭代,并防止無效請求擊中已更新的端點。它還有助于平滑任何主要API版本的轉換,因為您可以在一段時間內繼續提供舊的API版本。
關于API版本應該包含在URL中還是包含在頭文件中,人們有不同的看法。從學術角度來說,它應該在標題中。但是,版本需要在URL中,以確保跨版本資源的瀏覽器可探索性(還記得本文頂部指定的API需求嗎?),并為開發人員提供更簡單的體驗。
我是Stripe對API版本控制方法的忠實粉絲——URL有一個主版本號(v1),但API有基于日期的子版本,可以使用自定義HTTP請求頭來選擇。在這種情況下,主版本提供了API的整體結構穩定性,而子版本則負責較小的更改(字段棄用、端點更改等)。
API永遠不會完全穩定。改變是不可避免的。重要的是如何管理這種變化。對許多api來說,良好記錄和公布的數月棄用計劃是一種可接受的實踐。歸根結底,考慮到API的行業和可能的消費者,什么是合理的。
結果篩選,排序和搜索
最好保持基本資源url盡可能精簡。復雜的結果過濾器、排序需求和高級搜索(當限制為單一類型的資源時)都可以作為基本URL頂部的查詢參數輕松實現。讓我們更詳細地看看這些:
過濾:為實現過濾的每個字段使用唯一的查詢參數。例如,當從/tickets端點請求門票列表時,您可能希望將這些限制為僅處于打開狀態的門票。這可以通過類似GET /tickets?state=open這樣的請求來完成。這里,state是一個實現篩選器的查詢參數。
排序:與篩選類似,可以使用泛型參數排序來描述排序規則。通過讓排序參數接受一個由逗號分隔的字段列表,每個字段都可能帶有一個一元負來表示降序排序,從而滿足復雜的排序需求。讓我們來看一些例子:
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的使用。
使用字段查詢參數,該參數接受一個以逗號分隔的字段列表。例如,下面的請求將檢索足夠的信息來顯示已排序的未開票列表:
GET /tickets?fields=id,subject,updated_at&state=open&sort=-updated_at
注意:此方法也可以與相關資源的自動加載相結合:
GET /tickets?embed=customer&fields=id,customer.id,customer.name
更新和創建應該返回一個資源表現物
PUT, POST或PATCH調用可以對底層資源的字段進行修改,這些字段不是提供的參數的一部分(例如:created_at或updated_at時間戳)。為了防止API使用者為了更新的表示而不得不再次訪問API,可以讓API返回更新的(或創建的)資源作為響應的一部分。
在POST導致創建的情況下,使用HTTP 201狀態碼并包括指向新資源URL的Location頭。除了包含新創建的資源表示形式作為響應主體外,還應該包含這兩個。
HATEOAS目前還不實用
對于API使用者是否應該創建鏈接,或者是否應該將鏈接提供給API,有很多不同的意見。rest式設計原則指定了HATEOAS,它大致規定了與端點的交互應該在輸出表示附帶的元數據中定義,而不是基于帶外信息。
雖然網絡通常是基于HATEOAS類型的原則(我們進入一個網站的首頁,并根據我們在頁面上看到的鏈接進行鏈接),但我認為我們還沒有準備好在api上使用HATEOAS。在瀏覽網站時,將點擊哪些鏈接是在運行時做出的決定。然而,對于API,關于發送什么請求的決定是在編寫API集成代碼時做出的,而不是在運行時做出的。決策是否可以延遲到運行時?當然,沿著這條路走下去也沒有什么好處,因為代碼仍然不能在不破壞的情況下處理重大的API更改。也就是說,我認為HATEOAS很有前途,但還沒有準備好進入黃金時段。必須投入更多的努力來定義標準和圍繞這些原則的工具,以充分實現其潛力。
現在,最好假設用戶可以訪問文檔,并在輸出表示中包含資源標識符,API消費者在制作鏈接時將使用這些標識符。堅持使用標識符有幾個好處——在網絡上流動的數據被最小化,API使用者存儲的數據也被最小化(因為它們存儲的是小標識符,而不是包含標識符的url)。
此外,鑒于這篇文章提倡在URL中存儲版本號,從長遠來看,API使用者存儲資源標識符比存儲URL更有意義。畢竟,標識符在不同版本之間是穩定的,但表示它的URL不是!
盡可能使用JSON,必要時只使用XML
XML并不是API的最佳選擇。它很冗長,很難解析,也很難閱讀,它的數據模型與大多數編程語言的數據模型不兼容,當輸出表示的主要需求是從內部表示序列化時,它的可擴展性優勢就不重要了。我還可以繼續……
我不打算花太多精力解釋這個。需要注意的關鍵是,今天您將很難找到任何仍然支持XML的主要API。你也不應該。
也就是說,如果您的客戶基礎由大量的企業客戶組成,您可能會發現自己無論如何都必須支持XML。如果你一定要這么做,你會發現自己有一個新問題:
媒體類型應該根據Accept headers 更改還是根據URL更改?為了確保瀏覽器的可探索性,它應該在URL中。這里最明智的選擇是將.json或.xml擴展名附加到端點URL。
字段名的snake_case vs camelCase
如果你使用JSON (JavaScript對象表示法)作為你的主要表示格式,“正確”的事情是遵循JavaScript命名約定——這意味著字段名的駱駝格!如果你選擇用各種語言構建客戶端庫,最好使用它們的慣用命名約定——c#和Java使用camelCase, python和ruby使用snake_case。
精神食糧:我一直覺得snake_case比JavaScript約定的camelCase更容易閱讀。我只是沒有任何證據來支持我的直覺,直到現在。基于2010年對camelCase和snake_case的眼球追蹤研究,snake_case比camelCase容易閱讀20% !這種對可讀性的影響將影響API的可探索性和文檔中的示例。
許多流行的JSON api都使用snake_case。我懷疑這是由于服務器端序列化庫遵循它們內置的底層語言的命名約定。也許我們需要讓JSON序列化庫處理命名約定轉換。
默認為漂亮的打印&確保支持gzip
An API that provides white-space compressed output isn't very fun to look at from a browser. Although some sort of query parameter (like ?pretty=true) could be provided to enable pretty printing, an API that pretty prints by default is much more approachable. The cost of the extra data transfer is negligible, especially when you compare to the cost of not implementing gzip.提供white-space輸出的API從瀏覽器上看并不是很有趣。雖然可以提供一些查詢參數(比如?pretty=true)來啟用漂亮打印,但在默認情況下,漂亮打印的API要容易得多。額外數據傳輸的成本可以忽略不計,特別是與不實現gzip的成本相比。
考慮一些用例:如果API使用者正在調試,并讓他們的代碼打印出從API接收到的數據——在默認情況下,這些數據是可讀的。或者,如果消費者獲取了他們的代碼生成的URL,并直接從瀏覽器中點擊它——默認情況下,它將是可讀的。這些都是小事。讓API使用起來更愉快的小事情!
但是所有額外的數據傳輸怎么辦?
讓我們用一個真實的例子來看看這個問題。我從https://api.github.com/users/veesahni中提取了一些數據,該API默認使用漂亮的打印。我也會做一些gzip比較:
curl https://api.github.com/users/veesahni > with-whitespace.txt$ ruby -r json -e 'puts 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輸出文件的大小:
without-whitespace.txt - 1221 bytes
with-whitespace.txt - 1290 bytes
without-whitespace.txt.gz - 477 bytes
with-whitespace.txt.gz - 480 bytes
在本例中,當沒有使用gzip時,空白使輸出大小增加5.7%,當使用gzip時增加0.6%。另一方面,gzip本身提供了超過60%的帶寬節省。由于漂亮打印的成本相對較小,最好在默認情況下進行漂亮打印,并確保支持gzip壓縮!
不要默認使用信封,但在需要時可以使用
許多api將它們的響應包裝在這樣的信封中:
{"data" : {"id" : 123,"name" : "John"} }這樣做有幾個理由——它可以很容易地包含額外的元數據或分頁信息,一些REST客戶機不允許容易地訪問HTTP headers& JSONP請求不能訪問HTTP headers。然而,隨著諸如CORS(https://fetch.spec.whatwg.org/)和RFC 5988中的Link頭等標準的迅速采用,封裝開始變得沒有必要。
我們可以通過在默認情況下保持無信封并且只在特殊情況下進行信封來證明API。
在特殊情況下如何使用信封?
有兩種情況確實需要信封——如果API需要支持JSONP上的跨域請求,或者如果客戶端不能使用HTTP報頭。
為了支持跨域JSONP:這些請求附帶一個額外的查詢參數(通常命名為callback或JSONP),表示回調函數的名稱。如果該參數存在,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體
如果您遵循本文中的方法,那么您已經接受了所有API輸出的JSON。讓我們考慮JSON作為API輸入。
許多API在其API請求體中使用URL編碼。URL編碼就像它聽起來的那樣——請求體中鍵值對的編碼使用與URL查詢參數中編碼數據相同的約定。這很簡單,得到廣泛支持,可以完成工作。
但是,URL編碼有一些問題。它沒有數據類型的概念。這迫使API從字符串中解析整數和布爾值。此外,它沒有真正的層次結構概念。盡管有一些約定可以從鍵值對中構建一些結構(比如將[]附加到鍵后以表示數組),但這與JSON的原生層次結構是無法相比的。
如果API很簡單,我認為URL編碼就足夠了。但我認為這與輸出格式不一致。
對于基于JSON的API,也應該堅持使用JSON進行API輸入。
接受JSON編碼的POST, PUT和PATCH請求的API還應該要求Content-Type報頭設置為application/ JSON或拋出415不支持的媒體類型HTTP狀態碼。
分頁
喜歡封裝的api通常在封裝本身中包含分頁數據。我不怪他們——直到最近,也沒有多少更好的選擇。現在包含分頁細節的正確方法是使用RFC 8288引入的Link頭。
使用Link頭的API可以返回一組現成的鏈接,這樣API使用者就不必自己構造鏈接了。當分頁是基于游標時,這一點尤其重要。下面是一個正確使用Link頭的例子,摘自GitHub的文檔:
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方法的方法。雖然這里沒有任何硬標準,但流行的慣例是接受請求頭X-HTTP-Method-Override,其中包含PUT、PATCH或DELETE之一的字符串值。
注意,重寫頭應該只在POST請求上被接受。GET請求不應該改變服務器上的數據!
速度限制
為了防止濫用,標準做法是向API添加某種速率限制。RFC 6585引入了 HTTP狀態碼429 Too Many Requests來適應這種情況。
但是,在實際達到極限之前通知消費者它們的極限是非常有用的。這是一個目前缺乏標準的領域,但有許多使用HTTP響應標頭的流行約定。
至少要包含以下頭文件:
X-Rate-Limit-Limit -當前時間段允許的請求數
X-Rate-Limit-Remaining -當前期間剩余的請求數
X-Rate-Limit-Reset -當前周期剩余的秒數
為什么X-Rate-Limit-Reset使用的是剩余秒數而不是時間戳?
時間戳包含各種有用但不必要的信息,比如日期,可能還有時區。API使用者實際上只想知道他們什么時候可以再次發送請求&用最少的額外處理來回答這個問題的秒數。它還避免了與時鐘傾斜相關的問題。
一些api使用UNIX時間戳(從epoch開始的秒)進行X-Rate-Limit-Reset。不要這樣做!
為什么對X-Rate-Limit-Reset使用UNIX時間戳是不好的做法?
HTTP規范已經指定使用RFC 1123日期格式(目前在date, If-Modified-Since & Last-Modified HTTP報頭中使用)。如果要指定一個接受某種時間戳的新HTTP標頭,它應該遵循RFC 1123約定,而不是使用UNIX時間戳。
身份驗證
RESTful API應該是無狀態的。這意味著請求身份驗證不應該依賴于cookie或會話。相反,每個請求都應該帶有某種排序身份驗證憑據。
通過始終使用SSL,身份驗證憑據可以簡化為在HTTP基本身份驗證的用戶名字段中傳遞的隨機生成的訪問令牌。這樣做的好處是它完全是瀏覽器可探索的——如果瀏覽器從服務器接收到401未授權狀態碼,它會彈出一個提示,要求提供憑據。
但是,這種基于基本身份驗證的令牌方法僅適用于讓用戶將令牌從管理接口復制到API使用者環境的實際情況。在不可能實現這一點的情況下,OAuth 2應該用于向第三方提供安全的令牌傳輸。OAuth 2使用持名令牌,并依賴SSL進行底層傳輸加密。
需要支持JSONP的API將需要第三種身份驗證方法,因為JSONP請求不能發送HTTP基本身份驗證憑據或承載令牌。在這種情況下,可以使用一個特殊的查詢參數access_token。注意:使用令牌查詢參數存在固有的安全問題,因為大多數web服務器將查詢參數存儲在服務器日志中。
不管怎樣,上面的三個方法都只是跨API邊界傳輸令牌的方法。實際的底層令牌本身可能是相同的。
緩存
HTTP提供了一個內置的緩存框架!您所要做的就是包含一些額外的出站響應標頭,并在收到一些入站請求標頭時進行一些驗證。
有兩種方法:ETag和Last-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種可接受的日期格式,服務器應該準備好接受其中任何一種。
Errors
就像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請求的驗證錯誤將需要字段分解。最好的建模方法是使用一個固定的頂級錯誤代碼來驗證失敗,并在一個額外的錯誤字段中提供詳細的錯誤,如下所示:
{"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 status codes
HTTP定義了一堆有意義的狀態代碼,這些代碼可以從API返回。可以利用這些來幫助API使用者相應地路由其響應。我整理了一個簡短的清單,你一定要使用:
200 OK -響應成功的GET, PUT, PATCH或DELETE操作。也可以用于不產生創建的POST。
201 Created -對創建POST的響應。應該與指向新資源位置的Location頭相結合嗎
204 No Content -響應一個成功的請求,但不會返回body(比如DELETE請求)
304未修改-當HTTP緩存頭正在使用時使用
400 Bad Request——請求格式不正確,比如請求體沒有解析
401未經授權-沒有提供或無效的身份驗證詳細信息。如果API是從瀏覽器中使用,那么觸發一個驗證彈出框也很有用
403 Forbidden -認證成功,但認證用戶不能訪問資源
404 Not Found -當請求一個不存在的資源時
405方法不允許-當請求的HTTP方法不允許被驗證的用戶使用時
410 Gone -表示該端點的資源不再可用。作為舊API版本的通用響應非常有用
415不支持的媒體類型-如果在請求中提供了錯誤的內容類型
422不可處理實體-用于驗證錯誤
429請求過多-由于速率限制,請求被拒絕
總結
API是面向開發人員的用戶界面。努力確保它不僅是功能性的,而且使用起來也很愉快。
原文
總結
以上是生活随笔為你收集整理的设计实用的RESTful API的最佳实践的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Oracle减小数据文件大小
- 下一篇: 计算机二级笔记