https://zenn.dev/hsaki/books/golang-grpc-starting/viewer/metadata
クライアントーサーバー間でやりとりしたい情報には、ユーザー認証情報やユーザーエージェントといったいわゆる「付加情報」もあります。 通常のHTTP通信の場合には、これらの情報をヘッダーフィールドに入れてやりとりしていましたが、gRPCではメタデータというものを介して行うことになっています。 この章では、メタデータの送受信をどう実装すればいいのかを見ていきます。
クライアントからサーバーにリクエストを送る際には、コンテキストにメタデータを付加してやりとりをするようになっています。
まずは、クライアントがコンテキストにメタデータを付加するところを見てみましょう。
import (
)
func Hello() {
req := &hellopb.HelloRequest{
Name: name,
}
+ ctx := context.Background()
+ md := metadata.New(map[string]string{"type": "unary", "from": "client"})
+ ctx = metadata.NewOutgoingContext(ctx, md)
}
func HelloBiStreams() {
+ ctx := context.Background()
+ md := metadata.New(map[string]string{"type": "stream", "from": "client"})
+ ctx = metadata.NewOutgoingContext(ctx, md)
// (略)リクエスト送信処理
}
Unary RPCとStream RPC、どちらもリクエスト送信時には第一引数にコンテキストを指定するようになっているため、両者でやり方が異なるポイントはありません。
サーバー側でクライアントから送られてくるメタデータを参照するためには、metadata.FromIncomingContext
関数を用いてコンテキストからmetadata.MD
型を取り出すことになります。
import (
)
func (s *myServer) Hello(ctx context.Context, req *hellopb.HelloRequest) (*hellopb.HelloResponse, error) {
return &hellopb.HelloResponse{
Message: fmt.Sprintf("Hello, %s!", req.GetName()),
}, nil
}
func (s *myServer) HelloBiStreams(stream hellopb.GreetingService_HelloBiStreamsServer) error {
// (以下略)
}
Unary RPCとStream RPCでは、コンテキストの出所に違いがあります。
Unary RPCの場合には、メソッドの第一引数で受け取ったコンテキストをそのまま使えばOKですが、Stream RPCの場合にはストリーム型のContext
メソッドから取り出すというワンステップが必要です。
// Contextメソッドを使ってストリームからコンテキストを得る
stream.Context()
ここまで実装したところで、実際にクライアント->サーバーへのメタデータ送信を動かしてみましょう。 サーバー側のログに以下のような文字列が出力されれば成功です。
$ go run cmd/server/main.go
// (一部抜粋)
2022/06/12 14:57:48 map[:authority:[localhost:8080] content-type:[application/grpc] from:[client] type:[unary] user-agent:[grpc-go/1.47.0]]
2022/06/12 14:57:51 map[:authority:[localhost:8080] content-type:[application/grpc] from:[client] type:[stream] user-agent:[grpc-go/1.47.0]]