読者ターゲット
- 株式会社viviONにちょっと興味ある
- golang ✕ gRPCで毎回Validateのロジック書いてる方
- gRPCちょっとわかるよって方
- protoちょっとわかるよって方
課題感
毎回golangのvalidateロジックを書くの、疲れませんか?
golangのValidationといえばPackage validatorだと思います。
(v10まで出てますし、老舗感ありますよね。)
gRPCのRPCに対して毎回個別のvalidator structを用意して、開発するのって結構しんどいんですよね。。。
jsonのお取り扱いだったらzodも似たように先にvalidator objを作って検証するんですけど、json書くのとstruct書くのって全然工数違ってくるんですよね。。。 (疲弊感)
解決しよう
折角protoファイル書いてるんだからスキーマ定義段階で事前にスキーマにカスタムパラメータを付与することで、回避できないか?
と考え始めました。
同じことを考えた先人たちは素晴らしいことに、既に用意してくれていました。
そのOSSはPGV (protoc-gen-validate)です。
(※Buf Technologies, Inc.の製品ばかりご紹介していますが回し者ではないです。)
例えば特定のstring型のスキーマを必須項目にしたい場合
min_len = 1
とすることにより、「最低1文字以上の文字列を入力する必要がある」となります。
その為、擬似的にrequired = true
とすることが可能になります。
syntax = "proto3";
package greet.v1;
option go_package = "example/gen/greet/v1;greetv1";
import "validate/validate.proto"; // ココ重要 ☆
message GreetRequest {
string name = 1 [(validate.rules).string.min_len = 1]; // ココ重要 ☆
}
message GreetResponse {
string greeting = 1;
}
service GreetService {
rpc Greet(GreetRequest) returns (GreetResponse) {}
}
packageをprotoに認識させる
公式Docにも書いてるんですが、若干わかりにくいので書いておきます。
Install
pathがenvoyproxyになっているのはまだ、go側がmodule pathの変更に時間がかかってるそうです ><
(※新しくpathを切っただけだと、旧と新の2つのmoduleが存在してしまう為だと思います。)
go get -d github.com/envoyproxy/protoc-gen-validate
Buf config
※ Bufについて知りたい方はこちら!!
version: v1
deps:
- buf.build/envoyproxy/protoc-gen-validate ## ココ重要 ☆
breaking:
use:
- FILE
lint:
use:
- DEFAULT
version: v1
plugins:
- plugin: go
out: gen
opt: paths=source_relative
- plugin: connect-go ## connect-goでも通常のgRPCでも実現できるのでconnect-goを使わない場合は不要です
out: gen
opt: paths=source_relative
- plugin: buf.build/bufbuild/validate-go ## ココ重要 ☆
out: gen
opt: paths=source_relative
buf generate
コマンドでvalidateメソッドが実装されたRPCのリクエスト structが生成されます。
ValidationをDRYにする
生成されたprotobufには既に.Validate()
メソッドが実装されたリクエスト structが生成されているので、各RPCで以下を書いてもいいのですが、記述量が少なくなったとはいえ毎回ロジックを書かなければいけない世界線からは開放されません。
if err := req.Validate(); err != nil {
毎回コードを書かずに自動Validationを行う方法
gRPCオフィシャルのValidator moduleを使用することで、リクエスト structに実装されている.Validate()
関数の存在チェックを行い勝手にCallしてくれます。
Interceptorで実装されている為、各RPCで記述しなくてもすべてのRPC Callに対して自動的にValidateをかけてくれるようになります。
※ connect-goでも独自にこんな風にカスタムInterceptorを実装することで、自動Validateが可能になります。
まとめ
第三部作で書いてきた「gRPCを取り巻く環境はどんどん進化していた」ですが、如何でしたでしょうか?
2,3年前にはなかった「これが欲しかった」がどんどん増えてきており、コミッター達には感謝してもしきれないです。
採用PR