grpc-gateway - gRPC HTTP 仕様に準拠した gRPC to JSON プロキシ ジェネレーター

(gRPC to JSON proxy generator following the gRPC HTTP spec)

Created at: 2015-04-03 15:25:13
Language: Go
License: BSD-3-Clause

gRPC ゲートウェイ

gRPC HTTP 仕様に準拠した gRPC to JSON プロキシ ジェネレーター

gRPC-Gateway は、Google プロトコル バッファ コンパイラ protocのプラグインです。protobuf サービス定義を読み取り、RESTful HTTP API を gRPC に変換するリバース プロキシ サーバーを生成します。

google.api.http
このサーバーは、サービス定義の注釈に従って生成さ れます。

これにより、gRPC と RESTful の両方のスタイルで API を同時に提供できます。

ドキュメント

ドキュメントは次の場所で読むことができます。

お客様の声

私たちは gRPC-Gateway を使用して 1 日あたり数百万の API リクエストを処理しており、2018 年以来、問題は発生していません。

- ウィリアム・ミル、アドホック

バックグラウンド

gRPC は優れています。多くのプログラミング言語で API クライアントとサーバー スタブを生成し、高速で使いやすく、帯域幅効率が高く、その設計は Google によって実戦で証明されています。ただし、従来の RESTful JSON API も提供したい場合があります。理由は、下位互換性の維持、gRPC で十分にサポートされていない言語またはクライアントのサポートから、RESTful JSON アーキテクチャに関連する美学とツールの単純な維持まで、さまざまです。

このプロジェクトは、その HTTP+JSON インターフェイスを gRPC サービスに提供することを目的としています。このライブラリを使用してリバース プロキシを生成するために必要なのは、HTTP セマンティクスをアタッチするためのサービスの少量の構成だけです。

インストール

ソースからコンパイル

次の手順では、依存関係の管理にGo モジュールを使用していることを前提としています 。ツールの依存関係を使用して 、次の実行可能パッケージのバージョンを追跡します。

// +build tools

package tools

import (
    _ "github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-grpc-gateway"
    _ "github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2"
    _ "google.golang.org/grpc/cmd/protoc-gen-go-grpc"
    _ "google.golang.org/protobuf/cmd/protoc-gen-go"
)

go mod tidy
バージョンを解決するために実行します。実行してインストール

$ go install \
    github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-grpc-gateway \
    github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2 \
    google.golang.org/protobuf/cmd/protoc-gen-go \
    google.golang.org/grpc/cmd/protoc-gen-go-grpc

これにより、4 つのバイナリが

$GOBIN
;に配置されます。

  • protoc-gen-grpc-gateway
  • protoc-gen-openapiv2
  • protoc-gen-go
  • protoc-gen-go-grpc

あなたがあなたの中にあることを確認して

$GOBIN
ください
$PATH

バイナリをダウンロードする

または、 GitHub リリース ページからバイナリをダウンロードすることもできます。リリース プロセス中に、 OpenSSF のslsa-framework/slsa-github-generatorを使用してSLSA3 署名を生成します。リリース バイナリを確認するには:

  1. slsa-framework/slsa-verifier#installationから検証ツールをインストールします。
  2. GitHub リリース ページ
    attestation.intoto.jsonl
    から来歴ファイルをダウンロードします。
  3. ベリファイアを実行します。
slsa-verifier -artifact-path <the-binary> -provenance attestation.intoto.jsonl -source github.com/grpc-ecosystem/grpc-gateway -tag <the-tag>

または、以下のリモート管理プラグインのバージョンに関するセクションを参照してください。

使用法

  1. プロトコル バッファを使用してgRPCサービスを定義する

    your_service.proto
    :

     syntax = "proto3";
     package your.service.v1;
     option go_package = "github.com/yourorg/yourprotos/gen/go/your/service/v1";
    
     message StringMessage {
       string value = 1;
     }
    
     service YourService {
       rpc Echo(StringMessage) returns (StringMessage) {}
     }
  2. gRPC スタブを生成する

    この手順では、サービスを実装してクライアントから使用するために使用できる gRPC スタブを生成します。

    buf

    buf.gen.yaml
    でスタブを生成するために使用できる例を次に示します。

    version: v1
    plugins:
      - name: go
        out: gen/go
        opt:
          - paths=source_relative
      - name: go-grpc
        out: gen/go
        opt:
          - paths=source_relative

    このファイルを配置すると、 を使用してファイルを生成できます

    buf generate

    buf generate
    を使用して protobuf スタブを生成 する完全な例については、定型リポジトリを参照してください。buf を使用してスタブを生成する方法の詳細については 、公式ドキュメントを参照してください。

    を使用

    protoc
    してスタブを生成する場合、コマンドの例を次に示します。

    protoc -I . \
        --go_out ./gen/go/ --go_opt paths=source_relative \
        --go-grpc_out ./gen/go/ --go-grpc_opt paths=source_relative \
        your/service/v1/your_service.proto
  3. 通常どおり gRPC でサービスを実装します。

  4. を使用してリバース プロキシを生成する

    protoc-gen-grpc-gateway

    この時点で、次の 3 つのオプションがあります。

    • それ以上の変更は必要ありません。HTTP セマンティクス (メソッド、パスなど) へのデフォルトのマッピングを使用します。
      • これはどの
        .proto
        ファイルでも機能しますが、HTTP パスやリクエスト パラメータなどを設定することはできません。
    • カスタム マッピングを使用するための追加
      .proto
      の変更
      • ファイル内のパラメーターに依存して、
        .proto
        カスタム HTTP マッピングを設定します
    • 変更はありません
      .proto
      が、外部構成ファイルを使用します
      • 外部構成ファイルに依存してカスタム HTTP マッピングを設定します
      • ソースprotoファイルがあなたの管理下にない場合に最も役立ちます
    1. デフォルトのマッピングの使用

    これには、ファイルへの追加の変更は必要ありません

    .proto
    が、プラグインの実行時に特定のオプションを有効にする必要があります。
    generate_unbound_methods
    を有効にする必要があります。

    buf.gen.yaml
    このオプションを有効にすると、ファイルは次のようになります。

    version: v1
    plugins:
      - name: go
        out: gen/go
        opt:
          - paths=source_relative
      - name: go-grpc
        out: gen/go
        opt:
          - paths=source_relative
      - name: grpc-gateway
        out: gen/go
        opt:
          - paths=source_relative
          - generate_unbound_methods=true

    ( grpc

    protoc
    -gateway スタブのみ):

    protoc -I . --grpc-gateway_out ./gen/go \
        --grpc-gateway_opt logtostderr=true \
        --grpc-gateway_opt paths=source_relative \
        --grpc-gateway_opt generate_unbound_methods=true \
        your/service/v1/your_service.proto
    1. カスタム注釈付き

    google.api.http
    .proto ファイルに注釈を追加する

    your_service.proto
    :

     syntax = "proto3";
     package your.service.v1;
     option go_package = "github.com/yourorg/yourprotos/gen/go/your/service/v1";
    +
    +import "google/api/annotations.proto";
    +
     message StringMessage {
       string value = 1;
     }
    
     service YourService {
    -  rpc Echo(StringMessage) returns (StringMessage) {}
    +  rpc Echo(StringMessage) returns (StringMessage) {
    +    option (google.api.http) = {
    +      post: "/v1/example/echo"
    +      body: "*"
    +    };
    +  }
     }

    必要なサード パーティの protobuf ファイルを protobuf コンパイラに提供する必要があります。bufを使用している場合、この依存関係をname の下の

    deps
    配列に追加できます。
    buf.yaml
    buf.build/googleapis/googleapis

    version: v1
    name: buf.build/yourorg/myprotos
    deps:
      - buf.build/googleapis/googleapis

    buf mod update
    に依存関係を追加した後は常に実行します
    buf.yaml

    ゲートウェイの動作と生成された OpenAPI 出力をカスタマイズするために追加できるその他の注釈の例については、 a_bit_of_everything.protoを参照してください。

    ファイルは次の

    buf.gen.yaml
    ようになります。

    version: v1
    plugins:
      - name: go
        out: gen/go
        opt:
          - paths=source_relative
      - name: go-grpc
        out: gen/go
        opt:
          - paths=source_relative
      - name: grpc-gateway
        out: gen/go
        opt:
          - paths=source_relative

    を使用

    protoc
    してスタブを生成する場合は、必要な依存関係がコンパイル時にコンパイラで利用できるようにする必要があります。これらは、 googleapis リポジトリから関連ファイルを手動で複製およびコピーし 、実行時に提供することで見つけることができます
    protoc
    。必要なファイルは次のとおりです。

    google/api/annotations.proto
    google/api/field_behavior.proto
    google/api/http.proto
    google/api/httpbody.proto
    

    実行は次の

    protoc
    ようになります。

    protoc -I . --grpc-gateway_out ./gen/go \
        --grpc-gateway_opt logtostderr=true \
        --grpc-gateway_opt paths=source_relative \
        your/service/v1/your_service.proto
    1. 外部構成 gRPC-Gateway で使用する proto ファイルを変更したくない (または変更できない) 場合は、代わりに外部 gRPC サービス構成ファイルを使用できます。 詳細については、ドキュメント を確認してください。
      standalone=true
      これは、ソースの protobuf ファイルによって生成されたファイルとは別に、独自のパッケージに含めることができるファイルを生成するオプションと組み合わせるのが最適です。

    buf.gen.yaml
    このオプションを有効にすると、ファイルは次のようになります。

    version: v1
    plugins:
      - name: go
        out: gen/go
        opt:
          - paths=source_relative
      - name: go-grpc
        out: gen/go
        opt:
          - paths=source_relative
      - name: grpc-gateway
        out: gen/go
        opt:
          - paths=source_relative
          - grpc_api_configuration=path/to/config.yaml
          - standalone=true

    ( grpc

    protoc
    -gateway スタブのみ):

    protoc -I . --grpc-gateway_out ./gen/go \
        --grpc-gateway_opt logtostderr=true \
        --grpc-gateway_opt paths=source_relative \
        --grpc-gateway_opt grpc_api_configuration=path/to/config.yaml \
        --grpc-gateway_opt standalone=true \
        your/service/v1/your_service.proto
  5. HTTP リバース プロキシ サーバーのエントリポイントを作成する

    package main
    
    import (
      "context"
      "flag"
      "net/http"
    
      "github.com/golang/glog"
      "github.com/grpc-ecosystem/grpc-gateway/v2/runtime"
      "google.golang.org/grpc"
      "google.golang.org/grpc/credentials/insecure"
    
      gw "github.com/yourorg/yourrepo/proto/gen/go/your/service/v1/your_service"  // Update
    )
    
    var (
      // command-line options:
      // gRPC server endpoint
      grpcServerEndpoint = flag.String("grpc-server-endpoint",  "localhost:9090", "gRPC server endpoint")
    )
    
    func run() error {
      ctx := context.Background()
      ctx, cancel := context.WithCancel(ctx)
      defer cancel()
    
      // Register gRPC server endpoint
      // Note: Make sure the gRPC server is running properly and accessible
      mux := runtime.NewServeMux()
      opts := []grpc.DialOption{grpc.WithTransportCredentials(insecure.NewCredentials())}
      err := gw.RegisterYourServiceHandlerFromEndpoint(ctx, mux,  *grpcServerEndpoint, opts)
      if err != nil {
        return err
      }
    
      // Start HTTP server (and proxy calls to gRPC server endpoint)
      return http.ListenAndServe(":8081", mux)
    }
    
    func main() {
      flag.Parse()
      defer glog.Flush()
    
      if err := run(); err != nil {
        glog.Fatal(err)
      }
    }
  6. (オプション) を使用して OpenAPI 定義を生成する

    protoc-gen-openapiv2

    ファイルは次の

    buf.gen.yaml
    ようになります。

    version: v1
    plugins:
      - name: go
        out: gen/go
        opt:
          - paths=source_relative
      - name: go-grpc
        out: gen/go
        opt:
          - paths=source_relative
      - name: grpc-gateway
        out: gen/go
        opt:
          - paths=source_relative
      - name: openapiv2
        out: gen/openapiv2

    でサポートされているカスタム protobuf アノテーションを使用するには

    protoc-gen-openapiv2
    、protobuf 生成ステップに別の依存関係を追加する必要があります。を使用している場合は 、配列に依存関係を
    buf
    追加できます。
    buf.build/grpc-ecosystem/grpc-gateway
    deps

    version: v1
    name: buf.build/yourorg/myprotos
    deps:
      - buf.build/googleapis/googleapis
      - buf.build/grpc-ecosystem/grpc-gateway

    ( swagger

    protoc
    ファイルのみ):

    protoc -I . --openapiv2_out ./gen/openapiv2 \
        --openapiv2_opt logtostderr=true \
        your/service/v1/your_service.proto

    を使用してスタブを生成する場合は、このリポジトリ

    protoc
    のディレクトリから protobuf ファイルをコピーし、実行時に提供する必要があります。
    protoc-gen-openapiv2/options
    protoc

    このプラグインは、アノテーションのないメソッドの OpenAPI 定義の生成もサポートしていることに注意してください。オプションを使用して

    generate_unbound_methods
    これを有効にします。

    gRPC サービス メソッドの HTTP マッピングを使用すると、重複するマッピングを作成できますが、唯一の違いはパス パラメーターの制約です。

    /v1/{name=projects/*}
    /v1/{name=organizations/*}
    両方になり
    /v1/{name}
    ます。これが発生すると、プラグインはパス パラメータの名前を「_1」(または「_2」など)の接尾辞で変更して、さまざまな操作を区別します。したがって、上記の例では、2 番目のパスは になり
    /v1/{name_1=organizations/*}
    ます。これにより、OpenAPI クライアントは、パス パラメータの一部である「/」を URL エンコードすることもできます。これは、OpenAPI が仕様で定義しているためです。gRPC ゲートウェイが URL エンコードされたスラッシュを受け入れ、引き続き要求をルーティングできるようにするには、UnescapingModeAllCharacters または UnescapingModeLegacy を使用します (これは現在の既定値ですが、将来のバージョンでは変更される可能性があります)。詳細について は、ゲートウェイ のカスタマイズを参照してください。

リモートプラグインでの使用

上記のすべての代わりに、リモート プラグイン

buf
を使用して プラグインのバージョンと生成を管理できます。リモート プラグイン生成を使用した例は次のようになります。
buf.gen.yaml

version: v1
plugins:
  - remote: buf.build/library/plugins/go:v1.27.1-1
    out: gen/go
    opt:
      - paths=source_relative
  - remote: buf.build/library/plugins/go-grpc:v1.1.0-2
    out: gen/go
    opt:
      - paths=source_relative
  - remote: buf.build/grpc-ecosystem/plugins/grpc-gateway:v2.6.0-1
    out: gen/go
    opt:
      - paths=source_relative
  - remote: buf.build/grpc-ecosystem/plugins/openapiv2:v2.6.0-1
    out: gen/openapiv2

これには、プラグインをローカルにインストールする必要はありません。

v2.6.0-1
ランタイムライブラリと同じバージョンのジェネレータを使用するように注意してください。

$ go get github.com/grpc-ecosystem/grpc-gateway/v2@v2.6.0

で同じバージョンのランタイムを取得するには、

go.mod
.

ビデオの紹介

メンテナー@JohanBrandhorstによるこの GopherCon UK 2019 プレゼンテーションは、gRPC-Gateway の使用に関する優れた紹介を提供します。次のボイラープレート リポジトリをベースとして使用します: https://github.com/johanbrandhorst/grpc-gateway-boilerplate

パラメータとフラグ

を使用

buf
してスタブを生成する場合、フラグとパラメーターはファイル内の
opt
フィールドを介して渡されます。次に例を示します。
buf.gen.yaml

version: v1
plugins:
  - name: grpc-gateway
    out: gen/go
    opt:
      - paths=source_relative
      - grpc_api_configuration=path/to/config.yaml
      - standalone=true

を使用したコード生成中

protoc
、gRPC-Gateway ツールへのフラグは、次
protoc
の 2 つのパターンのいずれかを使用して渡す必要があります。

  • --<tool_suffix>_out
    protoc
    パラメータの一部として:
    --<tool_suffix>_out=<flags>:<path>
--grpc-gateway_out=logtostderr=true,repeated_path_param_separator=ssv:.
--openapiv2_out=logtostderr=true,repeated_path_param_separator=ssv:.
  • 追加の
    --<tool_suffix>_opt
    パラメータを使用:
    --<tool_suffix>_opt=<flag>[,<flag>]*
--grpc-gateway_opt logtostderr=true,repeated_path_param_separator=ssv
# or separately
--grpc-gateway_opt logtostderr=true --grpc-gateway_opt repeated_path_param_separator=ssv
--openapiv2_opt logtostderr=true,repeated_path_param_separator=ssv
# or separately
--openapiv2_opt logtostderr=true --openapiv2_opt repeated_path_param_separator=ssv

その他の例

examples
ディレクトリの下には、さらに多くの例があります。

  • proto/examplepb/echo_service.proto
    proto/examplepb/a_bit_of_everything.proto
    proto/examplepb/unannotated_echo_service.proto
    : サービス定義
    • proto/examplepb/echo_service.pb.go
      ,
      proto/examplepb/a_bit_of_everything.pb.go
      ,
      proto/examplepb/unannotated_echo_service.pb.go
      : [生成] サービスのスタブ
    • proto/examplepb/echo_service.pb.gw.go
      ,
      proto/examplepb/a_bit_of_everything.pb.gw.go
      ,
      proto/examplepb/uannotated_echo_service.pb.gw.go
      : [生成] サービスのリバース プロキシ
    • proto/examplepb/unannotated_echo_service.yaml
      : の gRPC API 構成
      unannotated_echo_service.proto
  • server/main.go
    : サービスの実装
  • main.go
    : 生成されたリバース プロキシのエントリ ポイント

カスタム HTTP ハンドラー (例: サービング

swagger.json
)、gRPC-Gateway、および gRPC サーバーに 同じポートを使用するには、CoreOS によるこの例 (および付随するブログ投稿) を参照してください。

特徴

対応

  • JSON API ハンドラーの生成。
  • リクエスト本文のメソッド パラメータ。
  • リクエスト パスのメソッド パラメータ。
  • クエリ文字列のメソッド パラメーター。
  • path パラメーターの列挙型フィールド (反復列挙型​​フィールドを含む)。
  • ストリーミング API を改行区切りの JSON ストリームにマッピングします。
  • プレフィックス付きの HTTP ヘッダー
    Grpc-Metadata-
    を gRPC メタデータにマッピングする (プレフィックスは
    grpcgateway-
    )
  • オプションで、 OpenAPI (Swagger) v2の API 定義を発行します。
  • インバウンド HTTPヘッダーによるgRPC タイムアウトの設定。
    Grpc-Timeout
  • 注釈の代替として、gRPC API 構成ファイルを部分的にサポートします。
  • PATCH リクエストをフィールド マスク gRPC リクエストに自動的に変換します。詳細について は、ドキュメント を参照してください。

対応予定なし

しかし、パッチは大歓迎です。

  • HTTP ヘッダーのメソッド パラメータ。
  • トレーラー メタデータの処理。
  • XML での要求/応答本文のエンコード。
  • 真の双方向ストリーミング。

gRPC を HTTP にマッピングする

  • レスポンスで gRPC エラー コードが HTTP ステータス コードにどのようにマッピングされるか
  • HTTP リクエストの送信元 IP が
    X-Forwarded-For
    gRPC リクエスト ヘッダーとして追加されます。
  • HTTP リクエスト ホストが
    X-Forwarded-Host
    gRPC リクエスト ヘッダーとして追加されます。
  • HTTP
    Authorization
    ヘッダーが
    authorization
    gRPC リクエスト ヘッダーとして追加されます。
  • 残りの永続的な HTTP ヘッダー キー ( ここで IANA によって指定されている) には、接頭辞が付け
    grpcgateway-
    られ、その値が gRPC 要求ヘッダーに追加されます。
  • 「Grpc-Metadata-」で始まる HTTP ヘッダーは、gRPC メタデータ (接頭辞が
    grpcgateway-
    ) にマップされます。
  • 構成可能ですが、デフォルトの {un,} マーシャリングは protojsonを使用します。
  • gRPC サービス メソッドを HTTP エンドポイントにマップするために使用されるパス テンプレートは、google.api.http パス テンプレート構文をサポートします。たとえば、
    /api/v1/{name=projects/*/topics/*}
    または
    /prefix/{path=organizations/**}
    .

貢献

CONTRIBUTING.mdを参照してください。

ライセンス

gRPC-Gateway は、BSD 3-Clause License に基づいてライセンスされています。詳細については、 LICENSE.txtを参照してください。