API請求失敗後發生了什麼?

{"type":"doc","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"當一個API請求沒能成功的時候,客戶端最好能收到一個正確的HTTP錯誤狀態,例如409或500,這會是一個好的開始。不幸的是,儘管400 Bad Request可能就足夠讓我們知道錯誤出在哪裏,但常見的情況是我們沒有充足的信息來理解或解決實際遇到的問題。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"許多API會在響應正文中爲你提供更多細節,但令人遺憾的是,每個API都有自己的定製風格,不同的API,甚至在各個端點使用的報告樣式都不一樣。這就需要定製的邏輯或者人工干預才能理解報告的內容。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"但這種情況並非無可避免。先不用急着否定我。試着想象一個更好的世界,其中每個API都以相同的標準格式返回錯誤信息。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"我們可以用一致的標識符來識別各種類型的錯誤,並能在任何地方輕鬆獲得清晰的描述和元數據。你的通用HTTP客戶端可以自動爲任何錯誤提供詳盡細節,你的客戶端錯誤處理機制則能輕鬆可靠地過濾出你所關心的特定錯誤,並且你能使用單組共享邏輯來處理多種API的常見錯誤。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"IETF提出的RFC 7807標準希望定義一個HTTP API錯誤響應的標準格式,從而實現上述目標。它已經開始在現實世界中得到應用了。人們可以很容易地用它來支持現有的API和客戶端,對於構建或使用HTTP API的人來說,這個標準值得關注。"}]},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"標準錯誤格式爲什麼這麼有用?"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/a9\/a95598c1b2d1e1c3f6e0b1b3dc759dfa.jpeg","alt":null,"title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":"center","origin":null},"content":[{"type":"text","text":"請不要這樣做"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"談這個問題前,讓我們先退一步思考問題。HTTP的一個關鍵特性是標準的響應狀態代碼,例如200或404。正確使用這些代碼可確保客戶端自動理解響應的總體狀態,並根據對應狀態採取適當措施。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"狀態代碼對錯誤處理來說特別有用。當請求收到意外的500狀態時,幾乎所有標準的HTTP客戶端都會自動爲你拋出一個錯誤,並不需要自定義規則來解析和解釋各處的所有響應,從而確保意外錯誤能被可靠地報告,並可以在任何位置輕鬆處理。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"這是很好的機制,但它也有很大的侷限性。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"實際上,一個HTTP 400響應可能表示以下任何一種情況:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"你的請求格式錯誤,無法解析"}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"你的請求意外爲空,或缺少一些必需的參數"}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"你的請求有效,但仍然模棱兩可,因此無法處理"}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"你的請求有效,但由於服務器錯誤,服務器認爲請求無效"}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"你的請求有效,但請求的是完全不可能的內容"}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"你的請求已啓動,但服務器拒絕了你提供的參數值"}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"你的請求已啓動,但服務器拒絕了你提供的每個參數值"}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"你的請求已啓動,但你的銀行拒絕了其中包含的銀行卡資料"}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"你的請求完成了一項購買操作,但請求的其他部分在稍後階段被拒絕"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"這些全是錯誤,看起來都是由一個“壞”請求觸發的400錯誤,但它們的內容卻大相徑庭。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"狀態代碼可幫助我們區分錯誤和成功狀態,但沒法區分得太細緻。因此,HTTP客戶端庫不能在拋出的錯誤中包含任何有用的細節,每個API客戶端都必須編寫自定義的處理機制來解析每個失敗的響應,並自行找出可能的原因和下一步應該做的操作。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"如果失敗的HTTP請求自動拋出的異常消息不僅僅是"},{"type":"codeinline","content":[{"type":"text","text":"HTTP Error: 400 Bad Request"}]},{"type":"text","text":",而是Credit card number is not valid,這樣豈不更好?"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"只要錯誤有一套標準格式,上面提到的每個錯誤就都可以有自己的唯一標識符,幷包含標準化的說明內容和指向更多細節的鏈接。好處是:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"通用工具可以爲你解析和解釋錯誤的詳細信息,而無需事先了解任何與API相關的信息。"}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"API能更安全地發起錯誤響應,因爲它知道這些錯誤類型標識符意味着即使解釋消息發生了更改,客戶端也會一直按同一種理解方式識別錯誤。"}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"自定義API客戶端可以檢查錯誤類型以輕鬆處理特定情況,所有操作都以一種標準方式進行,適用於你所使用的每個API,而無需從頭開始編寫API包裝程序,也用不着每次都和API文檔大戰三百回合。"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"提案的錯誤格式長什麼樣?"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"爲此,RFC7807提出了一組用於返回錯誤的標準字段,以及兩種將其格式化爲JSON或XML的內容類型。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"格式如下:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"plain"},"content":[{"type":"text","text":"{\n \"type\": \"https:\/\/example.com\/probs\/out-of-credit\",\n \"title\": \"You do not have enough credit.\",\n \"detail\": \"Your current balance is 30, but that costs 50.\",\n \"instance\": \"\/account\/12345\/transactions\/abc\"\n}"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"對於XML的等效格式:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"plain"},"content":[{"type":"text","text":"\n\n https:\/\/example.com\/probs\/out-of-credit\n You do not have enough credit.\n <detail>Your current balance is 30, but that costs 50.\n <instance>\/account\/12345\/transactions\/abc\n"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"這些RFC爲此定義了兩種新的對應內容類型:"},{"type":"codeinline","content":[{"type":"text","text":"application\/problem+json"}]},{"type":"text","text":"或"},{"type":"codeinline","content":[{"type":"text","text":"application\/problem+xml"}]},{"type":"text","text":"。返回錯誤的HTTP響應應在其"},{"type":"codeinline","content":[{"type":"text","text":"Content-Type"}]},{"type":"text","text":"響應標頭中包含適當的內容類型,並且客戶端可以檢查該標頭以確認格式。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"這個示例包括規範定義的一些標準化字段。完整列表是如下:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"type"}]},{"type":"text","text":":標識錯誤類型的URI。在瀏覽器中加載這個URI應該轉向這個錯誤的文檔,但這不是嚴格要求的。此字段可用於識別錯誤類。理論上講,將來站點甚至可以爲常見情況共享標準化的錯誤URI,以使通用客戶端自動檢測到它們。"}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"title"}]},{"type":"text","text":":錯誤的簡短可讀摘要。這是明確的指引,客戶端必須使用type作爲識別API錯誤類型的主要方式。"}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"detail"}]},{"type":"text","text":":較長的人類可讀解釋,帶有完整的錯誤詳細信息。"}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"status"}]},{"type":"text","text":":錯誤使用的HTTP狀態代碼。它必須與實際狀態匹配,但可以包含在這裏的body中以便參考。"}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"instance"}]},{"type":"text","text":":標識該特定故障實例的URI。它可以作爲發生的這個錯誤的ID,和\/或到特定故障更多詳細信息的鏈接,例如顯示失敗的信用卡交易細節的頁面。"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"所有這些字段都是可選的(不過"},{"type":"codeinline","content":[{"type":"text","text":"type"}]},{"type":"text","text":"是強烈建議使用的)。內容類型允許自由包含其他數據,只要它們不與這些字段衝突即可,因此你也可以在此處添加自己的錯誤元數據,幷包含所需的其他任何數據。實例URI和類型URI都可以是絕對URI,也可以是相對URI。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"這裏的思想是:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"通過返回帶有合適"},{"type":"codeinline","content":[{"type":"text","text":"Content-Type"}]},{"type":"text","text":"標頭的錯誤響應,API能很容易地表明它們正在遵循這一標準。"}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"這是一組簡單的字段,可以輕鬆添加到大多數現有的錯誤響應頂部(如果還沒有添加的話)。"}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"客戶端只需在請求中包含"},{"type":"codeinline","content":[{"type":"text","text":"Accept: application\/problem+json"}]},{"type":"text","text":"(和\/或+xml)標頭,即可輕鬆表明支持狀態,從而在必要時進行遷移。"}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"客戶端邏輯可以輕鬆識別這些響應,並使用它們來顯著改善通用和按API區分的HTTP錯誤處理操作。"}]}]}]},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"怎樣開始使用它呢?"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"目前,這是一個提案的標準,因此它尚未普及,並且在理論上可能會發生變化。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"不過它已經用在很多地方,包括5G標準之類中,並且有了適用於大多數語言和框架的一些便捷工具,包括:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"link","attrs":{"href":"https:\/\/docs.microsoft.com\/en-us\/dotnet\/api\/microsoft.aspnetcore.mvc.problemdetails?view=aspnetcore-5.0","title":"","type":null},"content":[{"type":"text","text":"ASP.NET的內置支持"}]}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Node.js的"},{"type":"link","attrs":{"href":"https:\/\/www.npmjs.com\/package\/http-problem-details","title":"","type":null},"content":[{"type":"text","text":"通用庫"}]},{"type":"text","text":"和"},{"type":"link","attrs":{"href":"https:\/\/www.npmjs.com\/package\/express-http-problem-details","title":"","type":null},"content":[{"type":"text","text":"Express庫"}]}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Java的"},{"type":"link","attrs":{"href":"https:\/\/github.com\/zalando\/problem","title":"","type":null},"content":[{"type":"text","text":"通用庫"}]},{"type":"text","text":"和"},{"type":"link","attrs":{"href":"https:\/\/github.com\/zalando\/problem-spring-web","title":"","type":null},"content":[{"type":"text","text":"Spring Web MVC庫"}]}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Python的"},{"type":"link","attrs":{"href":"https:\/\/pypi.org\/project\/httpproblem\/","title":"","type":null},"content":[{"type":"text","text":"通用庫"}]},{"type":"text","text":"和"},{"type":"link","attrs":{"href":"https:\/\/pypi.org\/project\/drf-problems\/","title":"","type":null},"content":[{"type":"text","text":"Django REST API庫"}]}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Ruby的"},{"type":"link","attrs":{"href":"https:\/\/rubygems.org\/gems\/problem_details","title":"","type":null},"content":[{"type":"text","text":"通用"}]},{"type":"text","text":"、"},{"type":"link","attrs":{"href":"https:\/\/rubygems.org\/gems\/problem_details-rails","title":"","type":null},"content":[{"type":"text","text":"Rails"}]},{"type":"text","text":"和"},{"type":"link","attrs":{"href":"https:\/\/rubygems.org\/gems\/sinatra-problem_details","title":"","type":null},"content":[{"type":"text","text":"Sinatra庫"}]}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"PHP的"},{"type":"link","attrs":{"href":"https:\/\/packagist.org\/packages\/phpro\/api-problem","title":"","type":null},"content":[{"type":"text","text":"通用庫"}]},{"type":"text","text":"和"},{"type":"link","attrs":{"href":"https:\/\/packagist.org\/packages\/phpro\/api-problem-bundle","title":"","type":null},"content":[{"type":"text","text":"Symfony庫"}]}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"link","attrs":{"href":"https:\/\/crates.io\/crates\/http-api-problem","title":"","type":null},"content":[{"type":"text","text":"Rust"}]},{"type":"text","text":"、"},{"type":"link","attrs":{"href":"https:\/\/github.com\/lpar\/problem","title":"","type":null},"content":[{"type":"text","text":"Go"}]},{"type":"text","text":"、"},{"type":"link","attrs":{"href":"https:\/\/github.com\/wix\/rest-rfc7807","title":"","type":null},"content":[{"type":"text","text":"Scala"}]},{"type":"text","text":"、"},{"type":"link","attrs":{"href":"https:\/\/hackage.haskell.org\/package\/http-rfc7807","title":"","type":null},"content":[{"type":"text","text":"Haskell"}]},{"type":"text","text":"的庫..."}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"也就是說,它已經滲透到了大多數主流生態系統中站穩了腳跟,並且即將更進一步:讓更多API和客戶端開始使用,直到實現大規模的普及狀態,即大多數API的錯誤格式都遵循其標準,使它成爲所有場景的默認值,讓我們大家都能從中受益。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"我們該如何做到這一點呢?"}]},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"如果你在構建或維護一個API:"}]},{"type":"bulletedlist","content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"如果可以的話,請嘗試使用適當的"},{"type":"codeinline","content":[{"type":"text","text":"Content-Type"}]},{"type":"text","text":"響應標頭以"},{"type":"link","attrs":{"href":"https:\/\/tools.ietf.org\/html\/rfc7807","title":"","type":null},"content":[{"type":"text","text":"RFC 7807"}]},{"type":"text","text":"格式返回錯誤。"}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"如果你有了一種錯誤格式,並且需要維護該格式以保證兼容性,請檢查是否可以在格式頂部添加這些字段,並對其進行擴展以符合標準。"}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"如果不能,請嘗試檢測傳入的"},{"type":"codeinline","content":[{"type":"text","text":"Accept"}]},{"type":"text","text":"標頭中的支持,並在可能的情況下使用它來將原有的錯誤格式切換爲標準格式。"}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"使用你的API​​框架(比如"},{"type":"link","attrs":{"href":"https:\/\/github.com\/spring-projects\/spring-boot\/issues\/19525","title":"","type":null},"content":[{"type":"text","text":"這個框架"}]},{"type":"text","text":")記錄錯誤,表明它們將來會轉向標準錯誤格式。"}]}]}]},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"如果你在使用一個API:"}]},{"type":"bulletedlist","content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"檢查這些內容類型的錯誤響應,並用那裏提供的數據改進你的錯誤報告和處理工作。"}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"考慮在請求中包含帶有這些內容類型的"},{"type":"codeinline","content":[{"type":"text","text":"Accept"}]},{"type":"text","text":"標頭,以表明支持狀態並在可用時啓用標準錯誤。"}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"向你使用的API提出抱怨,希望它們以這種標準格式返回錯誤,就像抱怨那些不會費心返回正確狀態代碼的API一樣。"}]}]}]},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"至於大家:"}]},{"type":"bulletedlist","content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"參與其中!這是IETF新的“HTTP API的構建塊”工作組旗下的規範。你可以加入"},{"type":"link","attrs":{"href":"https:\/\/www.ietf.org\/mailman\/listinfo\/httpapi","title":"","type":null},"content":[{"type":"text","text":"郵件列表"}]},{"type":"text","text":"以閱讀並參與有關該規範和其他可行API標準規範規範的討論,包括"},{"type":"link","attrs":{"href":"https:\/\/datatracker.ietf.org\/doc\/draft-polli-ratelimit-headers\/","title":"","type":null},"content":[{"type":"text","text":"速率限制"}]},{"type":"text","text":"和"},{"type":"link","attrs":{"href":"https:\/\/datatracker.ietf.org\/doc\/draft-dalal-deprecation-header\/","title":"","type":null},"content":[{"type":"text","text":"API棄用"}]},{"type":"text","text":"等。"}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"向你的同事和開發者朋友做宣傳,並幫助大家簡化錯誤處理的工作。"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"原文鏈接:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"link","attrs":{"href":"https:\/\/httptoolkit.tech\/blog\/http-api-problem-details\/","title":null,"type":null},"content":[{"type":"text","text":"https:\/\/httptoolkit.tech\/blog\/http-api-problem-details\/"}]}]}]}</instance></detail>
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章