搜尋文件

輸入關鍵字,搜尋標題與正文。

    API文件 10/16

    方法與操作語意

    本文提要

    同一個文章 URI,可以用來讀取文章,也可以成為取代或刪除操作的目標。 要理解一次 HTTP 請求,除了問「指向哪個資源」,還要問「用戶端要求做什麼」。 HTTP 方法提供這層共同語意;它也影響自動讀取與失敗後重試時能依賴的承諾。

    文件與本文目錄
    本主題文件

    同一個文章 URI,可以用來讀取文章,也可以成為取代或刪除操作的目標。 要理解一次 HTTP 請求,除了問「指向哪個資源」,還要問「用戶端要求做什麼」。 HTTP 方法提供這層共同語意;它也影響自動讀取與失敗後重試時能依賴的承諾。

    本文接續〈資源、表示與訊息〉, 說明常見方法、安全方法(safe methods)與冪等性(idempotency)。 先備概念是資源、表示及請求/回應,不要求熟悉特定語言或框架。

    查證日期:2026-11-02。依據固定版本 RFC 9110(2022 年 6 月)與 RFC 5789(2010 年 3 月)。 本文只查閱文件;例子均為本站自創,未發送範例 HTTP 請求,也未實測服務。

    方法表達操作目的,不只是資料庫動詞

    方法(method)是請求語意的主要來源,表達用戶端的目的與預期成功結果。 標準方法有跨資源共用的意義,但個別資源仍決定是否實作或允許該方法。 因此,知道 PUT 的語意,不代表任何文章 URI 都能接受 PUT。 參考 RFC 9110 §9.1。

    以下挑出閱讀 HTTP API 時常見的方法;這不是 HTTP 方法的完整清單。

    表格・3 欄 7 列
    方法用戶端要求什麼容易誤讀的地方
    GET取得目標資源目前選定的表示不等於直接讀取資料庫列或磁碟檔案;見 §9.3.1
    HEAD與 GET 相同,但回應不得包含內容仍有回應與標頭,不代表伺服器不需處理;見 §9.3.2
    POST由目標資源依自身語意處理請求所帶的表示新增資源只是用途之一,也可能提交資料或附加資料;見 §9.3.3
    PUT以請求內容中的表示所定義的狀態,建立或取代目標資源的狀態用戶端已知道目標資源;不能泛解成「只更新有傳的欄位」;見 §9.3.4
    DELETE移除目標資源與其目前功能的關聯操作的是目標 URI 的對應關係,不保證抹除底層資料或回收儲存空間;見 §9.3.5
    OPTIONS詢問與目標資源通訊時可用的選項回應可以提供能力資訊,但不能據此假定會取得完整 API 文件;見 §9.3.7
    PATCH將請求內容所描述的一組變更指令套用至目標資源需理解補丁文件的媒體類型與規則,不是任意少傳幾個欄位;見 RFC 5789 §2

    HEAD 常用來取得選定表示的中繼資料,而不傳送表示資料。 伺服器原則上應提供與 GET 相同的標頭,但可以省略必須產生內容才能算出的欄位。 因此不能保證 HEAD 一定包含每個 GET 標頭,也不能從沒有回應內容推定它完全沒有運算成本。 參考 RFC 9110 §9.3.2。

    本文以 PUT 的一般建立/取代語意說明,不展開 RFC 9110 另述的部分 PUT 支援。 PATCH 的內容則是「如何修改」的指令,實際格式必須由服務支援的媒體類型決定。 參考 RFC 9110 §9.3.4與 RFC 5789 §2。

    在文章服務中對照 POST、PUT 與 PATCH

    前篇使用的是假想唯讀文章服務。本篇另假設一個允許管理文章的服務, 沿用文章資源來說明寫入語意;這不是替前篇服務新增已定義的功能。 以下都是概念上的操作步驟,不是完整 HTTP 訊息或可直接執行的請求。

    表格・3 欄 3 列
    自創情境本例採用的操作請求內容在本例的意義
    建立文章,讓服務選擇新文章 URI對 /articles 使用 POST提交建立文章所需資料,由集合資源依本例契約處理
    用戶端已知道目標是 /articles/42,要設定其完整文章狀態對 /articles/42 使用 PUT提供本例契約所要求的完整替代表示
    只要求將第 42 篇文章的標題改為「HTTP 方法」對 /articles/42 使用 PATCH以服務支援的補丁格式表達變更指令;本例不指定格式

    POST 與 PUT 的差別不能簡化成「新增對更新」:PUT 也可以建立目標資源; POST 是否新增,以及如何處理內容,取決於目標資源自己的語意。 若服務在收到請求後才替用戶端選擇新資源 URI,RFC 建議使用 POST。 參考 RFC 9110 §9.3.3–§9.3.4。

    表中的「完整」指本例公開契約所要求的替代表示,不表示用戶端必須知道所有內部欄位。 服務仍須定義哪些資料可寫、哪些輸入有效,以及不符合限制時如何回應。 PUT 的語意不會自動補齊應用規則;可回看〈輸入、輸出與失敗語意〉。

    安全方法:用戶端沒有要求改變狀態

    HTTP 的 safe 指方法定義的語意基本上是唯讀:用戶端沒有要求,也不預期藉這項操作改變來源伺服器狀態。 RFC 9110 將 GET、HEAD、OPTIONS 與 TRACE 定義為安全方法。 這裡的安全不是資安保證,也不代表不需身分驗證或授權。 參考 RFC 9110 §9.2.1。

    安全方法仍可能伴隨寫入。RFC 舉例:伺服器記錄每次存取,以及點擊廣告後對廣告帳戶計費, 都可能是讀取時附帶的影響。重點是這些不是用戶端以安全方法要求執行的狀態變更。 因此,看到存取紀錄增加,不能直接斷言 GET 違反安全語意;也不能把 safe 解讀為「完全沒有副作用」。 參考 RFC 9110 §9.2.1。

    相反地,若設計 GET /articles/42?do=delete,並依參數真的刪除文章, 這就是用戶端要求執行的刪除操作,不能用「只是 GET 的副作用」合理化。 RFC 要求資源擁有者在安全方法存取時禁止這類不安全操作, 以免爬蟲、預先擷取或連結檢查等自動讀取意外觸發它。 參考 RFC 9110 §9.2.1。

    冪等性:重複要求的預期效果與一次相同

    冪等(idempotent)指多次相同請求對伺服器的預期效果,與只做一次相同。 它討論用戶端要求的效果,不要求每次回應內容或狀態碼都一樣, 也不限制伺服器為每次請求各留一筆紀錄或版本歷史。 參考 RFC 9110 §9.2.2。

    表格・3 欄 4 列
    方法安全方法方法定義是否保證冪等
    GET、HEAD、OPTIONS、TRACE是是
    PUT、DELETE否是
    POST否否;具體操作可以另外有冪等保證
    PATCH否否;特定變更指令與契約可以做到冪等

    RFC 9110 將安全方法及 PUT、DELETE 定義為冪等;PATCH 則另由 RFC 5789 說明, 其方法本身不保證安全或冪等,但請求可以設計成冪等。 參考 RFC 9110 §9.2.1–§9.2.2與 RFC 5789 §2。

    回到自創文章服務,先假設請求皆被接受、沒有其他人同時修改文章:

    • 重複 PUT 同一份替代表示:第一次將文章設為指定狀態,再次仍要求同一狀態;改變狀態與冪等可以同時成立。
    • 重複 DELETE 同一目標:第一次刪除關聯成功,第二次回報找不到,仍可能符合冪等;要求的效果仍是移除該關聯。
    • 重複 POST 建立文章:若本例每次都分配新 URI,兩次就可能建立兩篇;沒有額外契約時,不能假定重送只新增一次。
    • 重複 PATCH:若契約是「將標題設為固定文字」,可以設計成冪等;若是「在標題末尾再附加一個字」,重複套用就可能持續改變。

    以上是用定義推演的教學對照,不是實測結果;尤其 PATCH 的實際效果仍取決於補丁格式與操作規則。 方法名稱表達契約,不能替實作排除錯誤;若 PUT 每重送一次就無條件增加閱讀次數作為請求目的, 就不能只憑名稱宣稱已符合冪等語意。

    未收到回應時,冪等性提供什麼依據

    假設用戶端送出 PUT,連線卻在讀到回應前中斷。 伺服器可能尚未套用,也可能已完成;「沒有收到成功回應」本身不足以區分兩者。 RFC 因此允許在讀到回應前發生通訊失敗時,自動重試冪等請求: 即使第一次已成功,重複相同請求仍有相同的預期效果,回應則可能不同。 參考 RFC 9110 §9.2.2。

    這不表示所有逾時都能直接重送。對非冪等方法,RFC 建議用戶端不要自動重試, 除非有辦法知道該操作的實際語意是冪等,或確認原請求從未被套用。 RFC 也建議不要在一次自動重試仍失敗後繼續自動重試;冪等不是無限制重送的許可。 具體重試次數、等待與結果確認策略,見逾時、重試與冪等性。 參考 RFC 9110 §9.2.2。

    冪等也不會自動解決多人更新衝突。假設甲、乙都先讀取舊文章, 甲 PUT 新內容後,乙又 PUT 自己從舊文章改出的完整表示,仍可能覆蓋甲的修改。 PUT 的冪等性沒有承諾保留其他人的更新;條件請求與更新衝突的處理,見快取與條件請求。 參考 RFC 9110 §9.3.4。

    閱讀 API 契約時,可以分別確認:方法要求的操作、目標是否允許該方法、 請求的應用規則,以及重複請求的保證。回應是否代表成功、失敗後已發生哪些影響, 仍須連同狀態碼及錯誤表示理解,不能只從方法名稱推定。

    相關文件