HTTP QUERY 方法:透過 RFC 10008 解決複雜的 API 查詢

HTTP QUERY 方法:透過 RFC 10008 解決複雜的 API 查詢

RFC 10008 定義了新的 HTTP QUERY 方法,為需要請求主體的複雜唯讀操作提供了一種標準化的方式。這解決了 GET 查詢參數的限制與使用 POST 進行數據檢索在語義上的不正確性之間長期存在的緊張關係。

為什麼 HTTP QUERY 方法是必要的

HTTP QUERY 方法之所以必要,是因為現有的方法無法在不損害技術穩定性或 API 語義的情況下,高效地處理複雜的關聯查詢或深層嵌套的數據結構。

GET 的限制

雖然 GET 是檢索數據的標準,但它依賴於 URL 中的查詢參數。這種方法在幾種情境下會失效:

  • URL 長度限制: 複雜的篩選條件可能會產生巨大的 URL,從而超過瀏覽器或伺服器的字元限制。
  • 編碼開銷: 非 ASCII 或特殊字元必須經過編碼,這會增加請求的大小。
  • 安全性與日誌記錄: 請求參數通常會被伺服器和中間件記錄下來,這可能會暴露敏感數據。
  • 缺乏結構: 在 URL 中表達陣列或深層嵌套結構沒有通用標準(例如:?roles[]=admin?roles=admin)。

GET 帶有請求主體的失敗案例

雖然沒有任何 RFC 明確禁止在 GET 請求中使用請求主體,但強烈建議不要這樣做。在實務中,許多客戶端、代理伺服器和 Web 伺服器對 GET 主體的處理方式不一致——有些會直接拒絕,有些則會完全丟棄主體。這使得帶有主體的 GET 在生產環境中成為一個不可靠的選擇。

POST 的語義問題

開發者經常使用 POST 作為一種變通方法,透過發送請求主體來進行查詢。然而,POST 被定義為非冪等(non-idempotent),且旨在用於資源的創建或處理。這會產生幾個問題:

  • 重試機制: 因為 POST 不是冪等的,在失敗時進行自動重試是有風險的。
  • Caching: 代理伺服器和中間件無法自動將 POST 請求識別為唯讀,從而阻礙了標準緩存機制的使用。

QUERY 方法的技術規範

QUERY 方法旨在功能上與 GET 類似,但明確支持請求主體。其主要特徵包括:

  • 安全性與冪等性: 與 GET 一樣,QUERY 被定義為安全且冪等的,這意味著它不會改變伺服器的狀態。
  • 可緩存性: QUERY 請求可以被緩存。然而,實作方式必須將請求主體納入緩存金鑰(cache key),以確保針對不同的查詢參數能返回正確的數據。

實作考量與注意事項

儘管進行了標準化,QUERY 方法並非所有搜尋端點的直接替換方案。開發者應考慮以下限制:

  • 有限的生態系統支持: 目前對 QUERY 的支持仍然有限。許多代理伺服器、防火牆和 Web 伺服器可能仍會拒絕該方法。例如,雖然 Kreya API client 在 1.20 版本中增加了支持,但廣泛的採用可能需要數年時間。
  • 可連結性: QUERY 請求無法透過簡單的 URL 進行書籤標記或分享,因為查詢參數存在於請求主體中,而非 URL 中。
  • Caching 複雜度: 為 QUERY 實作自定義緩存比為 GET 實作更為複雜,因為緩存金鑰必須從請求主體中衍生出來。

社群觀點與評論

工程師之間的討論凸顯了支持明確標準與偏好遵循現有慣例之間的分歧。

支持新方法的論點

有些人認為,擁有一個明確的方法是唯一正確的前進方式,因為使用帶有主體的 GET 是一種不應被標準化的「黑客行為」(hack)。

反對新方法的論點

批評者建議,標準應該遵循現有的「GET 帶有主體」的慣例,並認為引入新動詞可能會對舊有基礎設施造成問題。一位用戶指出,當僅支持 HTTP/1.1 的昂貴 SSL 中間件代理設備遇到未知的 HTTP 動詞時,存在「DoS by the track record」的風險。

其他開發者也質疑,僅僅為了支持請求主體而增加一個新方法,是否為維護 HTTP 規範長期相關性的最佳方式,並暗示這可能是一種「阻力最小的路徑」,而非穩健的設計。

Sources