ブラウザからgRPCサービスを呼び出そうとしたことがあるなら、その摩擦は既にご存知でしょう。ブラウザはHTTPトレーラーを制御できないため、生のgRPCを話すことはできません。そのため、トラフィックを変換するためだけにEnvoyのようなプロキシを導入することになります。ConnectRPCはその手順を不要にします。ブラウザが直接呼び出せ、プレーンなcurlコマンドにも応答し、かつ広範なgRPCエコシステムと相互運用できるProtobufベースのAPIを構築できます。
このガイドでは、ConnectRPCとは何か、Connectプロトコルが解決する問題、ConnectがgRPC、gRPC-Web、RESTとどのように比較されるか、そしてHTTP上でのConnectリクエストがどのようなものかについて説明します。また、標準的なAPIクライアントを使用してConnectおよびgRPCエンドポイントをテストおよびデバッグする方法もご覧いただけます。
ConnectRPCとは
ConnectRPCは、Protocol Buffersからブラウザ互換およびgRPC互換のHTTP APIを構築するためのライブラリ群です。.protoファイルでサービスを定義し、コードを生成し、ハンドラを実装します。Connectがルーティング、シリアライゼーション、圧縮、クライアント生成を処理します。
このプロジェクトは、Protobuf用のbufビルドツールを開発した企業であるBufによって作成され、現在はCloud Native Computing Foundation (CNCF) のサンドボックスプロジェクトとなっています。この経緯は重要です。Connectは、チームがbufとProtobufで既に利用しているスキーマファーストのワークフローに適合するように設計されています。
ConnectRPCサーバーは一度に3つのプロトコルをサポートします。
- gRPC: ストリーミングとトレーラーを含む完全な互換性。
- gRPC-Web: 別途プロキシを必要としない直接サポート。
- Connect: ウェブ向けに調整された独自のHTTPベースプロトコル。
単一のサーバーがこれら3つすべてを話すため、gRPCクライアントはConnectサーバーを呼び出すことができ、ConnectクライアントはあらゆるgRPCサーバーを呼び出すことができます。通常、単一の設定変更でコードの書き換えなしに、クライアントごとにプロトコルを選択できます。
Connectが解決する問題
gRPCは高速で厳密に型付けされていますが、ウェブが尊重しない仮定に基づいています。HTTP/2とHTTPトレーラーに依存してステータス情報を伝達します。ブラウザはJavaScriptにトレーラーを公開しないため、ブラウザはネイティブのgRPCクライアントとして機能できません。通常の回避策は、gRPC-Webと、ブラウザとgRPCバックエンドの間に位置するEnvoyのような翻訳プロキシを使用することです。
それは機能しますが、可動部分が増えます。プロキシを実行・設定し、余分なホップをデバッグすることになります。型付きAPIとブラウザアクセスをそのオーバーヘッドなしで実現したいチームにとって、そのセットアップは必要以上に重く感じられます。
Connectは異なるアプローチを取ります。その独自のプロトコルは標準HTTP上で動作するため、ブラウザはそれを直接呼び出すことができ、ブラウザトラフィック用のプロキシは必要ありません。既存のgRPCクライアントにもサービスを提供する必要がある場合でも、同じConnectサーバーがそれらを処理します。ブラウザ、コマンドラインツール、gRPCサービスすべてに応答する単一のバックエンドが得られます。
Connect vs gRPC vs gRPC-Web vs REST
これら4つのアプローチは重複しているため、整理すると理解に役立ちます。
gRPCは、バイナリフレーミングとトレーラーを備えたHTTP/2上でProtobufを使用します。効率的で4つのストリーミングモードすべてをサポートしますが、ブラウザやシェルから呼び出すのは扱いにくいです。トランスポート層について復習したい場合は、gRPCとHTTP/2がどのように連携するかをご覧ください。
gRPC-Webは、gRPCのブラウザ向けバリアントです。Protobufを中心に据え、通常は実際のgRPCバックエンドに接続するためのプロキシが必要です。gRPC-Webとは何かに関する私たちのガイドで、その立ち位置を説明しています。
ConnectはProtobufスキーマとgRPCスタイルのメソッドモデルを維持しますが、そのプロトコルはHTTP/1.1、HTTP/2、HTTP/3上でクリーンに動作します。単項呼び出しはgRPCバイナリフレーミングなしのプレーンなJSONまたはProtobufボディを運び、応答には実際のHTTPステータスコードが使用されます。この組み合わせにより、Connect呼び出しはあらゆるREST呼び出しと同じくらい扱いやすくなります。
RESTはリソース指向でスキーマはオプションです。最も普遍的にサポートされているスタイルですが、Protobufが提供するコード生成と厳密な型付けが欠けています。トレードオフを比較検討している場合は、gRPC vs RESTで違いを詳しく説明しています。
要するに、ConnectはgRPCの型付けとツールを、RESTの到達範囲とデバッグ可能性と共に提供することを目指しています。ProtobufとgRPCのメソッドモデルに依拠しつつ、ブラウザやシェルが処理できない部分を削除しています。
HTTP上でのConnectリクエスト
Connectが扱いやすい理由はここにあります。単項Connect呼び出しは通常のHTTP POSTです。URLパスはProtobufスキーマから直接取得され、ボディは余分なフレーミングなしのJSONまたはバイナリProtobufです。
パス形式は/<package>.<Service>/<Method>です。したがって、greet.v1パッケージ内のGreetServiceに対するGreetメソッドは/greet.v1.GreetService/Greetに存在します。
curlで呼び出すことができます。
curl \
--header "Content-Type: application/json" \
--data '{"name": "Jane"}' \
http://localhost:8080/greet.v1.GreetService/Greet
応答はプレーンなJSONです。
{"greeting": "Hello, Jane!"}
カスタムクライアントも、プロキシも、バイナリデコードも不要です。それがリクエストのすべてです。ボディは実際のJSONであり、ステータスは実際のHTTPステータスコードであるため、HTTPを話すすべてのツールが呼び出しを検査できます。これがConnectプロトコルを生のgRPCと区別する特性であり、生のgRPCでは同じリクエストがバイナリフレーミングでラップされ、ステータスはトレーラーで伝達されます。
Connectは単項リクエストに対して2つのコンテンツタイプをサポートしています。
- 人間が読めるJSONペイロード用の
application/json。 - コンパクトなバイナリProtobuf用の
application/proto。
ワイヤーサイズを小さくしたい場合はバイナリProtobufを、開発中に可読性を高めたい場合はJSONを送信します。バイナリを送信するには、ヘッダーを切り替え、エンコードされたボディを渡します。
curl \
--header "Content-Type: application/proto" \
--data-binary @request.bin \
http://localhost:8080/greet.v1.GreetService/Greet
ストリーミング呼び出しは異なるコンテンツタイプ(application/connect+protoまたはapplication/connect+json)を使用し、各メッセージをエンベロープでラップします。これには1バイトのフラグ、4バイトのビッグエンディアン長、そしてメッセージが含まれます。単項呼び出しはそのエンベロープを完全にスキップするため、通常のHTTPリクエストに非常にきれいにマッピングされます。ペイロードのワイヤーフォーマットを選択する際には、Protobuf vs JSONでサイズと可読性のトレードオフについて説明しています。
言語サポートとbufツール
ConnectRPCは複数の言語で実装を提供しています。GoとTypeScript(ブラウザおよびNode.js向け)は安定しており、本番環境に対応しています。SwiftはAppleプラットフォームで、KotlinはJVMとAndroidで利用可能であり、Pythonはベータ版です。この広範なサポートにより、クライアントを手書きすることなく、GoバックエンドとTypeScriptフロントエンドで1つのProtobuf契約を共有できます。
コード生成はbufツールチェーンを通じて実行されます。.protoファイルでサービスを記述し、その後bufプラグインを使用してメッセージとConnectハンドラを生成します。Goプロジェクトでは、Protobufメッセージ用のprotoc-gen-goと、Connectハンドラおよびクライアント用のprotoc-gen-connect-goという2つのプラグインを使用します。
プラグインはbuf.gen.yamlファイルにリストされており、1つのコマンドで生成を実行します。
buf generate
これにより、型付きメッセージ構造体と、サービスのサーバーおよびクライアントコードが生成されます。そこからハンドラメソッドを実装し、HTTPサーバーに登録します。生成されたコードはGoの標準ライブラリのnet/httpを対象としているため、別のサーバーランタイムを取り込む必要はありません。Connectハンドラは、既存のルートと並行してマウントできる通常のHTTPハンドラです。
ConnectおよびgRPCエンドポイントのテストとデバッグ
Connectの単項呼び出しはJSONボディを持つプレーンなHTTPであるため、他のRESTエンドポイントと同じ方法でテストできます。これは実用的な利点です。開発中にサービスを検証するために特別なクライアントは必要ありません。
Apidogでは、Connectの単項リクエストをHTTPリクエストとして送信します。メソッドをPOSTに設定し、http://localhost:8080/greet.v1.GreetService/Greetのようなスキーマから導出されたURLを使用し、Content-Type: application/jsonヘッダーを追加し、メッセージをJSONボディに入力します。
{"name": "Jane"}
JSON応答と実際のHTTPステータスコードが返され、それらを直接アサートできます。ApidogはConnect専用クライアントではありませんが、そうである必要はありません。UI、保存されたリクエスト、履歴を備え、curlとまったく同じように、Connectプロトコルが公開するHTTPインターフェースを操作しているのです。関連する動詞の簡単な入門については、HTTPメソッドとは何かをご覧ください。
ConnectサーバーはgRPCも話すため、サービスのgRPC側もテスト可能です。ApidogはgRPCエンドポイントをサポートしているため、同じ.protoファイルをインポートし、サービスメソッドを参照し、型付きリクエストでそれらを呼び出すことができます。これは、HTTPフレンドリーなConnectプロトコルとネイティブgRPCプロトコルの両方を1つのツールでカバーできることを意味します。gRPCが主な関心事である場合は、gRPC APIを効率的にテストする方法でワークフローを詳しく説明しています。
リクエストが期待通りに動作するようになったら、自動化されたチェックに移行できます。ConnectおよびgRPC呼び出しをテストシナリオとして保存し、Apidog CLIを使用してCIで実行します。Nodeでインストールします。
npm install -g apidog-cli
その後、保存されたシナリオまたはスイートを実行し、環境を指定し、レポート形式を選択します。
apidog run \
--access-token "$APIDOG_ACCESS_TOKEN" \
-t <scenarioOrSuiteId> \
-e <environmentId> \
-r cli,html,junit
CLIはヘッドレスであるため、Nodeを実行できるあらゆるCIステップに組み込めます。アドホックなリクエストを送信するのではなく、保存されたテストシナリオやスイートを実行するため、ConnectおよびgRPCエンドポイントの回帰テストに適しています。詳細な手順については、コマンドラインからAPIをテストするためのApidog CLIチュートリアルをご覧ください。
よくある質問
ConnectRPCはgRPCと同じですか? いいえ。ConnectRPCは、gRPC、gRPC-Web、および独自のConnectプロトコルという3つのプロトコルを実装するフレームワークです。ConnectサーバーはgRPCクライアントおよびサーバーと相互運用できるため、gRPCエコシステムに適合しますが、Connectプロトコル自体は、ブラウザやシェルが直接呼び出せるように設計された、別のHTTPベースのデザインです。
ブラウザに到達するためにEnvoyのようなプロキシはまだ必要ですか? Connectプロトコルの場合は必要ありません。Connectは標準HTTP上で動作するため、ブラウザは翻訳プロキシなしでConnectサーバーを呼び出すことができます。Envoyのようなプロキシが必要になるのは、ブラウザトラフィックをネイティブgRPCのみを話すバックエンドに橋渡しする必要がある場合のみです。
ConnectRPCはどの言語をサポートしていますか? GoとTypeScript(ブラウザおよびNode.js)は、安定した本番環境対応の実装です。Swift、Kotlin、Pythonも利用可能で、Pythonはベータ版です。これらはすべて同じProtobufスキーマから生成されます。
Connectとbufの関係は何ですか? ConnectRPCはBufによって作成され、コード生成にはbufツールチェーンを使用します。.protoファイルからハンドラとクライアントを生成するために、protoc-gen-connect-goのようなプラグインとともにbuf generateを実行します。
通常のAPIクライアントでConnectエンドポイントをテストできますか? はい。Connectの単項呼び出しは、JSONまたはProtobufボディと実際のHTTPステータスコードを持つHTTP POSTリクエストです。curlやApidogを含むあらゆるHTTPクライアントがそれを送信できます。Apidogは、.protoファイルをインポートすることで、同じサーバーのgRPC側も呼び出すことができます。
