HTTP ガイドライン

このドキュメントでは、さまざまな HTTP バージョンと実装での Google API の動作について説明します。 生成済みか手動で作成されたクライアント ライブラリのいずれかを使用している場合(ほとんどの使用例で推奨されるアプローチ)、サーバーとの通信に関する下位レベルの問題についてコード詳細が提供されるため、このことを考慮する必要はありません。

ただし、経験豊富なデベロッパーが、選択したサードパーティの HTTP クライアント ライブラリを使用して API の REST インターフェースに直接アクセスして独自のカスタムコードを記述する必要がある場合は、ここにドキュメント化されているセマンティクスのうち(選択した API への関連性に応じて)少なくとも一部を理解すると同時に、使用する HTTP ライブラリの内容を理解している必要があります。

ワイヤ プロトコル(HTTP/*)の使用

ここでは、Cloud API でクライアントとサーバーの間の通信に使用できる、サポートされているワイヤ プロトコル(通常は HTTP のバージョン)と、推奨されるこれらの使用方法について説明します。リクエストとレスポンスの構造の詳細については、次のセクションで説明します。

HTTP セマンティクス

API クライアント コードを開発する場合は、標準の HTTP プロトコル セマンティクスに従います。サーバーサイド プロキシや API スタックでは、標準の HTTP 機能のサブセットのみがサポートされる場合がありますが、下位互換性のあるバージョンがサポートされる場合もあります。

API のサーバーサイドの実装によって処理する必要がある HTTP プロトコルのセマンティクスは、サーバー スタックによって制御されます。これらの機能が API 仕様の一部(キャッシュ サポートなど)として明示的にドキュメント化されている場合にのみ、このようなセマンティクスに依存するようにしてください。

HTTP バージョン

クライアントでは、クライアント プラットフォームやクライアントサイド ネットワークで許可されるか、サーバーサイド プロキシでネゴシエートされるすべての HTTP/* プロトコルを使用できます。サポートされているプロトコルには、HTTP/1.0、HTTP/1.1、SPDY/*、HTTP/2、QUIC があります。

サーバーの push や優先度などの一部の API 機能は、新しいバージョンの HTTP プロトコルでのみサポートされる場合があります。また、全二重通信ストリーミングなど、HTTP/2 でのみ完全に指定されているものもあります。API 仕様の一部としてこれらの機能のいずれかが必要な場合は、異なる HTTP バージョンの制限に注意してください。

通常、パフォーマンスとネットワーク障害に対する復元力の高さから、HTTP/2 が推奨されます。

チャンネル

チャンネルは、L4 ネットワーク接続(TCP ソケットや UDP ソケット)を指します。HTTP リクエストを処理するときにランタイムでチャネルがどのように使用されるかについて、クライアント アプリケーションではいかなる想定もしない必要があります。ほとんどの場合、チャネルはサーバー プロセスの代わりにプロキシによって終了されます。

HTTP/1.1 クライアントの場合は、常に TCP 接続(接続: キープアライブ)を再利用してください。パフォーマンス向上のために、HTTP クライアント ライブラリによって接続プールも管理されると考えられます。同じ TCP 接続を介してリクエストをパイプライン化しないでください。詳細については、HTTP と TCP をご覧ください。

最新のブラウザはすべて、SPDY/* や HTTP/2、QUIC に対応することで、単一のチャネルを介してリクエストを多重化しています。従来の接続制限(2~10)は、サーバーの実装により単一のクライアントからの同時 HTTP リクエスト数が抑制される場合(単一の送信元に対して HTTP/2 ストリームが 100 個に制限される場合など)を除き、考慮する必要はありません。

HTTPS

クライアントは、API 仕様でサポートされているように、HTTPS または HTTP 経由で API にアクセスできます。TLS ネゴシエーションと TLS バージョンはクライアント アプリケーションに対して透過的です。デフォルトでは、Google API では HTTPS トラフィックのみが許可されます。

リクエスト / レスポンスの形式

リクエスト URL

JSON-REST マッピングでは、URL エンコードされたリクエスト データがサポートされ、HTTP リクエストとレスポンスの本文では Content-Type として application/json が使用されます。

HTTP 本文では、ストリーミングされた RPC メソッドが JSON 配列を使用してサポートされ、JSON 配列には、任意の数の JSON メッセージやエラー ステータスの JSON メッセージを含めることができます。

長いリクエスト URL

URL には実用的な長さ制限があり、通常はデフォルトで 16 KB に設定されていますが、これはサーバーによって異なる場合があります。API でこの長さを超える URL を含む GET リクエストを使用する場合、リクエストが宛先 API サーバーに到達せず、Google フロントエンド(GFE)によってエラー メッセージ Your client has issued a malformed or illegal request. とともに拒否される可能性があります。

この制限を回避するには、クライアント コードで、Content-Type が application/x-www-form-urlencoded で、HTTP ヘッダーが X-HTTP-Method-Override: GET の POST リクエストを使用する必要があります。この方法は、DELETE リクエストに対しても有効です。

HTTP メソッド(動詞)

リクエスト URL が REST モデルに従う場合、その HTTP メソッドは API 仕様の一部として指定されます。特に、すべての API メソッドは、その API メソッドがマッピングされる特定の HTTP 動詞に基づいて、HTTP プロトコルの要件に準拠している必要があります。詳細については、ハイパーテキスト転送プロトコルの仕様と PATCH メソッドの RFC をご覧ください。

HTTP GETHEAD などの安全なメソッドで、取得以外の操作を表すことはできません。特に、HTTP GET安全であると考えられているため、クライアントが認識できる副次的影響が発生しないようにしてください。

HTTP のべき等性とは、複数の同一のリクエストの副作用が単一のリクエストの場合と同じであることを意味します。GETPUTDELETE は、スタイルガイドに関連するべき等 HTTP メソッドです。べき等性は、サーバーの副作用という観点でのみ示され、レスポンスについては一切指定しないことに注意してください。特に、存在しないリソースの DELETE では、404 (Not Found) が返されることが 推奨されます。

HTTP POSTPATCH は安全でもべき等でもありません(PATCHRFC 5789 で導入されました)

HTTP 動詞 安全 べき等
GET はい
PUT   はい
DELETE  
POST  
PATCH  

ペイロード形式

  • リクエストとレスポンスは、リクエストが本文に application/x-www-form-urlencoded を持つ GETPOST の場合を除き、同じ Content-Type を共有する必要があります。

  • JSON は、application/json MIME タイプでサポートされています。proto3 から JSON へのマッピングは、JSON マッピングで正式に指定されています。

  • リクエスト フィールドをクエリ パラメータにマッピングする場合と同じ REST スタイルのマッピング ルールに従って、URL クエリ パラメータ(GET)の代わりにフォーム パラメータ(POST)を使用できます。サポートされている Content-Typeapplication/x-www-form-urlencoded です。

ストリーミング

半二重通信と全二重通信

HTTP は、リクエストやレスポンスの本文を TCP(HTTP/1.x)やその多重化されたバリアント(SPDY、HTTP/2、QUIC)などのさまざまなストリーム指向トランスポートを介して配信できるようにする、リクエストとレスポンスのプロトコルです。

クライアント デベロッパーは、アプリケーションを使用して、リクエスト本文をストリーミング モード(クライアント ストリーミング)で生成できます。同様に、アプリケーションがストリーミング モード(サーバー ストリーミング)でレスポンス本文を使用することもできます。

ただし、HTTP 仕様では、リクエスト本文がまだ保留中の場合に、サーバーによるレスポンス本文(エラー レスポンスを除く)のストリーミング バックを許可するかどうかは指定されません。このセマンティックは、全二重通信ストリーミングと呼ばれます。多くの HTTP クライアント / サーバー / プロキシ ソフトウェアでは、HTTP/1.1 についても全二重通信ストリーミングを行うことができますが、相互運用性に関する問題を回避するために、HTTP ベースの Cloud API は半二重通信ストリーミングのみに制限されます。

デフォルトでは、Cloud API の Bidi ストリーミング メソッドは全二重通信セマンティクスを前提としています。つまり、HTTP を使用してこのようなメソッドを呼び出すのは安全ではありません。ストリーミング メソッドが半二重通信のみである場合(サーバーによって適用される場合)、API ドキュメントで半二重通信動作を明確に指定する必要があります。

ブラウザ クライアントの場合、標準の HTTP セマンティクスは、ブラウザの Network API によってさらに制約を受けます。現在のところ、ブラウザは XHR または Fetch 経由の(通常はトランスポート レベルのフレーム処理が考慮される)サーバー ストリーミングのみがサポートされています。Fetch API は whatwg ストリームを使用します。

ブラウザの制限により、ブラウザのサポートを必要とする Cloud API は、クライアント ストリーミングと全二重通信ストリーミングを避けるか、ブラウザ クライアント専用の個別 API を提供する必要があります。

通常、インターネットを介したクライアント ストリーミングは、サーバー ストリーミングほど有益ではありません。これは、クライアント ストリーミングを使用すると、多くの場合、ステートフルなサービスが発生してロード バランシングに悪影響を及ぼし、システムが障害や攻撃に対してより脆弱になるためです。一方、サーバー ストリーミングは、RTT の遅延が長いネットワークのレイテンシを大幅に削減できるので便利です。

メッセージ エンコード

ストリーミング時の JSON メッセージは、JSON メッセージの配列としてエンコードされます。リクエストやレスポンスの本文は、有効な JSON MIME タイプのままとなります。

クライアント ストリームのエンコードの例:

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

サーバー ストリームのエンコードの例:

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

ワイヤレベルのエンコード: StreamBody の定義は、タグ ID の割り当てにおいてのみ重要となります。これは、フィールド「messages」と「status」は、通常のメッセージでは 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.* クライアントには信頼性の高いキャンセル サポートは存在しません。接続が keep-alive(接続: keep-alive)としてマークされている場合でも、HTTP/1.1 での TCP FIN をキャンセルとして解釈しないでください。

ただし、クライアントが TCP 接続を閉じた後、サーバーがなんらかのデータをクライアントに書き込むことを試みると、RST が生成されてキャンセルがトリガーされることがあります。

また、キャンセルは非ストリーミング API でも問題となるので注意してください。このことは、特に、レスポンスによって長時間のポーリングが発生し、接続が長期間アイドル状態になる可能性がある場合に当てはまります。

明示的なキャンセルは、特に、切断メッセージについて SPDY、HTTP/2、QUIC でサポートされています。

keep-alive

keep-alive サポートにより、クライアントやサーバーでは、パケットロスやネットワーク障害が発生した場合でも、障害が発生したピアを検出できます。

TCP keep-alive は実現可能なアプローチではないため、HTTP/1.1 にキープアライブ サポートは存在しません。

QUIC や HTTP/2 では、ブラウザなどのアプリケーションによって keep-alive サポートを実装する目的で、特別な制御メッセージが提供されています。

ただし、信頼性の高い keep-alive と障害検出には、サーバーサイド サポートを必要とするクライアント ライブラリが必要となる可能性があります。通信プロトコルとして基本 HTTP に依存する場合、インターネットを介して長時間ストリーミングを行うと、通常はエラーが発生しやすくなります。

フロー制御

フロー制御サポートでは、クライアントにより、トランスポート レベルのフロー制御イベントをクライアント アプリケーションに伝播する必要があります。実際のメカニズムは、クライアント アプリケーションで使用する HTTP クライアント API のスタイルに依存します。たとえば、クライアントやサーバーの過負荷を防ぐために、アプリケーションによりフロー制御イベントを処理して考慮するには、明示的なフロー制御サポートを使用して、書き込みと読み取りをブロックしたり、ブロックを解除したりすることが必要となります。

HTTP/1.1 は、TCP フロー制御に依存します。

SPDY と HTTP/2 では、ストリーム レベルで独自のフロー制御が行われます。この場合、リクエストが単一の TCP 接続を介して多重化されるため、さらに接続レベルで TCP フロー制御に依存します。

QUIC は UDP 上で動作するため、フロー制御は自動的に完全に管理されます。