HTTP 規定

本文說明 Google API 如何與不同 HTTP 版本和實作搭配運作。如果您使用其中一種我們所產生或手動編寫的用戶端程式庫 (大部分的用途都建議使用這種做法),就不需要擔心這一點,因為所提供的程式碼會處理低層級的伺服器通訊問題。

不過,如果您是經驗豐富的開發人員,且需要使用您所選的第三方 HTTP 用戶端程式庫,自行編寫自訂程式碼來直接存取 API 的 REST 介面,則應瞭解至少幾種本文件中與您所選 API 相關的語意,並瞭解您的 HTTP 程式庫提供的內容。

使用傳輸通訊協定 (HTTP/*)

本節說明 Cloud API 可用來在用戶端和伺服器之間通訊的受支援傳輸通訊協定 (通常是 HTTP 的版本),以及這些通訊協定的建議使用方式。下一節會深入說明要求和回應的建構方式。

HTTP 語意

開發 API 用戶端程式碼時,請遵循標準 HTTP 通訊協定語意。伺服器端 Proxy 或 API 堆疊可能只支援標準 HTTP 功能的子集,也可能支援其回溯相容版本。

必須由伺服器端 API 實作處理的 HTTP 通訊協定語意是由伺服器堆疊控管。只有在這些功能明確記載為屬於 API 規格的一部分 (例如快取支援) 時,才可依賴這類語意。

HTTP 版本

用戶端可使用用戶端平台或其用戶端網路允許的任何 HTTP/* 通訊協定,或與伺服器端 Proxy 交涉的任何 HTTP/* 通訊協定。支援的通訊協定包括 HTTP/1.0、HTTP/1.1、SPDY/*、HTTP/2 和 QUIC。

部分 API 功能可能只有較新版本的 HTTP 通訊協定支援,例如伺服器推送和優先順序;有些功能則只有 HTTP/2 提供完整支援,例如全雙工串流。如果您需要任何這些功能做為 API 規格的一部分,請注意不同 HTTP 版本的限制。

一般建議使用 HTTP/2 以獲得較佳效能,並在網路發生問題時有較佳的恢復能力。

管道

管道指的是 L4 網路連線 (TCP 或 UDP 通訊端)。用戶端應用程式不應假設系統會如何在執行階段中使用管道來處理 HTTP 要求。在幾乎所有的情況下,Proxy 會代表伺服器流程終止管道。

針對 HTTP/1.1 用戶端,請一律重複使用 TCP 連線 (連線:保持運作);HTTP 用戶端程式庫也可能會管理連線集區以獲得較佳效能。請勿透過相同的 TCP 連線來傳輸要求。詳情請參閱 HTTP 和 TCP 一文。

新型瀏覽器全都使用 SPDY/*、HTTP/2 或 QUIC (會透過單一管道對要求進行多路複用)。除非伺服器實作會限制來自單一用戶端的並行 HTTP 要求數量,例如 100 個 HTTP/2 串流對一個來源,否則傳統連線限制 (2 到 10 個) 應該永遠不會是問題。

HTTPS

用戶端可根據 API 規格的支援情況,透過 HTTPS 或 HTTP 存取 API。TLS 交涉和 TLS 版本對用戶端應用程式而言是公開透明的。根據預設,Google API 只接受 HTTPS 流量。

要求/回應格式

要求網址

JSON 與 REST 的對應支援網址編碼要求資料,且 HTTP 要求和回應主體是使用 application/json 做為 Content-Type

HTTP 主體使用 JSON 陣列來支援串流 RPC 方法,且 JSON 陣列可包含任意數量的 JSON 訊息或錯誤狀態 JSON 訊息。

較長的要求網址

網址有實際長度限制,預設通常為 16 KB,但實際情況可能因伺服器而異。如果 API 使用的 GET 要求所含網址超出此長度,要求可能無法送達目的地 API 伺服器,且會遭 Google Front End (GFE) 拒絕,並顯示 Your client has issued a malformed or illegal request. 錯誤訊息。

如要規避這類限制,用戶端程式碼應使用 POST 要求,其中含有 application/x-www-form-urlencoded 的 Content-Type 和 HTTP 標頭 X-HTTP-Method-Override: GET。這種方法也適用於 DELETE 要求。

HTTP 方法 (動詞)

如果要求網址遵循 REST 模型,其 HTTP 方法會列在 API 規格中。特別要注意的是,每個 API 方法都必須符合 HTTP 通訊協定的要求,實際要求視 API 方法對應的特定 HTTP 動詞而定。詳情請參閱超文字傳輸通訊協定規格和 PATCH 方法 RFC。

HTTP GETHEAD安全方法不應代表擷取以外的動作。具體來說,HTTP GET 應視為「安全」的方法,而不應有任何用戶端可見的副作用。

HTTP 中的Idempotence表示多個相同要求和單一要求的副作用相同。GETPUTDELETE 是與本風格指南相關的冪等 HTTP 方法。請注意,冪等性只會以伺服器副作用表示,而不會指定任何與回應相關的內容。尤其要注意的是,針對不存在的資源進行的 DELETE 傳回 404 (Not Found)

HTTP POSTPATCH 並不安全,也不是冪等的 (PATCH 是在 RFC 5789 中導入)。

HTTP 動詞 安全 冪等
GET
PUT  
DELETE  
POST  
PATCH  

酬載格式

  • 要求和回應應共用相同的 Content-Type,但主體為 application/x-www-form-urlencodedGETPOST 要求除外。

  • application/json MIME 類型支援 JSON。proto3 至 JSON 的對應關係正式列載於 JSON 對應一文中。

  • 表格參數 (POST) 可用來取代網址查詢參數 (GET),但要遵循將要求欄位對應至查詢參數所適用的 REST 風格對應規則。支援的 Content-Typeapplication/x-www-form-urlencoded

串流

半雙工和全雙工的比較

HTTP 是要求-回應通訊協定,可讓其要求或回應主體透過不同的串流導向傳輸機制來傳送,例如 TCP (HTTP/1.x) 或其多路複用的版本 (SPDY、HTTP/2、QUIC)。

身為用戶端開發人員,您的應用程式可透過串流模式 (即用戶端串流) 產生要求主體。同樣地,應用程式也可透過串流模式 (即伺服器串流) 使用回應主體。

不過,HTTP 規格不會指定伺服器是否可在要求主體仍待處理時,透過串流傳回回應主體 (錯誤回應除外)。這個語意稱為「全雙工串流」。雖然許多 HTTP 用戶端/伺服器/Proxy 軟體允許全雙工串流,但即使是針對 HTTP 1.1,HTTP 式 Cloud API 也只能使用半雙工串流,以避免發生任何互通性問題。

根據預設,Cloud API 中的雙向串流方法會採用全雙工語意。也就是說,使用 HTTP 呼叫這類方法並不安全。如果串流方法僅為半雙工 (由伺服器強制執行),API 文件應清楚指定半雙工行為。

對於瀏覽器用戶端,標準 HTTP 語意會受到瀏覽器網路 API 的進一步限制。目前瀏覽器僅支援透過 XHR 或 Fetch 進行伺服器串流 (通常會遵守傳輸層級的框架)。Fetch API 會使用 whatwg 串流

由於瀏覽器限制,需要瀏覽器支援的 Cloud API 必須避免用戶端串流和全雙工串流,或必須專為瀏覽器用戶端另外提供 API。

一般來說,透過網際網路進行的用戶端串流不如伺服器串流實用。這是因為使用用戶端串流往往會產生有狀態的服務,這會對負載平衡產生負面影響,並使系統更容易發生錯誤或受到攻擊。另一方面,伺服器串流可大幅縮短延遲時間,因此或許很有幫助。

訊息編碼

JSON 訊息在串流時會編碼為 JSON 訊息陣列。要求或回應主體仍是有效的 JSON MIME 類型。

用戶端串流編碼範例如下:

1 <length> <message-bytes> 1 <length> <message-bytes>   EOF

伺服器串流編碼範例如下:

1 <length> <message-bytes>   2 <length> <status-bytes> EOF

傳輸層級編碼:StreamBody 定義的唯一重要之處,在於其針對「messages」和「status」欄位分配的標記 ID 會經過 Varint 編碼;一般訊息在進行這類編碼時會使用 1 到 2 個位元組,因此每則訊息的總編碼額外資料量為 2 到 3 個位元組。

另外需要選用的填充欄位來支援 Base64 編碼串流:

message StreamBody {
  repeated bytes message = 1;
  google.rpc.Status status = 2;
  repeated bytes padding = 15;   // max one-byte tag-id: xxx01111
}

錯誤訊息應採一般訊息的格式附加為 JSON 或 protobuf 陣列的最後一個元素。

狀態管理

半關閉行為在任何 HTTP 版本中都有完善定義,以便用戶端或伺服器向另一端告知主體已完成。

特別要注意的是,用戶端程式碼可在等候回應時自行完成要求。同樣地,用戶端可於系統仍在將要求主體寫入伺服器時查看完成的回應。當回應以非預期的方式完成時,HTTP 標準會預期用戶端取消或完成要求 (通常會傳回錯誤狀態)。也就是說,在正常情況下,當用戶端仍在傳送要求時,伺服器不應完成回應。

取消

「取消」支援功能可讓用戶端在要求或回應仍待處理時取消要求。

用戶端可在要求完成後自行關閉 TCP 連線,而不必取消要求/回應交易,因此 HTTP/1.* 用戶端沒有可靠的取消支援功能。使用 HTTP/1.1 時的 TCP FIN 不應視為取消,即使連線被標示為保持運作 (連線:保持運作) 亦然。

不過在用戶端關閉 TCP 連線後,如果伺服器嘗試寫入任何資料至用戶端,就會產生 RST,這樣可能會觸發取消作業。

另請注意,取消對於非串流 API 而言也是個問題,尤其當回應牽涉長時間輪詢,因而使連線可處於閒置狀態更長的時間時更是如此。

SPDY、HTTP/2 和 QUIC (特別是驅離訊息) 都支援明確取消。

保持運作

「保持運作」支援功能可讓用戶端或伺服器偵測發生錯誤的對等端,即使是封包遺失或網路發生錯誤也可偵測。

HTTP/1.1 不支援保持運作功能,因為 TCP 保持運作並不可行。

QUIC 或 HTTP/2 提供特殊控管訊息,以便讓應用程式 (包括瀏覽器) 支援保持運作功能。

不過,如要可靠地偵測保持運作和失敗情況,則可能需要具有必要伺服器端支援的用戶端程式庫:如果依賴基本 HTTP 做為通訊協定,透過網際網路執行長時間串流作業往往容易發生錯誤。

流量控制

「流量控制」支援功能需要用戶端將傳輸層級的流量控制事件傳播至用戶端應用程式,實際的機制取決於用戶端應用程式使用的 HTTP 用戶端 API 風格。舉例來說,您需要透過明確的流量控制支援功能,使用封鎖式寫入和讀取或非封鎖式寫入和讀取,讓應用程式處理及遵循流量控制事件,藉此避免用戶端或伺服器超載。

HTTP/1.1 需依賴 TCP 流量控制。

SPDY 和 HTTP/2 可在串流層級自行進行流量控制,但這會在連線層級進一步受到 TCP 流量控制的限制,因為要求會透過單一 TCP 連線多路複用。

QUIC 是透過 UDP 執行,因此流量控制完全由其自行管理。