Go?gRPC服務(wù)proto數(shù)據(jù)驗(yàn)證進(jìn)階教程
前言
上篇介紹了go-grpc-middleware的grpc_zap、grpc_auth和grpc_recovery使用,本篇將介紹grpc_validator,它可以對gRPC數(shù)據(jù)的輸入和輸出進(jìn)行驗(yàn)證。
創(chuàng)建proto文件,添加驗(yàn)證規(guī)則
這里使用第三方插件go-proto-validators自動(dòng)生成驗(yàn)證規(guī)則。
go get github.com/mwitkow/go-proto-validators
1.新建simple.proto文件
syntax = "proto3"; package proto; import "github.com/mwitkow/go-proto-validators/validator.proto"; message InnerMessage { // some_integer can only be in range (1, 100). int32 some_integer = 1 [(validator.field) = {int_gt: 0, int_lt: 100}]; // some_float can only be in range (0;1). double some_float = 2 [(validator.field) = {float_gte: 0, float_lte: 1}]; } message OuterMessage { // important_string must be a lowercase alpha-numeric of 5 to 30 characters (RE2 syntax). string important_string = 1 [(validator.field) = {regex: "^[a-z]{2,5}$"}]; // proto3 doesn't have `required`, the `msg_exist` enforces presence of InnerMessage. InnerMessage inner = 2 [(validator.field) = {msg_exists : true}]; } service Simple{ rpc Route (InnerMessage) returns (OuterMessage){}; }
代碼import "github.com/mwitkow/go-proto-validators/validator.proto",文件validator.proto需要import "google/protobuf/descriptor.proto";包,不然會(huì)報(bào)錯(cuò)。
google/protobuf地址:
https://github.com/protocolbuffers/protobuf/blob/main/src/google/protobuf/descriptor.proto
把src文件夾中的protobuf目錄下載到GOPATH目錄下。
2.編譯simple.proto文件
go get github.com/mwitkow/go-proto-validators/protoc-gen-govalidators
指令編譯:
protoc --govalidators_out=. --go_out=plugins=grpc:./ ./simple.proto
或者使用VSCode-proto3插件,第一篇有介紹。只需要添加"--govalidators_out=."即可。
// vscode-proto3插件配置 "protoc": { // protoc.exe所在目錄 "path": "C:\\Go\\bin\\protoc.exe", // 保存時(shí)自動(dòng)編譯 "compile_on_save": true, "options": [ // go編譯輸出指令 "--go_out=plugins=grpc:.", "--govalidators_out=." ] },
編譯完成后,自動(dòng)生成simple.pb.go和simple.validator.pb.go文件,simple.pb.go文件不再介紹,我們看下simple.validator.pb.go文件。
// Code generated by protoc-gen-gogo. DO NOT EDIT. // source: go-grpc-example/9-grpc_proto_validators/proto/simple.proto package proto import ( fmt "fmt" math "math" proto "github.com/golang/protobuf/proto" _ "github.com/mwitkow/go-proto-validators" regexp "regexp" github_com_mwitkow_go_proto_validators "github.com/mwitkow/go-proto-validators" ) // Reference imports to suppress errors if they are not otherwise used. var _ = proto.Marshal var _ = fmt.Errorf var _ = math.Inf func (this *InnerMessage) Validate() error { if !(this.SomeInteger > 0) { return github_com_mwitkow_go_proto_validators.FieldError("SomeInteger", fmt.Errorf(`value '%v' must be greater than '0'`, this.SomeInteger)) } if !(this.SomeInteger < 100) { return github_com_mwitkow_go_proto_validators.FieldError("SomeInteger", fmt.Errorf(`value '%v' must be less than '100'`, this.SomeInteger)) } if !(this.SomeFloat >= 0) { return github_com_mwitkow_go_proto_validators.FieldError("SomeFloat", fmt.Errorf(`value '%v' must be greater than or equal to '0'`, this.SomeFloat)) } if !(this.SomeFloat <= 1) { return github_com_mwitkow_go_proto_validators.FieldError("SomeFloat", fmt.Errorf(`value '%v' must be lower than or equal to '1'`, this.SomeFloat)) } return nil } var _regex_OuterMessage_ImportantString = regexp.MustCompile(`^[a-z]{2,5}$`) func (this *OuterMessage) Validate() error { if !_regex_OuterMessage_ImportantString.MatchString(this.ImportantString) { return github_com_mwitkow_go_proto_validators.FieldError("ImportantString", fmt.Errorf(`value '%v' must be a string conforming to regex "^[a-z]{2,5}$"`, this.ImportantString)) } if nil == this.Inner { return github_com_mwitkow_go_proto_validators.FieldError("Inner", fmt.Errorf("message must exist")) } if this.Inner != nil { if err := github_com_mwitkow_go_proto_validators.CallValidatorIfExists(this.Inner); err != nil { return github_com_mwitkow_go_proto_validators.FieldError("Inner", err) } } return nil }
里面自動(dòng)生成了message中屬性的驗(yàn)證規(guī)則。
把grpc_validator驗(yàn)證攔截器添加到服務(wù)端
grpcServer := grpc.NewServer(cred.TLSInterceptor(), grpc.StreamInterceptor(grpc_middleware.ChainStreamServer( grpc_validator.StreamServerInterceptor(), grpc_auth.StreamServerInterceptor(auth.AuthInterceptor), grpc_zap.StreamServerInterceptor(zap.ZapInterceptor()), grpc_recovery.StreamServerInterceptor(recovery.RecoveryInterceptor()), )), grpc.UnaryInterceptor(grpc_middleware.ChainUnaryServer( grpc_validator.UnaryServerInterceptor(), grpc_auth.UnaryServerInterceptor(auth.AuthInterceptor), grpc_zap.UnaryServerInterceptor(zap.ZapInterceptor()), grpc_recovery.UnaryServerInterceptor(recovery.RecoveryInterceptor()), )), )
運(yùn)行后,當(dāng)輸入數(shù)據(jù)驗(yàn)證失敗后,會(huì)有以下錯(cuò)誤返回
Call Route err: rpc error: code = InvalidArgument desc = invalid field SomeInteger: value '101' must be less than '100'
其他類型驗(yàn)證規(guī)則設(shè)置
enum驗(yàn)證
syntax = "proto3"; package proto; import "github.com/mwitkow/go-proto-validators/validator.proto"; message SomeMsg { Action do = 1 [(validator.field) = {is_in_enum : true}]; } enum Action { ALLOW = 0; DENY = 1; CHILL = 2; }
UUID驗(yàn)證
syntax = "proto3"; package proto; import "github.com/mwitkow/go-proto-validators/validator.proto"; message UUIDMsg { // user_id must be a valid version 4 UUID. string user_id = 1 [(validator.field) = {uuid_ver: 4, string_not_empty: true}]; }
總結(jié)
go-grpc-middleware中g(shù)rpc_validator集成go-proto-validators,我們只需要在編寫proto時(shí)設(shè)好驗(yàn)證規(guī)則,并把grpc_validator添加到gRPC服務(wù)端,就能完成gRPC的數(shù)據(jù)驗(yàn)證,很簡單也很方便。
教程源碼地址:https://github.com/Bingjian-Zhu/go-grpc-example
以上就是Go gRPC服務(wù)proto數(shù)據(jù)驗(yàn)證進(jìn)階教程的詳細(xì)內(nèi)容,更多關(guān)于Go gRPC服務(wù)proto數(shù)據(jù)驗(yàn)證的資料請關(guān)注腳本之家其它相關(guān)文章!
- golang通用的grpc?http基礎(chǔ)開發(fā)框架使用快速入門
- Go創(chuàng)建Grpc鏈接池實(shí)現(xiàn)過程詳解
- go?doudou開發(fā)gRPC服務(wù)快速上手實(shí)現(xiàn)詳解
- Golang?gRPC?HTTP協(xié)議轉(zhuǎn)換示例
- Go Grpc Gateway兼容HTTP協(xié)議文檔自動(dòng)生成網(wǎng)關(guān)
- Go?gRPC進(jìn)階教程gRPC轉(zhuǎn)換HTTP
- Go?gRPC服務(wù)進(jìn)階middleware使用教程
- Go?gRPC進(jìn)階教程服務(wù)超時(shí)設(shè)置
- Go語言與gRPC的完美結(jié)合實(shí)戰(zhàn)演練
相關(guān)文章
一文帶你了解Go語言標(biāo)準(zhǔn)庫strings的常用函數(shù)和方法
strings?庫包含了許多高效的字符串常用操作的函數(shù)和方法,巧用這些函數(shù)與方法,能極大的提高我們程序的性能。本文就來和大家分享一下Go標(biāo)準(zhǔn)庫strings的常用函數(shù)和方法,希望對大家有所幫助2022-11-11Go語言并發(fā)處理效率響應(yīng)能力及在現(xiàn)代軟件開發(fā)中的重要性
這篇文章主要為大家介紹了Go語言并發(fā)處理的效率及響應(yīng)能力以及在現(xiàn)代軟件開發(fā)中的重要性實(shí)例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-12-12golang動(dòng)態(tài)創(chuàng)建類的示例代碼
這篇文章主要介紹了golang動(dòng)態(tài)創(chuàng)建類的實(shí)例代碼,本文通過實(shí)例代碼給大家講解的非常詳細(xì),需要的朋友可以參考下2023-06-06

Golang實(shí)現(xiàn)微信公眾號后臺(tái)接入的示例代碼