跳至內容

REST 和 HTTP 語義

更新時間
快连VPN:速度和安全性最佳的VPN服务
快连VPN:速度和安全性最佳的VPN服务

roy fielding 創建了 rest 作爲他的博士論文。 

讀完後,我會將其歸結爲三個基本要素:

  1. 描述對象狀態的文檔

  2. 在系統之間來回傳輸對象狀態的傳輸機制

  3. 對狀態執行的一組操作

雖然 Roy 只專注於 HTTP,但我不明白爲什麼不能使用其他傳輸方式。以下是一些示例:

  • 安裝 WebDAV 共享(WebDAV 是 HTTP 擴展,因此仍使用 HTTP)。將電子表格(.xls、.xlsx、.csv、.ods)複製到已安裝的文件夾中,其中每一行都是新的/更新的狀態。複製到共享的行爲表示更新插入操作,文件名錶示數據類型,列是字段。服務器以(文檔名稱)-status.(文檔後綴)進行響應,它提供每行的鍵、狀態以及可能的錯誤消息。在這種情況下,請求數據並沒有多大意義。

  • 使用 gRPC。傳輸的對象是文檔,HTTP 是傳輸,遠程方法的名稱是操作。數據可以提供和請求。

  • 使用 FTP。 與 WebDAV 類似,它是基於文件的。 PUT 命令是更新插入,GET 命令是請求。 GET 僅提供文件名,因此它通常提供指定類型的所有數據。可以允許使用特殊文件名來指示硬編碼過濾器以獲取數據子集。

每當我在野外看到 REST 實現時,它們通常不遵循基本的 HTTP語義學,我從未見過對此給出任何解釋,只是一堆不同的意見。我發現這些都沒有引用 RFC。大多數人似乎認爲:

  • POST = 創建

  • PUT = 更新整個文檔

  • PATCH = 更新文檔的一部分

  • GET = 檢索整個文檔

這與 HTTP 關於 POST 和 PUT 的規定相反:

  • PUT 是“創建”或“更新”。 GET 通常會返回上次 PUT 的內容。如果 PUT 創建,它必須返回 201 Created。如果 PUT 更新,它必須返回 200 OK 或 204 No Content。 RFC 建議 PUT 的 200 OK 內容應該是操作的狀態。我認爲就 SQL 而言,從 select 語句返回新行是可以的。這樣做的優點是,任何生成的列都會返回給調用者,而無需執行單獨的 GET。

  • POST 根據資源自身的語義處理資源。較舊的 RFC 表示 POST 適用於資源的下屬。所有版本都給出了將文章發佈到郵件列表的示例;所有版本都說,如果創建了資源,則應返回 201 Created。

我認爲 POST 的真正含義是:

  • 除創建、全部/部分更新或刪除之外的任何數據操作

  • 任何非數據操作的操作,例如:

  • 執行全文搜索與短語匹配的行。

  • 生成要在地圖上顯示的 GIS 對象。

該詞必須表示您的僅當您按照規定執行時,實現才符合 HTTP。僅使用 PUT 進行更新顯然不會破壞任何內容,只是因爲它不符合 RFC 標準。如果您提供處理發送/接收數據的所有細節的客戶端,那麼使用什麼動詞對於客戶端的用戶來說並不重要。

我是那種想要一個理由的人不遵循 RFC。我從來不理解在 REST API 中將創建與更新分開的重要性,就像在 Web 應用程序中一樣。想想日曆約會、筆記、聯繫人等手機應用程序:

  • “創建”點擊加號圖標,它會顯示一個帶有空值或默認值的新表單。

  • “更新”正在選擇一個對象並點擊鉛筆圖標,這將顯示包含當前值的條目表單。

  • 一旦條目表單出現,它就會顯示在字段驗證方面的工作方式完全相同。

那麼爲什麼 REST API 和 Web 前端與手機應用程序有任何不同呢?如果電話用戶獲得用於“創建”和“更新”的相同數據輸入表單有幫助,那麼它對 API 和網絡用戶是否也同樣有幫助?

如果您決定使用 PUT 作爲“創建”或“更新”,並且您使用 SQL 作爲存儲,大多數供應商都有某種類型的更新插入查詢。不幸的是,這無助於決定何時返回 200 OK 或 201 Created。您必須查看驅動程序在執行 DML 查詢時提供的信息,以找到區分更新插入的插入和更新的方法,或使用其他查詢策略。 

一個簡單的示例是執行更新集...其中 pk 列 = pk 值。如果一行受到影響,則該行存在並已更新;否則,該行不存在,需要插入。在 Postgres 上,您可以利用 RETURNING 子句,它實際上可以返回任何內容,而不僅僅是行數據,如下所示:

SQL VALUES (...) ON CONFLICT() DO UPDATE SET ( ...) 返回 (SELECT COUNT() FROMWHERE=) 存在" data-lang="text/x-sql" style="box-sizing: border-box;">1

INSERT INTO 
登錄後複製VALUES (...)ON CONFLICT() DOUPDATE SET (...)RETURNING (SELECT COUNT() FROM 
 WHERE  = ) exists

這樣做的天才在於:

  • RETURNING 子句中的子查詢首先執行,因此它會在執行 INSERT ON CONFLICT UPDATE 查詢之前確定該行是否存在。查詢的結果是名爲“exists”的列,如果該行在查詢之前存在,則該列爲 1。執行,如果沒有執行,則返回 0。

  • RETURNING 子句還可以返回行的列,包括未提供的任何生成內容。

您只需弄清楚如何處理是否需要插入或更新,並進行一個簡單的抽象,您的所有 PUT 都可以調用它來處理 200 OK 或 201 Created。

使用的一個很好的好處PUT 的目的是,一旦您看到 POST,您就確定它不是檢索或持久性,相反,您知道搜索 POST 來查找任何不是檢索或持久性操作的代碼。

我認爲按照 RFC 中的描述使用 PUT 和 POST 的好處超過了人們以不符合 RFC 的方式使用它們的任何原因。

以上就是REST 和 HTTP 語義的詳細內容,更多請關注本站其它相關文章!

更新時間

發表留言

請注意,留言須先通過審核才能發佈。