我已經閱讀了很多關于400vs的問題422,但它們幾乎是針對 HTTPPOST請求的,例如這個:400 vs 422 response to POST of data。
我仍然不確定GET在發送帶有錯誤值的所需引數時應該使用什么。想象一下這個場景:
- 我有端點
/searchDeclaration,帶有引數type。 - 我的宣告有兩種型別:TypeA和TypeB。
所以,我可以這樣呼叫這個端點:/searchDeclaration?type=TypeA獲取所有TypeA宣告。
當有人用無效的端點呼叫端點時,我應該發送什么錯誤type?例如:/searchDeclaration?type=Type123
我應該發送400嗎?我不確定它是不是最好的代碼,因為引數是正確的,只有值是無效的。
該422代碼看起來更適合POST請求。
編輯:
經過一些回應,我還有另一個疑問。端點將/searchDeclaration回傳經過身份驗證的用戶的宣告。A型和TypeB是有效值,但是有些用戶沒有提交TypeB宣告,那么當他們呼叫時/searchDeclaration?type=TypeB我應該發送哪個錯誤?回傳404似乎不正確,因為 URI 是正確的,但該用戶還沒有該值的宣告。這是我想太多了嗎?
uj5u.com熱心網友回復:
如果 URI 錯誤,請使用404 Not Found。
404(未找到)狀態碼表示源服務器沒有找到目標資源的當前表示
這那樣,目標資源由目標 URI 標識。
除了回應的語意之外,404 表示回應是可快取的——這意味著通用快取將知道它們可以將此回應重新用于未來的請求
我不確定它是不是最好的代碼,因為引數是正確的,只有值是無效的。
事實上,這URI 包含引數和值我們在 HTTP 級別不關心的東西。
隨便:404表示“URI拼寫錯誤”;但不會嘗試區分 URI 的哪些部分有錯誤。該資訊可以包含在回應正文中,作為錯誤情況說明的一部分。
這是我想太多了嗎?
不,但我認為你還沒有考慮正確的事情。
您發現這一挑戰的原因之一是您有多個邏輯資源共享同一個目標 URI。如果每個用戶宣告檔案都有自己的唯一識別符號,那么選擇正確的回應語意的練習將更加直接。
另一種處理方式是將客戶端重定向到更具體的 URI,然后以直接的方式處理那里的回應語意。
它試圖為不同的邏輯資源使用一個通用的 URI,并在不需要額外的往返行程的情況下做出回應。壞訊息:這是在設計資源識別符號時應該考慮的權衡之一;如果您不希望這需要更加努力的思考,請不要使用這種設計。
好訊息:404 仍然沒問題 - 您正在處理授權請求,關于共享對授權請求的回應的規則意味著唯一可能的混淆是不同用戶共享相同的私有快取。
請記住:部分原因是所有資源共享一個通用的通用訊息詞匯表。一切都應該看起來像是由無聊的 Web 服務器提供的檔案。
資源背后存在大量復雜含義的事實是正確隱藏在統一介面后面的實作細節。
uj5u.com熱心網友回復:
有兩種選擇,這完全取決于您的“ type”變數。
如果 '
type' 是一個ENUM,只允許 'typeA' 和 'typeB',并且你的客戶端發送 'type123',服務會回應一個 '400 Bad Request'error,你不需要檢查。在我看來,這應該是理想的,因為如果您將來需要添加新的 'type's,您只需將它們添加到 中ENUM,而不是在代碼中執行 'if-else' 來檢查它們。如果 'type' 變數是 a
String,控制器將承認 'type123' 并且您應該是回傳錯誤的人,因為客戶端請求不是格式錯誤,而是它試圖訪問不存在的資源。
在這種情況下,您可以回傳一個404 Not Found error, (找不到客戶端過濾的資源),或者422 error如您所說的,因為服務器理解請求,但無法處理它。
uj5u.com熱心網友回復:
讓我們假設您正在查詢的資源正在回傳一組包含某些屬性的條目。如果您不指定過濾器,您基本上將獲得這些條目的(可分頁)表示,作為嵌入物件或作為指向這些資源的鏈接。
現在您要根據這些條目的某些屬性過濾結果。如今,大多數編程語言都以以下形式提供了一些 lambda 功能
List filteredList = list.filter(item => item.propertyX == ...)...;
這種過濾函式的結果通常是滿足指定條件的專案串列。如果沒有專案滿足給定條件,則結果將是一個空串列。
可以類似地設計在 Web 上應用某些過濾條件。當提供的過濾器運算式沒有產生任何條目時,這真的是一個錯誤嗎?IMO 就實際訊息傳輸本身而言,這不是錯誤,因為服務器能夠毫無問題地接收和決議請求。因此,它必須是某種業務規則,規定只允許允許的值作為輸入。
如果您或您的公司考慮為屬性提供的過濾器值不回傳結果作為錯誤的情況,或者您對接收到的有效負載(對于復雜請求)執行一些即 XML 或 JSON 模式驗證,那么我們應該看看那些提到的 HTTP錯誤定義:
400 (Bad Request) 狀態碼表示服務器不能或不會處理請求,因為某些東西被認為是客戶端錯誤(例如,格式錯誤的請求語法、無效的請求訊息幀或欺騙性請求路由)。(來源:RFC 7230)
在這里,顯然您不想處理帶有無效屬性值的請求并因此拒絕請求。
422(Unprocessable Entity)狀態碼意味著服務器理解請求物體的內容型別(因此 415(Unsupported Media Type)狀態碼是不合適的),并且請求物體的語法是正確的(因此是 400(Bad Request) ) 狀態碼不合適)但無法處理包含的指令。例如,如果 XML 請求正文包含格式正確(即語法正確)但語意錯誤的 XML 指令,則可能會出現這種錯誤情況。(來源:RFC 4918 (WebDAV))
在這種情況下,您基本上說有效負載實際上在語法上是正確的,但在語意層面上失敗了。
請注意,它422 Unprocessable Entity源于 WebDAV,而400 Bad Request在 HTTP 規范中定義。如果您的 API 服務于任意 HTTP 客戶端,這可能會產生一些影響。那些只知道并支持 HTTP 規范中定義的 HTTP 錯誤代碼的人將無法真正確定422回應的語意。他們仍會將其視為用戶錯誤,但無法在該問題上為客戶提供更多幫助。因此,如果您的 API 需要盡可能通用,請堅持使用400 Bad Request. 如果您確定所有客戶都支持422 Unprocessable Entity該服務。
一般改進提示
當您用休息,讓我們看看如何改進這種情況。
REST 是一種架構風格,旨在將客戶端與服務器分離,以使前者更能容忍故障,同時允許后者隨著時間的推移自由發展。因此,這種架構中的服務器應該為客戶端提供客戶端發出有效請求所需的所有東西。為了避免讓客戶端預先知道服務器期望的輸入,服務器通常會提供某種輸入掩碼,客戶端可以使用它來填充服務器需要的內容。
在可瀏覽的 Web 上,這通常由HTML 表單完成。該表單不僅教您的客戶端將請求發送到哪里、使用哪個 HTTP 操作以及請求實際使用的表示格式(通常隱含地給出application/x-www-form-urlencoded),而且還教您服務器支持的結構和屬性。
在 HTML 表單中,服務器很容易通過使用類似以下內容的方式來限制客戶端的輸入選擇
<form action="/target">
<label for="cars">Choose a car:</label>
<select name="cars" id="cars">
<option value="volvo">Volvo</option>
<option value="saab">Saab</option>
<option value="opel">Opel</option>
<option value="audi">Audi</option>
</select>
<br/>
<input type="submit" value="Submit">
</form>
這并沒有真正消除在服務器端檢查和驗證請求的正確性的需要,很難讓客戶端更容易實際執行有效請求。
不幸的是,HTML 表單本身也有其局限性。即他們只允許POST和GET請求成為問題。雖然encType默認為application/x-www-form-urlencoded,但如果您想傳輸檔案,您應該使用multipart/form-data. 除此之外,任何有效的內容型別都應該是可接受的。
如果您更喜歡基于 JSON 的有效負載而不是 HTML,您可能需要查看JSON Forms、HAL forms、Ion Forms等。
請注意,您應該遵守內容型別協商原則。大多數情況下,主動內容型別協商是在客戶端發送其首選項時執行的Accept,服務器將以某種方式選擇最佳匹配并回傳映射到該表示格式的資源或回應406 Not Acceptable回應。雖然該標準不會阻止在這種情況下回傳默認表示,但它存在客戶端將無法處理此類回應的危險。此處更好的替代方法是回退到反應式協商,在這種協商中,服務器回應300 Muliple Choice回應,客戶端必須選擇提供的替代方案之一,然后發送一個GET對所選替代 URI 的請求以檢索有效負載中的內容可能能夠處理。
如果您想提供客戶端可以用來檢索過濾結果的簡單鏈接,服務器應該已經為客戶端提供完整的 URI 以及客戶端可以用來查找 URI的鏈接關系名稱和/或擴展關系型別如果感興趣,可以檢索內容。
表單和鏈接關系支持都屬于 HATEOAS 的范疇,因為它們有助于消除對任何外部檔案(如 OpenAPI 或 Swagger 檔案)的需求。
總而言之,我會重新考慮提供的不存在的財產價值是否真的應該以商業失敗告終。我認為在這里回傳一個空串列就可以了,因為您清楚地指出,對于給定的標準,無法獲得任何結果。如果您仍然想堅持業務錯誤,請檢查哪些客戶端實際使用了您的 API。如果他們支持422去那個。如果您不知道,最好堅持400所有 HTTP 客戶端都應該理解的內容。
為了消除以發出無效屬性值的請求而告終的可能性,使用表單來教客戶請求應該是什么樣子。通過某些元素或屬性,您已經可以告訴客戶只有一組有限的選擇對某個屬性有效。除了表單之外,您還可以提供客戶端可以用來獲取過濾結果的專用鏈接。然后確保使用有意義的鏈接相關名稱發布這些鏈接。
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/484452.html
上一篇:工廠模式
