https://zenn.dev/hsaki/books/golang-grpc-starting/viewer/metadata

og-base-book_yz4z02.jpg

この章について

クライアントーサーバー間でやりとりしたい情報には、ユーザー認証情報やユーザーエージェントといったいわゆる「付加情報」もあります。 通常のHTTP通信の場合には、これらの情報をヘッダーフィールドに入れてやりとりしていましたが、gRPCではメタデータというものを介して行うことになっています。 この章では、メタデータの送受信をどう実装すればいいのかを見ていきます。

クライアント -> サーバーへのメタデータ送受信

クライアントからサーバーにリクエストを送る際には、コンテキストにメタデータを付加してやりとりをするようになっています。

クライアントからメタデータを送信する

まずは、クライアントがコンテキストにメタデータを付加するところを見てみましょう。

  1. 2で作ったコンテキストを使ってメソッドを呼び出す(Unary) or ストリームを生成(Stream)
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]]