我有一個資源,例如“書”。
我想創建一個 REST POST 端點以允許消費者創建一本新書。
但是,有些屬性是API需要和計算的,而其他屬性實際上是按原樣獲取的
Book
{
name,
color,
author # computed
}
假設作者是根據書名在 API 中以某種方式計算出來的。
我可以想到這些解決方案每個都有其缺點:
- 強制消費者提供作者并過濾它(不考慮作為輸入)#不好,因為作者被更改的原因非常不可預測
- 允許用戶提供作者#同樣的問題
- 不允許用戶提供作者并在用戶提供時顯示例外
最后一個解決方案似乎是最明顯的一個。我能看到的主要問題是它不一致,消費者稍后在 GET 請求中看到作者可能會很奇怪。
我希望我的 POST 端點盡可能具有表現力。因此 POST 和 GET 資料傳輸物件看起來幾乎相同。
是否有任何簡單、富有表現力和可預測的模式可供考慮?
uj5u.com熱心網友回復:
就我個人而言,我非常喜歡使用相同格式的GET請求以及PUT.
這使得客戶端可以執行GET請求,將屬性添加到他們收到的物件并立即PUT再次。如果您的 API 和客戶端遵循這種模式,這也意味著它可以輕松地向GET請求添加新屬性而不會破壞客戶端。
然而,雖然這是一個很好的模式,但我并不認為對“創造”存在同樣的期望。在創建新專案時,通常有很多東西可以減少對屬性的要求(例如考慮“id”),所以我通常:
PUT為和定義模式GET。- 為其定義一個單獨的模式,
POST該模式僅包含用于創建的相關屬性。 - 如果用戶提供架構中沒有的屬性,總是會出現錯誤
422。
uj5u.com熱心網友回復:
一些屬性是必需的,由 API 計算
根據定義,計算屬性既不是必需的,也不是可選的。沒有理由要求消費者傳遞此類屬性。
不允許用戶提供作者并在用戶提供時顯示例外
實際上,DTO 不應包含作者屬性。消費者可以通過網路發送任何他們想要的東西,但是 API 提供者有責任發布合同 (DTO) 以供消費者正確使用。API 提供者控制要考慮的屬性,并且不應拋出例外,因為消費者可以發送的“壞”屬性的數量是無窮無盡的。
因此 POST 和 GET 資料傳輸物件看起來幾乎相同
使相同資源的 DTO 看起來相同并不是目標。在許多情況下,對于同一資源,get-operation 比 post-operation 暴露更多的屬性,尤其是在設計領域驅動的 API 時。
是否有任何簡單、富有表現力和可預測的模式可供考慮?
如果您希望您的 API 表達計算作者的事實,您可以使用以下端點:
發布 http://.../author-computed-books
獲取 http://.../books/1
就個人而言,我不會那樣實作,因為它看起來不自然,但是您可以理解。
uj5u.com熱心網友回復:
我希望我的 POST 端點盡可能具有表現力。因此 POST 和 GET 資料傳輸物件看起來幾乎相同。
也許只是記錄它而不是依賴像它必須與 GET 端點幾乎相同的顯式內容。
例如,我的 POST 端點是POST /number "1011",我的 GET 端點是GET /number -> 11. 如果我沒有記錄我期望二進制并且我提供十進制,那么沒有人會知道并且他們會猜測例如兩者都是十進制的。除了檔案之外,另一種更明確的方法是更改?? GET 的回應以包含基礎{"base":10, value:"11"}或更改 GET 端點GET /number/decimal -> 11。
作為計算作者,我不明白你將如何計算它。我的意思是要么一本書已經注冊,消費者不應該再次注冊它,要么你對它的作者不太了解。如果是后者,那么您可以根據標題的 google 搜索結果進行猜測,但這只是猜測,不一定正確。消費者資料也是如此,但至少這是消費者提供的。沒有確定性。所以對我來說,如果資訊的來源很重要,這將是一個復雜的屬性,而不僅僅是一個原始屬性。通常"author": {name: "John Wayne", "source": "consumer/service"}情況下,它也很復雜,因為作者往往有 ID、姓名、其他書籍等。
另一個想法是,如果這對消費者來說很奇怪而不是預期,那么我根本不知道為什么它是一個功能。如果作者猜測是一項服務,那么一個可能的解決方案是強制屬性并添加猜測服務GET /author?by-book-name={book-name},以便他們可以根據需要使用該服務。或者與完全可選的屬性相同。這樣,您就可以將控制權交還給消費者,決定他們是否要使用此服務。
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/525021.html
標籤:api休息哎呀设计模式
