RFC 10008: HTTP QUERY 方法
RFC 10008 定義了 HTTP 的 QUERY 方法,為需要請求主體的安全且冪等請求提供了一種標準化方式。此方法彌補了 GET(安全且冪等,但通常受限於 URI 長度)與 POST(支援請求主體,但預設既非安全也非冪等)之間的差距。
問題所在:URI 長度與方法語義
傳統上,HTTP 用戶端使用 GET 進行查詢,透過 URI 查詢字串傳遞參數。然而,當查詢數據過於龐大而無法放入 URI 時,開發者通常會求助於 POST。雖然 POST 支援請求主體,但它缺乏自動重試與中間代理進行高效快取所需的安全與冪等語義。
RFC 10008 透過引入 QUERY 來解決此問題,它允許將查詢操作的輸入作為請求內容傳遞,同時明確保持安全與冪等的特性。
QUERY 方法的核心屬性
QUERY 方法旨在作為複雜查詢時 GET 的直接替代方案。其主要特徵包括:
- 安全且冪等:與
GET一樣,QUERY請求不會改變目標資源的狀態,且可以多次重複執行而不會產生副作用。這使得基礎設施能夠在連線失敗後進行自動重試。 - 請求主體:與
GET不同,QUERY預期會有一個請求主體(查詢內容)以及對應的Content-Type標頭。如果Content-Type缺失或與內容不符,伺服器必須使請求失敗。 - 可快取:對
QUERY請求的響應是可快取的。快取金鑰必須包含請求內容及相關元數據。為了提高效率,快取可以對請求內容進行正規化,以移除語義上不顯著的差異。
HTTP 方法比較
| 屬性 | GET | QUERY | POST |
|---|---|---|---|
| 安全 | 是 | 是 | 可能不是 |
| 冪等 | 是 | 是 | 可能不是 |
| 請求主體 | 無定義語義 | 預期 | 預期 |
| 可快取 | 是 | 是 | 是(有限) |
資源識別與重新導向
為了維持「重要資源應透過 URI 識別」的原則,RFC 10008 描述了伺服器如何將 QUERY 請求映射到 URI:
- 等效資源:伺服器可以為「等效資源」分配一個 URI——即代表特定
QUERY請求及其目標的資源。如果分配了該 URI,則可以在Location響應標頭中提供,允許用戶端切換到GET進行後續請求。 - Content-Location:成功的響應可能包含一個
Content-Location標頭,用以識別持有操作結果的資源,該資源可以透過GET取得。 - 重新導向:
QUERY支援標準 HTTP 重新導向(301, 302, 307, 308)。303 (See Other) 響應特別指出,原始查詢可以透過對Location標頭中的 URI 發起GET請求來完成。
探索與實作
伺服器可以使用以下機制來發送支援 QUERY 方法及其接受的格式訊號:
- OPTIONS 方法:用戶端可以使用
OPTIONS來發現QUERY是否列在Allow標頭中。 - Accept-Query 標頭:一個新的結構化欄位
Accept-Query允許資源列出其支援的特定查詢格式媒體類型(例如application/sql,application/jsonpath+json)。
安全性與效能考量
安全性
當查詢參數包含敏感資訊時,優先使用 QUERY 而非 GET,因為 URI 比請求主體更容易被中間代理記錄下來。然而,伺服器在為結果建立臨時 URI 時(透過 Location 或 Content-Location),應確保這些 URI 不會洩漏原始請求中的敏感數據。
CORS
由於 QUERY 不在 CORS 安全名單(safelisted)的方法中,來自瀏覽器用戶端代理的請求將需要進行 CORS 預檢請求(preflight request)。
社群觀點
開發者之間關於 RFC 10008 的討論揭示了支持者與擔憂採用率及技術開銷的人之間的意見分歧:
"我喜歡這可以輕易地擴展到讓 JS EventSource 在串流 AI 查詢上運作…… EventSource 因為某些頑固的原因只能使用 GET。"
"如果包含一個強而有力的動機範例,或許能幫助推廣這項提案……將請求主體作為快取金鑰的一部分感覺非常奇怪。"
"I'm seeing the advantages of using this, but I can't help feel like momentum is going to be strongly against adoption."
"這讓我感到高興,老實說,當我在處理強大的 API 時,我從來都不喜歡建立
POST /search端點。"