⛳
Go言語でgRPCに入門してみた3 独自インターセプタ
以前の記事で、gRPCで認証処理を入れる実験をしてみました。
その時はこちら。
インターセプタには認証の他にもロギングなど、定型的な処理がすでに用意されていていて、便利そうです。
ただ、実際の業務では独自処理を差し挟むこともあるかと思い、この記事ではカスタムインターセプタのテストをやってみました。
railsのbefore、afterやjavaのSpringのinterceptorに慣れている人であれば、すぐにイメージがつくと思います。
この記事では前々回の名前を渡すとhello <name>を返却するだけのサンプルに以下のことをやるカスタムインターセプタを追加します。
前々回の記事はこちら。
- 送信された名前を<<< >>>で囲みます
- 返却したhelloを*** ***で囲みます
例:name: worldをサーバに送信すると"*** hello ***<<< world >>>"を返却
独自インターセプタを追加
server.goに以下のような関数を定義します。
これが独自インターセプタの処理内容となります。
関数の真ん中にあるhandler()がリクエストを受けて起動される本来の処理です。
func CustomInterceptor() grpc.UnaryServerInterceptor {
return func(ctx context.Context, request interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHand
fmt.Printf("before process")
helloMessage, _ := request.(*hello.HelloMessage)
helloMessage.Name = fmt.Sprintf("<<< %s >>>", helloMessage.Name)
res, err := handler(ctx, request)
if err != nil {
return nil, err
}
fmt.Println("after process")
helloResponse, _ := res.(*hello.HelloResponse)
helloResponse.Msg = fmt.Sprintf("*** %s ***", helloResponse.Msg)
return res, nil
}
}
独自インターセプタを設定する
server.goの以下の部分を変更します。
リクエストの度に処理を行いたいインターセプタをこのように登録します。
server := grpc.NewServer(
grpc.UnaryInterceptor(CustomInterceptor()),
)
コード全文
下がserver.goのコード全文となります。
package main
import (
"context"
"fmt"
"log"
"net"
"test/hello"
"google.golang.org/grpc"
)
func main() {
listenPort, err := net.Listen("tcp", ":19003")
if err != nil {
log.Fatal(err)
}
server := grpc.NewServer(
grpc.UnaryInterceptor(CustomInterceptor()),
)
hello.RegisterHelloServer(server, &Hello{})
server.Serve(listenPort)
}
type Hello struct{}
func (h *Hello) Hello(cts context.Context, message *hello.HelloMessage) (*hello.HelloResponse, error) {
res := hello.HelloResponse{Msg: fmt.Sprintf("hello %s", message.Name)}
return &res, nil
}
func CustomInterceptor() grpc.UnaryServerInterceptor {
return func(ctx context.Context, request interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) {
fmt.Printf("before process")
helloMessage, _ := request.(*hello.HelloMessage)
helloMessage.Name = fmt.Sprintf("<<< %s >>>", helloMessage.Name)
res, err := handler(ctx, request)
if err != nil {
return nil, err
}
fmt.Println("after process")
helloResponse, _ := res.(*hello.HelloResponse)
helloResponse.Msg = fmt.Sprintf("*** %s ***", helloResponse.Msg)
return res, nil
}
}
Discussion