やりたいこと
grpc-gateway
がHTTP/1.1で受け取ったリクエストヘッダーX-Cloud-Trace-Context
の情報を
BackendへgRPCで通信するときにも伝搬してBakend側で使用したい。
想定しているアーキテクチャ
grpc-gateway側の設定
muxを作成する際に、http headerを伝播するオプションをセット。
runtime.WithIncomingHeaderMatcher()
を設定しない場合、header情報は伝搬されない。
mux := runtime.NewServeMux(runtime.WithIncomingHeaderMatcher(matcher))
matcher
で伝搬したいheaderのみ指定することもできる。
This matcher will be called with each header in http.Request. If matcher returns true, that header will be passed to gRPC context. To transform the header before passing to gRPC context, matcher should return modified header.
https://pkg.go.dev/github.com/grpc-ecosystem/grpc-gateway/runtime#WithIncomingHeaderMatcher
func matcher(key string) (string, bool) {
if key == "X-Cloud-Trace-Context" {
return key, true
}
return "", false
}
Backend側の設定
Backend側でX-Cloud-Trace-Context
を取得するためには
Controller層などのgrpcのpb serverに登録している関数がcontext
を受け取ったあとに、
metadata
を取り出すことでHttp Headerを取り出せる。
import (
"context"
"github.com/example/controller"
"github.com/exmaple/pb"
"google.golang.org/grpc/metadata"
)
// Backend側のController実装の例
func (ec *ExampleController) HelloExample(ctx context.Context, req *pb.ExampleRequest) (res *pb.ExampleRequest, err error) {
// grpc-gatewayからheader情報はmetadataとして伝搬される
md, isExist := metadata.FromIncomingContext(ctx)
// metadataが存在する場合はisExist=true
// metadata.Get(key string) []string を使用してheader情報を取得する
traceContext := ""
if isExist && len(md.Get("X-Cloud-Trace-Context")) > 0 {
// []stringなのでindex=0を指定して取得
traceContext = md.Get("X-Cloud-Trace-Context")[0]
}
..
return res, err
}
Sample
TODO: そのうちにつくってgithubのurlを貼ります。。
参考した記事